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

Ephemerides Path #6

Closed
craigjarman opened this issue Dec 9, 2022 · 20 comments
Closed

Ephemerides Path #6

craigjarman opened this issue Dec 9, 2022 · 20 comments
Labels
bug Something isn't working

Comments

@craigjarman
Copy link

craigjarman commented Dec 9, 2022

Hi,
I looking for some guidance re where to place the Swiss ephemerides files so as to prevent the following error.

Exception: SwissEph file 'seas_18.se1' not found in PATH '.:/users/ephe2/:/users/ephe/')

I have tried to adding the file to an 'assets' directory and setting the path:

sweph.swe_set_ephe_path("/assets");

Thanks

@vm75
Copy link
Owner

vm75 commented Dec 10, 2022

Hi Craig,
Thanks for logging this. I believe you want to refer to some assets you are including in your app.
One option I am using is to extract the assets to some folder in user's home directory, for example, in Linux it could be inside ~/.config or in Windows it could be in %LOCALAPPDATA%, and then provide that path for swe_set_ephe_path.
I am doing something similar in method '_initFiles' in sweph_wrapper.dart.
I am not an expert in flutter, but my understanding was that flutter assets were not accessible via paths. But I may be wrong and would be happy to learn how :)

@vm75
Copy link
Owner

vm75 commented Dec 10, 2022

Looking at your example again, I may have misunderstood your question. If possible, could you please share a minimal example with the error and repro steps?
Thanks

@vm75
Copy link
Owner

vm75 commented Dec 10, 2022

And platform as well. I presently do not have any Apple platform to test/debug

@craigjarman
Copy link
Author

Hi,
If looking to the position of sat Chiron, the ephemeris file seas18_.se1 is required.

The euro is that the file cannot be found in the path.

How to se the path, and include the file is not part of the example. That is the challenge.

I'm on Mac/iOS.

I can try editing the puligin code.

Thanks

Craig

///Users/. ******. /Library/Application Support/sweph/2.10.03/'

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022

How are you accessing the position of Chiron?

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022

Do you want to package seas_18.se1 with your app as an asset?

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022

I think this is a bug. I have to update the init

@craigjarman
Copy link
Author

craigjarman commented Dec 11, 2022

How are you accessing the position of Chiron?

I have included the additional seas_18.se1 file in the _initFiles (see below);

I noticed the files have to be copied across, with each initialisation.

Ideally this could be established from the start (so no need to copy files over). Or done once only.

Possibly the files could be included in the app directory (from the main app or plugin), so there I not need to se the path.

So either:

  1. Revise the init (and load files each time the Swiss Ephemeris is used).
  2. Place the files where they're expected to be found by path (no need to call 'await init')
  3. Include as assets and point the path to the same directory (if that is allowed/possible). Relative to "application path"
  4. Place the files alongside the C-code

Also init is setting the path, so not sure where sweph.swe_set_ephe_path(""xxx) I to be used.

Is initFiles meant to be called only once? And then sweph.swe_set_ephe_path after that?

Just some suggestions.

Craig

