How to use an API: fetch daily images with NASA's Open API
Tags: api, python, opensource, webdev
Published: 2020-10-02 20:29:08

#### An application-programming interface (API) is a set of instructions used to access a web application. Today, we'll use Python and NASA's Open API to create a program that fetches a daily astronomy image. 

*This article was written by Pratik Shukla as part of his astronomy games series.*

___

**Who doesn’t like those mesmerizing images of space!** 

National Aeronautics and Space Administration (NASA) provides amazing astronomical images through the Astronomy Picture of the Day service. In this tutorial, we are going to use NASA API and nasa.py library to fetch these images.

An application-programming interface (API) is a set of instructions and standards used to access a web application. APIs are a very useful tool that allow us to share information publicly. The best way to learn how to use APIs it is to program yourself.

Today, we will learn how to download and display the daily astronomical images. First, we are going to fetch today’s. image. Then, we’ll make a few changes to our code so that we automatically get an image of any date.

**Here is what we'll cover today:**
*  [Fetch an astronomy picture of the day using NASA's API](#api)
* [Get astronomy image based on date value](#date)
* [Downloading astronomy images for a range of dates](#range)
* [Wrapping up](#wrap-up)

<br>

<a name="api"></a>

## Fetch an astronomy picture of the day using NASA's API

In the following program. we are going to download today’s Astronomy Picture of the Day(APOD) using NASA's Open API. The program will download image files only. If there is no image file available for today’s date, it will simply print a message that says, "Image not available". 

If the image file is available, it will be downloaded on the local system. Then, our code will fetch the image from the local system and display it along with any extra information (i.e. title, url).

Next, our code will ask the user if they want to hear an audio explanation for the image. If the user chooses to hear the audio explanation, we will use the Google Text to Speech (GTTS) library to convert the text explanation to an audio file and play it.

> **Note:** To access the services provided by NASA, we need to have a registered api key. To get an api key, we simply have to [fill out a form](https://api.nasa.gov/) on the NASA API website. We can also use a `demo_key`.
>
> We can place 1000 requests per hour by registered api, and with `demo_key`, we can only place 50 requests per day. 
>
> After successful registration, you’ll get an api key in the mentioned email address. We’ll use this key later in this tutorial.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/koso3yprc2b2l4np1vwl.png)

<br>

### Python Implementation (5 Steps)

<br>

#### Step 1: Import required libraries

```py
#Import required libraries:
import nasapy
import os
from datetime import datetime
import urllib.request
from IPython.display import Image,display,Audio
from gtts import gTTS
```

* `nasapy`: We are going to use the nasapy library to access the information provided by NASA's API.
* `os`: To store the image in a particular directory, we use the os library.
* `datetime`: We use a date while sending a request to NASA API to access the information. To get a date in a specific format, we’ll use a datetime library.
* `urllib`: The image we get from NASA API will be in a form of a URL, so we use urllib to fetch it.
* `Ipython`: We need to display the image in a jupyter notebook using Ipython library. We will also play the audio explanation of the image using the audio module.
* `gtts`: We use Google Text to Speech library to convert the text explanation of the image into an audio file.

<br>

#### Step 2. Create an object of Nasa class

Here, we are going to create an object called `nasa`. We are using the `nasapy` library and our registered api key. We’ll use this object to call a method of the `Nasa` class to get the information on astronomical images.

```py
#Initialize Nasa class by creating an object:

k = "523p5hPYHGzafYGLCkqa54kKMTV2vbP0XcPxkcLm"
nasa = nasapy.Nasa(key = k)
```

<br>

#### Step 3. Get date in required format

Now to get an image for a specific date, we need to pass a date in a specific format. The required format for the date is `YYYY-MM-DD` using the `datetime.today()` function. So, we need to convert this tuple into a string using the `strftime(%Y-%m-%d)` function.

```py
#Get today's date in YYYY-MM-DD format:

d = datetime.today().strftime('%Y-%m-%d')
```

<br>

#### Step 4. Get information from NASA's API

Now that we have today’s date in the proper format, we can place a request for today’s astronomical image. Here we use the `picture_of_the_day()` method to get the image data.

```py
#Get the image data:

apod = nasa.picture_of_the_day(date=d, hd=True)
```

Our apod variable is a dictionary of various keys and values. Let’s take a look at the keys of this variable:

* `date`
* `title`
* `copyright`
* `explanation`
* `url`
* `hdurl`
* `media_type`
* `service_version`

<br>

#### Step 5. Displaying the image and other information

```py
#POINT A:
#Check the media type available:
if(apod["media_type"] == "image"):
    
    #POINT B:
    #Displaying hd images only:
    if("hdurl" in apod.keys()):
        
        #POINT C:
        #Saving name for image:
        title = d + "_" + apod["title"].replace(" ","_").replace(":","_") + ".jpg"
        
        #POINT D:
        #Path of the directory:
        image_dir = "./Astro_Images"

        #Checking if the directory already exists?
        dir_res = os.path.exists(image_dir)
 
        #If it doesn't exist then make a new directory:
        if (dir_res==False):
            os.makedirs(image_dir)

        #If it exist then print a statement:
        else:
            print("Directory already exists!\n")
        
        #POINT E:
        #Retrieving the image:
        urllib.request.urlretrieve(url = apod["hdurl"] , filename = os.path.join(image_dir,title))
        
        #POINT F:
        #Displaying information related to image:
        
        if("date" in apod.keys()):
            print("Date image released: ",apod["date"])
            print("\n")
        if("copyright" in apod.keys()):
            print("This image is owned by: ",apod["copyright"])
            print("\n")
        if("title" in apod.keys()):
            print("Title of the image: ",apod["title"])
            print("\n")
        if("explanation" in apod.keys()):
            print("Description for the image: ",apod["explanation"])
            print("\n")
        if("hdurl" in apod.keys()):
            print("URL for this image: ",apod["hdurl"])
            print("\n")
        
        #POINT G:
        #Displaying main image:
        display(Image(os.path.join(image_dir,title)))
        
        #Point H:
        #Text to Speech Conversion:
        #Take input from user:
        print("\n")
        choice = input("Press * to hear the audio explanation : ")

        if(choice=="*"):
            #Text to be converted:
            mytext = apod["explanation"]
            #mytext="Good Evening Pratik."

            #Creating an object:
            myobj = gTTS(text=mytext, lang="en", slow=False) 
            
            #Generating audio file name:
            audio_title = d + "_" + apod["title"] + ".mp3"
            
            #Save the converted file:
            myobj.save(os.path.join(image_dir,audio_title)) 

            #Name of sound file:
            sound_file = os.path.join(image_dir,audio_title)

            # Playing the converted file 
            display(Audio(sound_file, autoplay=True))
            
    

#POINT I:
#If media type is not image:
else:
    print("Sorry, Image not available!")
```

Now we will understand the code block by block.

**Displaying Images:**
* First of all, we are only going to display images. 
* Next, we are only interested in High Definition images. So if our image has Standard Definition then we are not entering the loop.
* Now, we have to maintain a certain kind of name structure to save the images. Here, we will use the date of the image followed by the title of the image followed by the extension of the image. 
* We also replace the colons and spaces with an underscore.

**Creating Directory:** 
* Now we must have a specific directory to store the images. We create a directory using the os library. To check whether the directory exists or not, we are using `.exist()` function. If the directory doesn’t exist, then we create it using `.makedirs()` function.
* Now we fetch the image using the url retrieved in apod variable. To fetch the image we are using the `urllib.request.urlretrieve()` function. 
* We also use `os.path.join()` to store the image in the newly created directory with a specified title name. 
* We use `apod[“hdurl”]` to download the image.

**Display other information:**
* Now that we have downloaded the image in a specific directory, we are going to display other related information to the image. We check if the specific information of the key exists or not. If the key exists, then we’ll display its value.
* Then we display the main image using the `Image()` function of the Ipython library.

**Audio Explanation:**
* Now that our image and other information is displayed, we’ll ask the user if they want to hear the explanation of the image or not. If the user presses `*`, we’ll use Google Text to Speech (`gtts`) library to convert the text into audio file. 
* We create an object that will take text to be converted, speed of speech and language as inputs. Then we store that information in specific directory with the  `.mp3` extension. 
* Then we use the `Audio()` function to play the audio file in our jupyter notebook.
* If the media type is not an image, we print a short message saying that "Image is not available".

> Please run the following Google Collaboratory file to view proper output. You can download and run this code file online on [Google Collaboratory](https://colab.research.google.com/drive/1sd1hIPRpWeGHv9zcDFSF4ZeQt9dKgnsa#scrollTo=xcR-iq6TPpPa).

<br>

<a name="date"></a>

## Get astronomy image based on date value

But what if the user wants to get an image for a **specific date**? It’s very simple! Instead of using today’s date, we’ll get the date from the user in the specified format and pass that as an argument. That is the only difference in the code. Check out the complete below. 


```py
#Import required libraries:
import nasapy
import os
from datetime import datetime
import urllib.request
from IPython.display import Image,display,Audio
from gtts import gTTS

#Initialize Nasa class by creating an object:
nasa = nasapy.Nasa(key="523p5hPYHGzafYGLCkqa54kKMTV2vbP0XcPxkcLm")

#Get today's date in YYYY-MM-DD format:
d = input("Enter date in YYYY-MM-DD format : ")

#Get the image data:
apod = nasa.picture_of_the_day(date=d, hd=True)

#POINT A:
#Check the media type available:
if(apod["media_type"] == "image"):
    
    #POINT B:
    #Displaying hd images only:
    if("hdurl" in apod.keys()):
        
        #POINT C:
        #Saving name for image:
        title = d + "_" + apod["title"].replace(" ","_").replace(":","_") + ".jpg"
        
        #POINT D:
        #Path of the directory:
        image_dir = "Astro_Images"

        #Checking if the directory already exists?
        dir_res = os.path.exists(image_dir)
 
        #If it doesn't exist then make a new directory:
        if (dir_res==False):
            os.makedirs(image_dir)

        #If it exist then print a statement:
        else:
            print("Directory already exists!\n")
        
        #POINT E:
        #Retrieving the image:
        urllib.request.urlretrieve(url = apod["hdurl"] , filename = os.path.join(image_dir,title))
        
        #POINT F:
        #Displaying information related to image:
        
        if("date" in apod.keys()):
            print("Date image released: ",apod["date"])
            print("\n")
        if("copyright" in apod.keys()):
            print("This image is owned by: ",apod["copyright"])
            print("\n")
        if("title" in apod.keys()):
            print("Title of the image: ",apod["title"])
            print("\n")
        if("explanation" in apod.keys()):
            print("Description for the image: ",apod["explanation"])
            print("\n")
        if("hdurl" in apod.keys()):
            print("URL for this image: ",apod["hdurl"])
            print("\n")
        
        #POINT G:
        #Displaying main image:
        display(Image(os.path.join(image_dir,title)))
        
        #Point H:
        #Text to Speech Conversion:
        #Take input from user:
        print("\n")
        choice = input("Press * to hear the audio explanation : ")

        if(choice=="*"):
            #Text to be converted:
            mytext = apod["explanation"]
            #mytext="Good Evening Pratik."

            #Creating an object:
            myobj = gTTS(text=mytext, lang="en", slow=False) 
            
            #Generating audio file name:
            audio_title = d + "_" + apod["title"] + ".mp3"
            
            #Save the converted file:
            myobj.save(os.path.join(image_dir,audio_title)) 

            #Name of sound file:
            sound_file = os.path.join(image_dir,audio_title)

            # Playing the converted file 
            display(Audio(sound_file, autoplay=True))
            
    

#POINT I:
#If media type is not image:
else:
    print("Sorry, Image not available!")
```

> Please run the following Google Collaboratory file to view proper output. You can download and run this code file online on [Google Collaboratory](https://colab.research.google.com/drive/1hXUEAIc3NWfiTEoHX2kjA3rDHMwOOS0W#scrollTo=Uhc0378DX8ZO).

<a name="range"></a>

## Downloading astronomy images for a range of dates

Now that we know how to download and display an image for a particular date, it’s time we push things a little further. We will download images for a **range of dates** and display a random image from our downloads. Let’s understand how we can achieve this below.

<br>

### Python Implementation (9 Steps)

<br>

#### Step 1: Import required libraries

These are the same libraries we used previously.

```py
These are the same libraries we used previously.
#Import required libraries:
import nasapy
import os
import pandas as pd
import urllib.request
from IPython.display import Image,display
```

<br>

####  Step 2: Creating an object of Nasa class

Here we are going to create an object called `nasa`. We are using the nasapy library and our registered api key. We’ll use this object to call a method of Nasa class to get the information on our astronomical images.


```py
#Initialize Nasa class by creating an object:

k = "523p5hPYHGzafYGLCkqa54kKMTV2vbP0XcPxkcLm"
nasa = nasapy.Nasa(key = k)
```

<br>

#### Step 3: Get a list of dates

We want to download more than one image for more than one date. So, we are going to use the `date_range()` function of the [pandas library](https://www.educative.io/blog/python-pandas-tutorial). This function will give us the list of dates in required format. Here, the period value determines the range of the list. 

We are going to download 5 images, but you can download as many as you want by adjusting the periods and end values.

```py
#Get a list of dates:
dates = pd.date_range(end = '2020-08-15', periods=5)
```

<br>

#### Step 4: Get the data

In the previous case, we only had one image. But here, we are going to download many images. To do so, we are creating an empty list to store all the values for all the images as a dictionary. 

First of all, we’ll take the date value and store it in the apod variable. Then we are going to get the required information as a dictionary and append it in the list.

```py
#Empty list to store dictionary keys and values:
data = []

#Getting all the data:
for d in dates:
    apod = nasa.picture_of_the_day(d, hd=True)
    
    if apod['media_type'] == 'image':
        if 'hdurl' in apod.keys():
            data.append({'date':apod['date'], 'title': apod['title'],'hdurl': apod['hdurl']})
```

<br>

#### Step 5: Set the location to store the images

Now we are going to create a directory to store images as we did previously.

```py
#Path of the directory:
image_dir = "AAA_Images_1"

#Checking if the directory already exists?
dir_res = os.path.exists(image_dir)
 
#If it doesn't exist then make a new directory:
if (dir_res==False):
    os.makedirs(image_dir)

#If it exist then print a statement:
else:
    print("Directory already exists!\n")  
```

<br>

#### Step 6: Downloading the images

Now that we have all the information of the image and directory, we are going to download the images. We use a `for loop` to loop through all the data in our list.

```py
#Retrieving the image:    
for img in data: 
    
    

    #Creating title for image:
    title = img["date"]+"_"+img["title"].replace(" ","_").replace(":","_")+".jpg"
    
    #Downloading the image:
    urllib.request.urlretrieve(img['hdurl'],
os.path.join(image_dir,title))
```

<br>

#### Step 7: Get a list of images

Now that we have downloaded all the images, it’s time to display them. There will be many images in the directory, so we can get a list of images using the following code.

```py
#Get a list of images:
astro_images = os.listdir(image_dir)
```

<br>

#### Step 8: Displaying an image
Now we can easily display an image using `Image()`. We are going to use `os.path.join()` to find the image location. Here we are going to display the *0th* image from the list of images available.

```py
#Displaying an image:
Image(os.path.join(image_dir, astro_images[0]))
```

<br>

#### Step 9: Displaying a random image from the list

We can use the random library of python to get a random image from the list of images available.

```py
#Get random image:
import random
Image(os.path.join(image_dir, astro_images[random.randint(0,len(astro_images)-1)]))
```

<br>

### Putting it all together

**Step 1:**

```py
#Import required libraries:
import nasapy
import os
import pandas as pd
import urllib.request
from IPython.display import Image,display

#Initialize Nasa class by creating an object:
k = "523p5hPYHGzafYGLCkqa54kKMTV2vbP0XcPxkcLm"
nasa = nasapy.Nasa(key = k)

#Get a list of dates:
dates = pd.date_range(end = '2020-08-15', periods=5)

#Empty list to store dictionary keys and values:
data = []

#Getting all the data:
for d in dates:
    apod = nasa.picture_of_the_day(d, hd=True)
    
    if apod['media_type'] == 'image':
        if 'hdurl' in apod.keys():
            data.append({'date':apod['date'], 'title': apod['title'],'hdurl': apod['hdurl']})
        

#Path of the directory:
image_dir = "AAA_Images_1"

#Checking if the directory already exists?
dir_res = os.path.exists(image_dir)
 
#If it doesn't exist then make a new directory:
if (dir_res==False):
    os.makedirs(image_dir)

#If it exist then print a statement:
else:
    print("Directory already exists!\n")       


#Retrieving the image:    
for img in data: 
    
    #Creating title for image:
    title = img["date"]+"_"+img["title"].replace(" ","_").replace(":","_")+".jpg"
    
    #Downloading the image:
    urllib.request.urlretrieve(img['hdurl'], os.path.join(image_dir,title))

#Get list of images:
astro_images = os.listdir(image_dir)
```

**Step 2:**

```py
#Displaying an image:
Image(os.path.join(image_dir, astro_images[0]))
```

**Step 3:**

```py
#Get random image:
import random
Image(os.path.join(image_dir, astro_images[random.randint(0,len(astro_images)-1)]))
```


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cs48x5udbmjndwoabebn.png)

> Please run the following Google Collaboratory file to view proper output. You can download and run this code file online on [Google Collaboratory](https://colab.research.google.com/drive/1sBbtDnPxs8sNckbsoCK0W43R4ACkX3vl#scrollTo=9BNjIKNbLYuH).

<br>

<a name="wrap-up"></a>

## Wrapping up

Congratulations of completing this fun activity with NASA's API and Python. I hope this activity taught you some new things you can do with Python and inspired you to keep learning. 

In the next part of this tutorial, we’ll see how we can send the downloaded images from email. 

To download all the jupyter notebooks used in this tutorial, [click here](https://drive.google.com/drive/folders/1WgcmtSouN6QSfdcH5lCLhpOPbIVoqNKl?usp=sharing). If you have any doubts, questions, or thoughts regarding this article, feel free to contact me at shuklapratik22@gmail.com


If you want to continue learning abut APIs and want to take these skills to the next level, check out Educative's course **[Learn REST and SOAP API Test Automation in Java](https://www.educative.io/courses/learn-rest-soap-api-test-automation-java)**. You will learn how to perform REST and SOAP API test automation and learn how to write APIs and integration tests from scratch. 

*Happy learning!*

<br>

### Continue reading about Python and APIs
* [Level up your Python skills with these 6 challenges
](https://www.educative.io/blog/level-up-python-skills)
* [Java 8 Tutorial: master stream API and beyond
](https://www.educative.io/blog/master-stream-api-and-beyond)
* [Master Algorithms with Python for Coding Interviews
](https://www.educative.io/blog/python-algorithms-coding-interview)