AttributeError: 'str' object has no attribute 'content'

Thiago Bueno Dalpiaz
  • 2
  • 3 Feb '23

Hi there,

I'm trying to generate mock stellar images of TNG50 subhalos. Despite using task 10 code, with few adaptations, from https://www.tng-project.org/data/docs/api/, it stills give AttributeError: 'str' object has no attribute 'content', as in an API as in JupyterLab.

import requests
import h5py
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from io import BytesIO

def get(path, params=None):
    # make HTTP GET request to path
    r = requests.get(path, params=params, headers=headers)

    # raise exception if response code is not HTTP SUCCESS (200)
    r.raise_for_status()

    if r.headers['content-type'] == 'application/json':
        return r.json() # parse json responses automatically

    if 'content-disposition' in r.headers:
        filename = r.headers['content-disposition'].split("filename=")[1]
        with open(filename, 'wb') as f:
            f.write(r.content)
        return filename # return the filename string

    return r

ids = [455291, 597792]
sub_count = 1
plt.figure(figsize=[15,3])

for id in ids:
    url = "http://www.tng-project.org/api/TNG50-1/snapshots/96/subhalos/" + str(id)
    sub = get(url)
    # it is of course possible this data product does not exist for all requested subhalos
    if 'skirt_images' in sub['supplementary_data']:
        print (sub["id"])
        # download PNG image, the version which includes all stars in the FoF halo (try replacing 'fof' with 'gz')
        png_url = sub['supplementary_data']['skirt_images']['fits_xy_kids']
        response = get(png_url)

        # make plot a bit nicer
        plt.subplot(1,len(ids),sub_count)
        plt.text(0,-20,"ID="+str(id),color='blue')
        plt.gca().axes.get_xaxis().set_ticks([])
        plt.gca().axes.get_yaxis().set_ticks([])
        sub_count += 1

        # plot the PNG binary data directly, without actually saving a .png file
        file_object = BytesIO(response.content)
        plt.imshow(mpimg.imread(file_object))

The error appears in the "file_object" line, 25.

Kind regards,
Thiago

Dylan Nelson
  • 3 Feb '23

Looks like exactly the same problem as in this thread (using a version of get() which isn't the real one).

Thiago Bueno Dalpiaz
  • 1
  • 5 Feb '23

It kind of worked, but now I have a different error message:

<Response [200]>

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-cda64e820566> in <module>
     25         file_object = BytesIO(response.content)
     26         print(response)
---> 27         plt.imshow(mpimg.imread(file_object))

/opt/conda/lib/python3.6/site-packages/matplotlib/image.py in imread(fname, format)
   1377                 return handler(fd)
   1378     else:
-> 1379         return handler(fname)
   1380 
   1381 

ValueError: invalid PNG header

It looks like in the other thread the problem was solved after deleting "if 'content-disposition'" from get(), which I also did. Now the problem appears to be at imread() function. I looked into its matplotlib documentation, but found nothing helpful to solve the issue.

Dylan Nelson
  • 5 Feb '23

The 'fits_xy_kids' indicates you are requesting a FITS file, not an image (PNG) file.

  • Page 1 of 1