Skip to content
Snippets Groups Projects
Select Git revision
  • 776ac91e01f038b2258cac38dd98c57026c03a67
  • main default
  • fixtests
  • dynamic-map-layers
  • 1.0.0
5 results

FetchData.js

Blame
  • FetchData.js 9.29 KiB
    
    /**
     *
     * @returns
     */
    export default async function Initialize(){
    
        // Astro Web Maps, has the tile base data for the map of each planetary body
        const astroWebMaps =
            "https://astrowebmaps.wr.usgs.gov/webmapatlas/Layers/maps.json";
    
        // STAC API, has footprint data for select planetary bodies
        const stacApiCollections =
            "https://stac.astrogeology.usgs.gov/api/collections";
    
        const vectorApiCollections =
            "https://astrogeology.usgs.gov/pygeoapi/collections";
    
        // Async tracking
        let fetchStatus = {};
        let fetchPromise = {};
        let jsonPromise = {};
    
        // Fetched Maps
        let mapsJson = {};
    
        // Combined Data
        let aggregateMapList = {};
    
        // Init
        fetchStatus[astroWebMaps] = "Not Started";
        fetchPromise[astroWebMaps] = "Not Started";
        jsonPromise[astroWebMaps] = "Not Started";
        mapsJson[astroWebMaps] = [];
    
        fetchStatus[stacApiCollections] = "Not Started";
        fetchPromise[stacApiCollections] = "Not Started";
        jsonPromise[stacApiCollections] = "Not Started";
        mapsJson[stacApiCollections] = [];
    
        fetchStatus[vectorApiCollections] = "Not Started";
        fetchPromise[vectorApiCollections] = "Not Started";
        jsonPromise[vectorApiCollections] = "Not Started";
        mapsJson[vectorApiCollections] = [];
    
        // Fetch JSON and read into object
        async function ensureFetched(targetUrl) {
            if(fetchStatus[targetUrl] === "Not Started")
            {
                fetchStatus[targetUrl] = "Started";
                fetchPromise[targetUrl] = fetch(
                  targetUrl
                ).then((res)=>{
                    jsonPromise[targetUrl] = res.json().then((jsonData)=>{
                        mapsJson[targetUrl] = jsonData;
                    }).catch((err)=>{
                        console.log(err);
                    });
                }).catch((err) => {
                    console.log(err);
                });
            }
            await fetchPromise[targetUrl];
            await jsonPromise[targetUrl];
        }
    
        // Combine data from Astro Web Maps and STAC API into one new object
        function organizeData(astroWebMaps, stacApiCollections, vectorApiCollections) {
    
            // Initialize Objects
            let mapList = { "systems" : [] };
            let stacList = [];
    
            // Check for Planets that have STAC footprints from the STAC API
            for (let i = 0; i < stacApiCollections.collections.length; i++) {
                let stacTarget = stacApiCollections.collections[i].summaries["ssys:targets"][0].toLowerCase();
    
                // pushes stacTarget onto the stacList if the target isn't already in the list
                if(!stacList.find(targetBody => targetBody == stacTarget)){
                    stacList.push(stacTarget.toLowerCase());
                }
            }
    
            // Scan through every target in the Astro Web Maps JSON
            for (const target of astroWebMaps.targets){
    
                // Check for, add system if system is not in array
                if (!mapList.systems.some(system => system.name === target.system)) {
                    mapList.systems.push({
                        "name" : target.system,
                        "naif" : 0,
                        "bodies" : []
                    })
                }
    
                // Index of System
                let sysIndex = mapList.systems.map(sys => sys.name).indexOf(target.system);
    
                // ID the system. This seems to get the main planet of the system.
                if (target.naif % 100 === 99){
                    mapList.systems[sysIndex].naif = target.naif;
                }
    
                // Check for/add body if not already incl
                if (!mapList.systems[sysIndex].bodies.some(body => body.name === target.name)) {
    
                    // A flag that indicates whether or not the body has footprints
                    let hasFootprints = stacList.includes(target.name.toLowerCase())
    
                    // Add STAC collections
                    let myCollections = []
                    if (hasFootprints) {
                        for (const collection of stacApiCollections.collections){
                            if (target.name == collection.summaries["ssys:targets"][0].toUpperCase()) {
                                // Add a specification to the title in order to show what kind of data the user is requesting
                                collection.title = collection.title.concat(" (Raster)")
                                myCollections.push(collection);
                            }
                        }
    
                        for (const pycollection of vectorApiCollections.collections){
                            // view the collection as GEOJSON
                            let target_name = pycollection.id.split('/')[0];
                            if (target.name == target_name.toUpperCase()) {
                                pycollection.links.find(link => link.rel === "items").href = "https://astrogeology.usgs.gov/pygeoapi" + pycollection.links.find(link => link.rel === "items").href;
                                // Add a specification to the title in order to show what kind of data the user is requesting
                                pycollection.title = pycollection.title.concat(" (Vector)");
                                myCollections.push(pycollection);
                            }
                        }
                    }
    
                    // Add a body data entry
                    mapList.systems[sysIndex].bodies.push({
                        "name" : target.name,
                        "naif" : target.naif,
                        "hasFootprints" : hasFootprints,
                        "layers" : {
                            "base" : [],
                            "overlays" : [],
                            "nomenclature" : []
                        },
                        "collections" : myCollections
                    })
                }
    
                // Index of Body
                let bodIndex = mapList.systems[sysIndex].bodies.map(bod => bod.name).indexOf(target.name);
    
                // Sort through AstroWebMaps to get the right ones for GeoSTAC
                function getWmsMaps(webMaps) {
                    let myLayers = {
                        "base" : [],
                        "overlays" : [],
                        "nomenclature" : [],
                        /* "wfs" : [] */
                    };
    
                    // Add maps
                    for (const wmap of webMaps) {
                        if(wmap.type === "WMS" && wmap.layer != "GENERIC") {
                            if(wmap.transparent == "false") {
                                // Non-transparent layers are base maps
                                myLayers.base.push(wmap);
                            } else if (wmap.layer == "NOMENCLATURE") {
                                // Feature Name Layers
                                myLayers.nomenclature.push(wmap);
                            } else {
                                // OthTransparent layers are overlays
                                myLayers.overlays.push(wmap);
                            }
                        }
                        // else if (wmap.type === "WFS") {
                        //     // Currently in AstroMap but doesn't seem to be used.
                        //     myLayers.wfs.push(wmap);
                        // }
                    }
                    return myLayers;
                }
    
                // Add base and overlay maps (but not empty arrays!)
                let myLayers = getWmsMaps(target.webmap);
                if (myLayers.base.length > 0){
                    mapList.systems[sysIndex].bodies[bodIndex].layers.base.push(...myLayers.base);
                }
                if (myLayers.nomenclature.length > 0){
                    mapList.systems[sysIndex].bodies[bodIndex].layers.nomenclature.push(...myLayers.nomenclature);
                }
                if (myLayers.overlays.length > 0){
                    mapList.systems[sysIndex].bodies[bodIndex].layers.overlays.push(...myLayers.overlays);
                }
            }
    
            // Sort systems by NAIF ID
            mapList.systems.sort((a, b)=>{return a.naif - b.naif})
    
            // Go through each System
            for (let sysIndex = 0; sysIndex < mapList.systems.length; sysIndex++){
    
                // Remove bodies with no base maps
                for (let bodIndex = mapList.systems[sysIndex].bodies.length - 1; bodIndex >= 0; bodIndex--){
                    if(mapList.systems[sysIndex].bodies[bodIndex].layers.base.length < 1){
                        mapList.systems[sysIndex].bodies.splice(bodIndex, 1);
                    }
                }
                // Sort targets by naif id
                mapList.systems[sysIndex].bodies.sort((a, b)=>{
                    let valA = a.naif;
                    let valB = b.naif;
                    if (a.naif % 100 == 99) valA = 0; // Planet IDs end with 99,
                    if (b.naif % 100 == 99) valB = 0; // but put them first.
                    return valA - valB;
                })
            }
    
            return mapList;
        }
    
        // Fetch and organize data from
        async function getStacAndAstroWebMapsData() {
            // Start fetching from AWM and STAC API concurrently
            ensureFetched(astroWebMaps);
            ensureFetched(stacApiCollections);
            ensureFetched(vectorApiCollections);
    
            // Wait for both to complete before moving on
            await ensureFetched(astroWebMaps);
            await ensureFetched(stacApiCollections);
            await ensureFetched(vectorApiCollections);
    
            return organizeData(mapsJson[astroWebMaps], mapsJson[stacApiCollections], mapsJson[vectorApiCollections]);
        }
    
        aggregateMapList = await getStacAndAstroWebMapsData();
        return { "aggregateMapList":aggregateMapList, "astroWebMaps":mapsJson[astroWebMaps] };
    }