diff --git a/docs/environment.yml b/docs/environment.yml index e5128ed39..42892d354 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -7,9 +7,11 @@ dependencies: - matplotlib==3.7.1 - pip>=20.1 - sphinx==7 + - folium - pip: - sympy - sphinx_book_theme==1.1.0rc1 - sphinx-design==0.5.0 - sphinxcontrib-bibtex - sphinx-copybutton + - pillow diff --git a/docs/source/conf.py b/docs/source/conf.py index 04deba793..bee1b3009 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -14,6 +14,23 @@ sys.path.insert(0, os.path.abspath("../..")) + +# Generate the map + +# Add the directory containing your Python script to the Python path +sys.path.insert(0, os.path.abspath(".")) + +import map + +m = map.generate_map() +current_dir = os.path.dirname(__file__) +html_path = os.path.join(current_dir, "_static", "map.html") + +# create _static directory if it doesn't exist +os.makedirs(os.path.dirname(html_path), exist_ok=True) + +m.save(html_path) + # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information diff --git a/docs/source/index.rst b/docs/source/index.rst index a9dde2011..423e5240a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -23,6 +23,19 @@ For more information, feel free to ask questions on the `FESTIM Discourse Page < "`FESTIM: An open-source code for hydrogen transport simulations. International Journal of Hydrogen Energy 63 (2024): 786-802. `_", +Map of FESTIM users +------------------- + +.. raw:: html + + + + +.. admonition:: Add your institution + + If you would like your institution to be added to this map, please `open an issue `_. + + -------- Contents -------- @@ -36,5 +49,4 @@ Contents userguide/index devguide/index api/festim - publications - + publications \ No newline at end of file diff --git a/docs/source/map.json b/docs/source/map.json new file mode 100644 index 000000000..c21491597 --- /dev/null +++ b/docs/source/map.json @@ -0,0 +1,285 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 5.7843, + 43.7254 + ] + }, + "properties": { + "name": "IRFM cadarache France", + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/LOGO_CEA_ORIGINAL.svg/768px-LOGO_CEA_ORIGINAL.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 2.3458, + 48.9583 + ] + }, + "properties": { + "name": "LSPM Villetaneuse France", + "url": "https://upload.wikimedia.org/wikipedia/en/thumb/2/2c/CNRS.svg/316px-CNRS.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -71.0921, + 42.3601 + ] + }, + "properties": { + "name": "MIT Cambridge, MA USA", + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/MIT_logo.svg/321px-MIT_logo.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -74.6596903, + 40.35006468849364 + ] + }, + "properties": { + "name": "Thea Energy USA", + "url": "https://media.licdn.com/dms/image/sync/D4E27AQEtSPdhh29Xiw/articleshare-shrink_800/0/1711995007077?e=1714071600&v=beta&t=l2mnifsctT8XWseYQSfPIyzRpwsAYVgq5j-FOWejeyY" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -71.6152, + 42.5406 + ] + }, + "properties": { + "name": "Commonwealth Fusion Systems Devens, MA USA", + "url": "https://api-kla-prod.2ambh.com/v1/images/10348/thumb/w950" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -89.4012, + 43.0761 + ] + }, + "properties": { + "name": "University Wisconsin Madison USA", + "url": "https://brand.wisc.edu/content/uploads/2023/09/vert-w-crest-logo-web-digital-color.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -122.41135340346865, + 37.77479335835942 + ] + }, + "properties": { + "name": "Marathon Fusion USA", + "url": "https://media.licdn.com/dms/image/D560BAQFyuUtXrkDBGg/company-logo_200_200/0/1707489994810/marathon_fusion_logo?e=1721865600&v=beta&t=HoM15_eB3GxED9wJ_21j057IVLQaFfU--iGjbBOpK4U" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -117.1611, + 32.7157 + ] + }, + "properties": { + "name": "University San Diego", + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Seal_of_the_University_of_California%2C_San_Diego.svg/1920px-Seal_of_the_University_of_California%2C_San_Diego.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 37.6649462235042, + 55.66362336404334 + ] + }, + "properties": { + "name": "MEPhI moscow Russia", + "url": "https://cdn.freelogovectors.net/wp-content/uploads/2021/04/national-research-nuclear-university-logo-freelogovectors.net_.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 5.0266, + 43.5455 + ] + }, + "properties": { + "name": "ITER organization France", + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/ITER_Logo_NoonYellow.svg/500px-ITER_Logo_NoonYellow.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -1.229138717146069, + 51.65868576158049 + ] + }, + "properties": { + "name": "UKAEA UK", + "url": "https://upload.wikimedia.org/wikipedia/en/thumb/9/95/UK_Atomic_Energy_Authority_logo.svg/1920px-UK_Atomic_Energy_Authority_logo.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -3.530686738097156, + 50.719235968686455 + ] + }, + "properties": { + "name": "digiLab UK", + "url": "https://creativedestructionlab.com/wp-content/uploads/2023/05/digilab-logo.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -0.4269, + 52.0720 + ] + }, + "properties": { + "name": "cranfield University UK", + "url": "https://resiliencefirst.org/sites/default/files/2022-02/cranfield-university-vector-logo-small.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 7.6818, + 45.0703 + ] + }, + "properties": { + "name": "Politecnico di Torino", + "url": "https://upload.wikimedia.org/wikipedia/it/thumb/4/47/Logo_PoliTo_dal_2021_blu.png/2880px-Logo_PoliTo_dal_2021_blu.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 116.3056, + 39.9923 + ] + }, + "properties": { + "name": "University of Beijing", + "url": "https://upload.wikimedia.org/wikipedia/en/thumb/f/f4/Beihang_University_logo.svg/1920px-Beihang_University_logo.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 117.2703, + 31.8669 + ] + }, + "properties": { + "name": "University of Hefei China", + "url": "https://media.licdn.com/dms/image/C510BAQFbUnIQqa62aA/company-logo_200_200/0/1630599485875/caships_logo?e=1721865600&v=beta&t=wKPCqctsafbewtZpD0Mk1snTab681zYrQaRoSTSZzBI" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 14.487728061376515, + 46.043586411058726 + ] + }, + "properties": { + "name": "Institut Jožef Stefan", + "url": "https://www.concordia-h2020.eu/wp-content/uploads/2019/02/IJS_logo.jpg" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 139.76446527724698, + 35.68673663876397 + ] + }, + "properties": { + "name": "Kyoto Fusioneering", + "url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEBUXW9DSGrDVhY80Fr6--hOywnBUnAwsb4ZTc9_2liw&s" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 12.455144726473035, + 41.818823289415484 + ] + }, + "properties": { + "name": "ENI", + "url": "https://upload.wikimedia.org/wikipedia/en/thumb/b/b2/Eni_new_logo.svg/320px-Eni_new_logo.svg.png" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 12.670768074076161, + 41.83511773016589 + ] + }, + "properties": { + "name": "ENEA", + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/ENEA_logo.svg/358px-ENEA_logo.svg.png" + } + } + ] +} \ No newline at end of file diff --git a/docs/source/map.py b/docs/source/map.py new file mode 100644 index 000000000..791137390 --- /dev/null +++ b/docs/source/map.py @@ -0,0 +1,73 @@ +import json +from folium.plugins import MarkerCluster +import folium + +import requests +from PIL import Image +from io import BytesIO + +LOGO_HEIGHT = 80 + + +def get_image_dimensions_from_url(image_url): + """Function to get the dimensions of an image from URL + + + Args: + image_url (str): the url + + Returns: + tuple: the dimensions of the image + """ + headers = { + "User-Agent": "FESTIM (https://github.com/festim-dev/festim; remidm@mit.edu)" + } + + try: + response = requests.get(image_url, headers=headers) + response.raise_for_status() # Raise an exception for HTTP errors + img = Image.open(BytesIO(response.content)) + return img.size + except Exception as e: + print(f"Error fetching or processing image: {e}") + return None + + +def generate_map(): + # Load GeoJSON data + with open("map.json") as f: + data = json.load(f) + + # Create a map centered on a specific location + m = folium.Map( + location=[42.256349987281666, -37.61204625889672], + zoom_start=3, + tiles="cartodbpositron", + ) + + marker_cluster = MarkerCluster().add_to(m) + # Iterate over features in the GeoJSON data + for feature in data["features"]: + name = feature["properties"]["name"] + url = feature["properties"]["url"] + if url == "URL_PLACEHOLDER": + url = "https://upload.wikimedia.org/wikipedia/commons/9/92/LOGO_CEA_ORIGINAL.svg" + coordinates = feature["geometry"]["coordinates"] + + # Get the dimensions of the image from URL + image_dimensions = get_image_dimensions_from_url(url) + if image_dimensions: + height_to_width_ratio = image_dimensions[1] / image_dimensions[0] + image_dimensions = (int(LOGO_HEIGHT / height_to_width_ratio), LOGO_HEIGHT) + else: + image_dimensions = (LOGO_HEIGHT, LOGO_HEIGHT) + # Create a marker with a custom icon and popup + if coordinates != [0, 0]: + icon = folium.CustomIcon(url, icon_size=image_dimensions) + folium.Marker( + location=[coordinates[1], coordinates[0]], + icon=icon, + ).add_to(marker_cluster) + else: + print("no coordinates for", name) + return m