Changing DataLoader to include a FITS class

username: spacemeerkat
cooked: <p>I’m wondering if there’s a way to alter the torch.utils.data.DataLoader so that one could import FITS files into Pytorch as tensors with labels?</p>
<p>I’m intending to load in Astronomical images from FITS format (<a href="http://docs.astropy.org/en/stable/index.html" rel="nofollow noopener">http://docs.astropy.org/en/stable/index.html</a>) and presumably in the source code for DataLoader there must be some function for handling different data types such as: .jpg, .png etc.</p>
<p>Perhaps if there’s no simple clause for directly importing FITS files, I could be pointed towards that function and I can insert my own FITS handler clause?</p>
<p>Given that my code looks as follows when importing the training set:</p>
<pre><code class="lang-auto">trainset = dset.ImageFolder(root="/Documents/Image_data",transform=transform)
train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,shuffle=True)
</code></pre>
<p>…and I haven’t been able to find the data type handling functions in the source code for torch.utils.data.DataLoader or torch.utils.data.Dataset, maybe someone could point me in the right direction?</p>
<p>Many thanks in advance!</p>

username: spacemeerkat
cooked: <p>Update, I believe I may be able to make this work if using <code>torchvision.datasets.DatasetFolder</code> and setting my own loader for FITS extensions.</p>
<p>However when trying to use this class I get the following error:</p>
<p><code>AttributeError: module 'torchvision.datasets' has no attribute 'DatasetFolder'</code></p>
<p>Is DatasetFolder actually supported by torchvision at this point in time?</p>

username: justusschock
cooked: <p>you could specify your own folder as shown in <a href="https://discuss.pytorch.org/t/imagefolder-data-shuffle/17731/5?u=justusschock">this post</a></p>

username: spacemeerkat
cooked: <p>I’m unsure as to where data.Dataset comes from in this class.</p>

username: spacemeerkat
cooked: <p>I’ve implemented the method you suggested above:</p>
<p>class FitsFolder(DatasetFolder):</p>
<pre><code>EXTENSIONS = ['.fits']

def __init__(self, root, transform=None, target_transform=None,
             loader=None):
    if loader is None:
        loader = self.__fits_loader

    super(FitsFolder, self).__init__(root, loader, self.EXTENSIONS,
                                     transform=transform,
                                     target_transform=target_transform)

@staticmethod
def __fits_loader(filename):
    file = fits.open(filename)
    return (file[1].data)
</code></pre>
<p>But when I implement the actual loading process of data:</p>
<pre><code class="lang-auto">testset = FitsFolder(root='/Documents/Image_data2')
test_loader = torch.utils.data.DataLoader(testset, batch_size=batch_size,shuffle=False)
</code></pre>
<p>And try to plot them, the images look nothing like they are supposed to:</p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/2X/7/7262efe45a134e241507210196e62c8ef3f62a73.png" alt="image" data-base62-sha1="gjUp0s2ANHUDFzbBCCI7Jkkw5EL" width="254" height="252"></p>
<p>Rather than:</p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/2X/e/e56f377217b86713459a63b99d8f253d7f2c103d.png" alt="image" data-base62-sha1="wJFCvLnxgFD3JEBaqydCMS539Q9" width="260" height="256"></p>
<p>I also don’t know how to perform a transform such as:</p>
<pre><code class="lang-auto">transform = transforms.Compose([
                    transforms.Resize((32,32)),
                    transforms.ToTensor(),
                    ])
</code></pre>
<p>When using this setup…any help would be greatly appreciated!</p>

username: justusschock
cooked: <p>Could you attach an example file and a converted image (PNG or JPG) for me to verify that my method works?</p>
<p>EDIT: from what I just saw from googling: it should work with</p>
<pre><code class="lang-auto">img_data = fits.get_data(filename)
</code></pre>
<p>As load function and then passing the numpy array to the transformations</p>

username: justusschock
cooked: <p>If you take a look at the gist I linked in the other post:</p>
<p>data.Dataset comes from <code>import torch.utils.data as data</code></p>

