cds-astro / aladin-lite

An astronomical HiPS visualizer in the browser
https://aladin.cds.unistra.fr/AladinLite/
GNU General Public License v3.0
102 stars 41 forks source link

Displaying a HiPS from local hard drive #103

Closed imbasimba closed 1 month ago

imbasimba commented 1 year ago

I would like to be able to display HiPS from my hard drive, i.e. not through http.

A folder can be marked as readable through the standard browser "upload" feature.

bmatthieu3 commented 1 year ago

Hi @imbasimba ,

I would like to have more info about that "upload" browser feature. From my search, I could not find a way to access the path of a selected directory via the browser filedialog. It is possible to access one file and convert it into an url (i.e. loading a local fits file works) but in the case of a local hips, I need the root directory path. Still it is possible to directly put the path in a script if you know it

let aladin;
A.init.then(() => {
    aladin = A.aladin('#aladin-lite-div', {target: 'galactic center'});
    let survey = aladin.createImageSurvey('HiPS gaia', "Gaia eDR3 density map survey", <relative path to the HiPS root dir>, undefined, undefined, {colormap:"viridis"});
    aladin.setBaseImageLayer(survey);
});

but using the File/Directory dialog to get the path seems complicated. Only File objects inside the selected folder are returned but without their path.

It seems to be a feature to pick a directory using https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker but that feature is only supported by chrome and edge.

simontorres commented 1 year ago

I was able to deploy. a GAIADR3 server on a Linux Machine, it is quite simple once you know what to do. If you are interested I can provide instructions how I did it.

bmatthieu3 commented 3 months ago

See this example for running a local hips stored on the drive disk: https://github.com/cds-astro/aladin-lite/blob/master/examples/al-hips-local.html

pmatsson commented 2 months ago

Hi @bmatthieu3! I'm sorry for not getting back to you sooner. We want to display HiPS uploaded from the client's computer with the HiPS files stored in memory.

The user can select a directory (using webkitdirectory on the input) and the uploaded files will all be provided as a FileList. There was previously a getTileURL function where we would retrieve the correct tile and encode it to an in-memory URL with createObjectURL. Something like this:

for(var i = 0; i < this.localFiles.length; i++){
    if(this.localFiles[i].webkitRelativePath.includes("Norder" + norder)){
        if(this.localFiles[i].webkitRelativePath.includes("Npix" + npix + "." +  this.imgFormat )){
            if(!this.localUrls[norder]){
                this.localUrls[norder] = {};
            }
            this.localUrls[norder][npix] = URL.createObjectURL(this.localFiles[i]);
            return this.localUrls[norder][npix];
        }
    }
}

Is this something you think would be possible to implement?

tboch commented 2 months ago

Hi @pmatsson . As this is something you implemented in ESA Sky with Aladin Lite v2, would you mind sharing your code to add this feature?

pmatsson commented 2 months ago

Hi @tboch.

The user uploads the directory using regular input with webkitdirectory. The files are then stored in memory like so:

HpxImageSurvey.prototype.setLocalFiles = function(files) {
    this.localFiles = files;
    this.localUrls = {};
}

We then changed the getTileURL function like so:

HpxImageSurvey.prototype.getTileURL = function(norder, npix) {
    var dirIdx = Math.floor(npix / 10000) * 10000;

    // Altered code
    if(this.localFiles){
        if(this.localUrls[norder] && this.localUrls[norder][npix]){
            return this.localUrls[norder][npix];
        } else{
            for(var i = 0; i < this.localFiles.length; i++){
                if(this.localFiles[i].webkitRelativePath.includes("Norder" + norder)){
                    if(this.localFiles[i].webkitRelativePath.includes("Npix" + npix + "." +  this.imgFormat )){
                        if(!this.localUrls[norder]){
                            this.localUrls[norder] = {};
                        }

                        this.localUrls[norder][npix] = URL.createObjectURL(this.localFiles[i]);
                        return this.localUrls[norder][npix];
                    }
                }
            }
        }

        return "";
    }
    // Original code
    else { 
        return this.rootUrl + "/" + "Norder" + norder + "/Dir" + dirIdx + "/Npix" + npix + "." + this.imgFormat + (this.additionalParams ? ('?' + this.additionalParams) : '');;
    }
};

We also modify retrieveAllskyTextures

HpxImageSurvey.prototype.retrieveAllskyTextures = function() {
    ....
    ....
    // Altered code
    if(this.localFiles){
        for(var i = 0; i < this.localFiles.length; i++){
            if(this.localFiles[i].webkitRelativePath.includes("/Norder3/Allsky." + this.imgFormat)){
                img.src = URL.createObjectURL(this.localFiles[i]);
            }
        }
    }
    // Original code
    else {
        img.src = this.rootUrl + '/Norder3/Allsky.' + this.imgFormat + (this.additionalParams ? ('?' + this.additionalParams) : '');
    }
};

These are all the changes we made to Aladin Lite v2 to make this work.

bmatthieu3 commented 2 months ago

hi @pmatsson - Would it be ok for you to use createImageSurvey with the 'url' params being either:

pmatsson commented 2 months ago

a javascript object[norder][npix] = 'your url pointing towards the tile' (new) You will have to process your file path array into that object

Yes, this would be great!

bmatthieu3 commented 1 month ago

Hi @pmatsson,

There is a new beta out where it is possible to give a FileList to createImageSurvey as the url param: https://cds-astro.github.io/aladin-lite/Aladin.html#createImageSurvey

pmatsson commented 1 month ago

@bmatthieu3 I can confirm that it is working great. Many thanks!

bmatthieu3 commented 1 month ago

@pmatsson - There are in fact several fixes that need to be done. Those should be ready for the next release. Good that this work for your use cases.