使用python修改拟合文件时,错误“缓冲区对于请求的数组来说太小”

时间:2017-10-31 14:19:40

标签: python astropy fits

我正在尝试从初始template.fits

创建一个新的拟合文件

此template.fits包含3915行的语音1表,而我的新文件必须包含超过50000行。

代码的一部分如下:

hdulist = fits.open('/Users/Martina/Desktop/Ubuntu_Condivisa/Post_Doc_IAPS/ASTRI/ASTRI_scienceTools/Astrisim_MC/template.fits') 

hdu0=hdulist[0]

hdu0.writeto(out_pile+'.fits', clobber=True)  

hdu1=hdulist[1]

hdu1.header['NAXIS2'] = na           

hdu1.header['ONTIME'] = tsec              

hdu1.header['LIVETIME'] = tsec       

hdu1.writeto(out_pile+'.fits', clobber=True) 

hdu1_data=hdu1.data              

for j in range(na-1):

  hdu1_data[j+1][1]=j+1

  hdu1_data[j+1][3]=t[j]+0.

  hdu1_data[j+1][7]=ra[j]

  hdu1_data[j+1][8]=dec[j]

  hdu1_data[j+1][21]=enetot[j]

hdu1.writeto(out_pile+'.fits', clobber=True)

当我尝试填充新表(代码的最后一部分)时,错误如下:

Traceback (most recent call last):

  File "C:\Users\Martina\AppData\Local\Programs\Python\Python36\lib\site-packages\astropy\utils\decorators.py", line 734, in __get__
    return obj.__dict__[self._key]

KeyError: 'data'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File "Astrisim_MC_4.py", line 340, in 

    hdu1_data=hdu1.data              

  File "C:\Users\Martina\AppData\Local\Programs\Python\Python36\lib\site-packages\astropy\utils\decorators.py", line 736, in __get__
    val = self.fget(obj)

  File "C:\Users\Martina\AppData\Local\Programs\Python\Python36\lib\site-packages\astropy\io\fits\hdu\table.py", line 404, in data
    data = self._get_tbdata()

  File "C:\Users\Martina\AppData\Local\Programs\Python\Python36\lib\site-packages\astropy\io\fits\hdu\table.py", line 171, in _get_tbdata
    self._data_offset)

  File "C:\Users\Martina\AppData\Local\Programs\Python\Python36\lib\site-packages\astropy\io\fits\hdu\base.py", line 478, in _get_raw_data
    return self._file.readarray(offset=offset, dtype=code, shape=shape)

  File "C:\Users\Martina\AppData\Local\Programs\Python\Python36\lib\site-packages\astropy\io\fits\file.py", line 279, in readarray
    buffer=self._mmap)

TypeError: buffer is too small for requested array

我尝试改变行数,代码正常工作,最多可达3969行。

我该如何解决这个问题?

非常感谢您提前,

喝彩!

的Martina

1 个答案:

答案 0 :(得分:0)

您最初的问题在哪里执行此操作:

hdu1.header['NAXIS2'] = na 

认为你可以做的很自然,但实际上你不应该这样做。通常,在使用astropy.io.fits时,几乎不应该手动弄乱FITS标头中描述数据本身结构的关键字。这部分源于FITS本身的设计 - 它将这些结构关键字与元数据关键字混合在一起 - 部分是astropy.io.fits的设计问题,它允许您在以下操作这些关键字所有,或者它没有更紧密地将数据绑定到它们。我在这里更详细地写了这个问题:https://github.com/astropy/astropy/issues/3836但是从来没有在文档中添加更多解释。

基本上你可以考虑的方法是,当打开FITS文件时,首先读取它的头并将其解析为包含所有头关键字的Header对象。还进行了一些簿记以跟踪标题后文件中的数据量。然后,当您访问HDU的数据时,标题关键字用于确定数据的类型和形状。所以做一些像

这样的事情
hdu1.header['NAXIS2'] = na
hdu1_data = hdu1.data

这不是增长文件中的数据。相反,它只是混淆它认为文件中有更多的数据行然后实际存在,因此错误“缓冲区对于请求的数组来说太小”。在这种情况下,它所指的“缓冲区”是文件中的其余数据,并且您要求它读取的文件比文件中的数据长。

它允许你完全打破这个事实是 Astropy IMO中的 bug 。首次打开文件时,它应该在后台保存所有正确的结构关键字,这样即使用户不小心修改了这些关键字(或者用户应该是completely prevented from modifying these keywords directly),仍然可以正确加载数据。 / p>

这有很长的路要说明你出错的地方,但也许这有助于更好地了解图书馆的运作方式。

至于你的实际问题,我认为@Evert的建议是好的,使用更高级别更容易使用astropy.table来创建一个你需要的大小的新表,然后复制现有的表进入新的。您可以直接打开FITS表作为Table对象以及Table.read。我想你也可以复制FITS元数据,但我不确定最好的方法。

与您的主要问题无关的另一个小评论 - 在使用数组时,您不必(实际上不应该)使用for循环来执行可向量化的操作。

例如,因为这只是循环遍历数组索引:

表示范围内的j(na-1):     hdu1_data [J + 1] [1] = J + 1     hdu1_data [J + 1] [3] = T [j]的0。     hdu1_data [J + 1] [7] = RA [j]的     hdu1_data [J + 1] [8] =癸[j]的     hdu1_data [J + 1] [21] = enetot [j]的

你可以写下这样的操作:

hdu1_data[:][1] = np.arange(na)
hdu1_data[:][3] = t + 0.
hdu1_data[:][7] = ra

依此类推(我不确定你为什么要做j+1,因为这是跳过第一行,但这一点仍然存在)。这当然假设正在更新的数组(在这种情况下为hdu1_data)已经有na行。但这就是为什么你需要首先增长或连接你的数组,如果它不是那么大。