username: spacemeerkat
cooked: <p>Unfortunately if I use .get_data I get the warning: <code>module 'astropy.io.fits' has no attribute 'get_data'</code> so I’m currently having to manually pull out the data using:</p>
<pre><code>def __fits_loader(filename):
    file = fits.get_data(filename)
    return file
</code></pre>
<p>So this method is not quite working yet.<br>
I would upload a FITS example but they are not valid extensions for this forum sorry.</p>

username: spacemeerkat
cooked: <p>Okay that would be really helpful, thanks! I’ve uploaded them to a git repo here:</p>
<aside class="onebox whitelistedgeneric">
  <header class="source">
      <img src="https://assets-cdn.github.com/favicon.ico" class="site-icon" width="32" height="32">
      <a href="https://github.com/SpaceMeerkat/Alderaan/tree/master/PyTorch" target="_blank" rel="nofollow noopener">GitHub</a>
  </header>
  <article class="onebox-body">
    <img src="https://avatars2.githubusercontent.com/u/32263989?s=400&amp;v=4" class="thumbnail onebox-avatar" width="400" height="400">

<h3><a href="https://github.com/SpaceMeerkat/Alderaan/tree/master/PyTorch" target="_blank" rel="nofollow noopener">SpaceMeerkat/Alderaan</a></h3>

<p>Alderaan - Spectral Analysis Task</p>


  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>

<p>and added the FITS file to Archive if that’s easier.</p>
<p>Ah, it works if I use <code>getdata()</code> rather than <code>get_data()</code>, so you were right. Although interestingly I have to multiply the output of using <code>getdata()</code> by 1 to make the image not throw up warnings.</p>

username: justusschock
cooked: <p>Strange. If I try use <code>fits.get_data()</code> in a jupyter notebook it works like a charm but if I want to use it within a function in a python-file it breaks.</p>
<p>However I got the following code working with your fits-file by surpassing the <code>get_data()</code> function:</p>
<p><a href="https://gist.github.com/justusschock/dd28afb1dc5ea8f313a10bd25a001802" rel="noopener nofollow ugc">link_to_gist</a></p>
<p>The code is usually straight forward. If you have any questions regarding the functions feel free to ask.</p>
<p>The output I got seems pretty similar to your uploaded image:<br>
<img src="https://discuss.pytorch.org/uploads/default/original/2X/7/75f7093f0cbfc5a97100f5150d6b2eb0974030c5.png" alt="data_img_from_tensor" data-base62-sha1="gPz8sEcVmL2MBVRNgWgPyQmSDB3" width="64" height="64"></p>

username: spacemeerkat
cooked: <p>Really strange isn’t it!</p>
<p>Thanks it works great and gives the same image as what I was seeing with my more crude method, thanks!</p>
<p>I’ve noticed in <code>default_fits_loader</code>  you have left a space for a custom label function. Would it be possible to alter the loader so that instead of loading single fits files, it would load a stacked fits data cube, split the 2d arrays and assign them the labels?</p>
<p>This would help to save a lot of space by saving cubes instead of lots of fits files in preprocessing.</p>

username: justusschock
cooked: <p>should be possible, if the labels are saved in the same order as the arrays inside the cube</p>

username: Shoebhabeeb
cooked: <p>Hi,<br>
Can you provide a repo link or explain how you managed transform the data using Compose. I am stuck on normalizing and transforming the FITS image</p>

username: spacemeerkat
cooked: <p>Hi <a class="mention" href="/u/shoebhabeeb">@Shoebhabeeb</a>, sorry for the delayed reply! I’ve just seen this, as it’s been a while since I encountered this problem I’ll need to go back and have a look so I’ll get back to you on this as soon as I can… it could be that using Compose isn’t the optimal way to do this anymore so I’ll check that first <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

username: Shoebhabeeb
cooked: <p>Hi,<br>
Sure… Do let me know as soon as you can.<br>
I am having trouble passing my dataloader into transforms functions. As they usually classify my images as Nonetype</p>