Future<void> _initFiles() async {
    final appDir = await getApplicationSupportDirectory();

    String path = '${appDir.path}/sweph/${swe_version()}';

    await Directory(path).create(recursive: true);

    final files = {
      'ast_list.txt': 'seasnam.txt',
      'sefstars.txt': 'sefstars.txt',
      'seleapsec.txt': 'seleapsec.txt',
      'seas_18.se1': 'seas_18.se1',
    };

    for (final entry in files.entries) {
      final src = 'packages/sweph/native/sweph/src/${entry.key}';
      final dst = File('$path/${entry.value}');
      if (await dst.exists()) {
        continue;
      }
      try {
        final data = await rootBundle.load(src);
        await dst.writeAsBytes(
            data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
      } catch (e) {
        /// ignore
      }
    }

    await swe_set_ephe_path(path);
  }

@craigjarman
Copy link
Author

Also, once the files have been copied across (as above, the first init), I find there is no need to set the path. So no await prefix required.

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022

First of all, really appreciate your looking into this.
I realized the issue. swe_set_ephe_path inits the folder and should be called once during the init.
I am changing the init sequence accordingly.
Hopefully, it should solve the problem.

@craigjarman
Copy link
Author

Thanks - Happy to help. You'e done all the hard work with the FFI interface.

Setting the path does not appear to be necessary.

The C-code will look in this directory (/sweph/${swe_version()}') anyway it seems, without the init or setPath.

Possibly the path is set elsewhere.

The key dependency is for the files to have been copied across.

C

@craigjarman
Copy link
Author

Do you want to package seas_18.se1 with your app as an asset?

seas_18.se1 is the main extra and is required for Chiron and the four main asteroids plus others.

Along with seas_18.se1, I also use se00010s.se1, s136108s.se1, se07066s.se1, se20000s.se1, s225088s.se1, s136472s.se1, se50000s.se1, se28978s.se1, se90482s.se1, se00005s.se1, se00433s.se1, se90377s.se1, s136199s.se1, seplm18.se1, sepl_18.se1, semom18.se1, semo_18.se1, seasm18.se1

Being able to reference and include via the main app yaml/assets directive would be ideal.

I don't know if this is easily achieved however, as there may be restrictions as to what directories the c-code is allowed to access. See https://pub.dev/packages/path_provider

The temporary, Application Support and Documents directories might be accessible.

I presume you've hit this issue, and that is why you copy the files on init.....

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022

I think I have fixed the issue. The init sequence is different from before so will need some code change.
I have also added an example with a packaged file.
Hopefully it will work on Apple as well.
You may close this issue if it is fixed :)

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022

I had to do breaking changes to the init. Should have realized that Sweph init is very rigid.

@vm75 vm75 added the bug Something isn't working label Dec 11, 2022
@craigjarman
Copy link
Author

craigjarman commented Dec 11, 2022

This is a breaking change for me.
I can no longer call final sweph = Sweph() to get a standard instance and used for subsequent sync calls.
So will need to stick with version 2.10.3+1 plus the work around to manually include the added Ephemeris files.
I've a 'planetary clock' that shows the planetary position every 1 second, so an async call that copies the files each time becomes an expensive call.
The only need of async processing is for the file copying, but this only needs doing once.

@vm75
Copy link
Owner

vm75 commented Dec 11, 2022 via email

@craigjarman
Copy link
Author

craigjarman commented Dec 12, 2022

Hi,

Here is an example of how I call the SwissHelper. No await call required...

This approach does require that the initFiles() to have been run once previously by the app, just to copy the files over.

Maybe this functionality could be moved to a setup() function.

C

class _NowViewState extends State<NowView> {
   DateTime now = DateTime.now().toUtc();
   List<Placement> _placements = SwissHelper.getPlacements(now.year, now.month, now.day, now.hour, now.minute, now.second);

//.......

}
class SwissHelper {
 
   static List<Placement> getPlacements(
      int year, int month, int day, int hour, int minutes, int seconds) {
    final sweph = Sweph().

    double jd = sweph.swe_julday(year, month, day,
        (hour + minutes / 60 + seconds / 3600), CalendarType.SE_GREG_CAL);

    List<Placement> placements = <Placement>[];

List<HeavenlyBody> heavenlyBodys = SwissHelper.getHeavenlyBodys();

    for (var i = 0; i < heavenlyBodys.length; i++) {
      CoordinatesWithSpeed coordinatesWithSpeed =
          sweph.swe_calc_ut(jd, heavenlyBodys[i], SwephFlag.SEFLG_SWIEPH);

      PlacementPosition placementPosition = PlacementPosition();
      placementPosition.distance = coordinatesWithSpeed.distance;
      placementPosition.distanceSpeed = coordinatesWithSpeed.speedInDistance;
      placementPosition.longitude = coordinatesWithSpeed.longitude;
      placementPosition.longitudeSpeed = coordinatesWithSpeed.speedInLongitude;
      placementPosition.latitude = coordinatesWithSpeed.latitude;
      placementPosition.latitudeSpeed = coordinatesWithSpeed.speedInLatitude;

      placements.add(Placement(heavenlyBodys[i], placementPosition));
    }
    return placements;
  }

 static List<HeavenlyBody> getHeavenlyBodys() {
    List<HeavenlyBody> heavenlyBodys = <HeavenlyBody>[];
    heavenlyBodys.add(HeavenlyBody.SE_SUN);
    heavenlyBodys.add(HeavenlyBody.SE_MOON);
    heavenlyBodys.add(HeavenlyBody.SE_CHIRON);
    return heavenlyBodys;
  } 
}

@vm75
Copy link
Owner

vm75 commented Dec 12, 2022

ok, thanks.
I have reverted my recent changes and made it all simple.
Now it should all work in sync mode, unless one needs to use the packaged files, in which case they will have to wait for the async method useDefaultEpheFiles. It should be a no-op if files are already present
Do let me know if it works for you.

@vm75 vm75 closed this as completed Dec 12, 2022
@craigjarman
Copy link
Author

OK - I will test for iOS and let you know.
Thanks again.

@craigjarman
Copy link
Author

Hi

Just tested now. The

await ResourceUtils.extractAssets( 'assets/files/seas_18.se1', 'assets/ephe/seas_18.se1');

fails with the following error.

Exception has occurred.
FileSystemException (FileSystemException: Creation failed, path = 'assets' (OS Error: Read-only file system, errno = 30))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants