我似乎遇到了使用python包ccdproc
进行基本天文图像处理/校准的问题。
我目前正在将30个偏置帧编译成组件帧的单个图像平均值。在完成组合之前,我迭代每个图像,以便使用subtract_overscan()
减去过扫描区域,然后使用trim_image()
选择我想要保留的图像尺寸。
我认为我的索引是正确的但是当我进入组合时,它需要非常长的时间(超过几个小时)。我不确定这是否正常。我怀疑某些东西可能被我的电脑误解了。我之前没有进行任何其他处理就创建了平均图像,并且不需要很长时间(5-10分钟左右),这就是为什么我认为这可能是我索引的问题。
如果有人可以验证我的代码是否正确和/或对可能存在的问题发表评论,那将会有很多帮助。
图片尺寸:NAXIS1 = 3128,NAXIS2 = 3080,allfiles
是ccdproc.ImageFileCollection
。
from astropy.io import fits
import ccdproc as cp
biasImages = []
for filename in allfiles.files_filtered(NAXIS1=3128,NAXIS2=3080,OBSTYPE = 'BIAS'):
ccd = fits.getdata(allfiles.location + filename)
# print(ccd)
ccd = cp.CCDData(ccd, unit = u.adu)
# print(ccd)
ccd = cp.subtract_overscan(ccd,overscan_axis = 1, fits_section = '[3099:3124,:]')
# print(ccd)
ccd = cp.trim_image(ccd,fits_section = '[27:3095,3:3078]')
# print(ccd)
biasImages.append(ccd)
master_bias = cp.combine(biasImages,output_file = path + 'mbias_avg.fits', method='average')
答案 0 :(得分:2)
代码看起来类似于我自己的代码,用于将偏差组合在一起(请参阅此example),因此没有任何内容会立即跳出红旗。我很少做这么大的偏见,ccdproc.combine任务可以更加优化,所以我并不感到惊讶它很慢。
有时我遇到的一件事是垃圾收集问题。因此,如果您在笔记本或大型脚本的一部分中运行此操作,则可能存在未清除内存的问题。查看内存中发生的情况很有用,有时我会在使用后删除biasImages对象(或其他ccd对象列表),并且不再需要它
我很高兴在此进一步回复,或者如果您还有其他问题,请在github repo上打开一个问题。
答案 1 :(得分:1)
如果您只是寻找解决方案,请跳到此答案的最后但如果您感兴趣,为什么(可能)不要跳过
需要很长时间(超过几个小时)。
看起来你的RAM耗尽,然后你的电脑开始使用swap memory。这意味着它将保存硬盘上的部分(或全部)对象并将其从RAM中删除,以便在需要时再次加载它们。在某些情况下,交换内存可以非常高效,因为它只需要很少从硬盘重新加载,但在某些情况下,它必须重新加载很多次,然后你会注意到“整个系统变慢”和“永不结束操作”
经过一些调查后我认为问题主要是因为numpy.array
创建的ccdproc.combine
沿着第一个轴是 stacked而operation是第一个轴轴即可。第一个轴是好的,如果它是一个FORTRAN连续的数组但是ccdproc
doesn't specify any "order"然后它将是C连续的。这意味着最后一个轴上的元素彼此相邻存储在内存中(如果它是FORTRAN-contiguous the elements in the first axis would be next to each other)。因此,如果RAM耗尽并且您的计算机开始使用交换内存,它会将部分数组放在磁盘上,但因为操作是沿第一个轴执行的 - 每个操作中使用的元素的内存地址都“很远”彼此“。这意味着它无法以有用的方式利用交换内存,因为它必须从硬盘中为“每个”下一个项目重新加载数组的部分。
知道实际上,我只是包含了这一点并不是很重要,以防你感兴趣观察行为战的原因。需要注意的一点是,如果你注意到如果你运行任何程序系统变得非常慢,那么它似乎没有取得多大进展,因为你已经用完了RAM!
最简单的解决方案(尽管与编程无关)是购买更多内存。
复杂的解决方案是减少程序的内存占用。
让我们先做一个小小的计算我们要处理多少内存:
您的图片是3128 * 3080
个9634240
元素。当您阅读它们时,它们可能是任何类型,但是当您使用ccdproc.subtract_overscan
时,它们将在float
之后出现。一个浮点(实际上,np.float64
)使用8个字节,因此我们处理77073920
个字节。这个偏差图像大约是73 MB。你有30个偏差图像,所以我们在这里处理大约2.2 GB的数据。这假设您的图片没有uncertainty
或mask
。如果他们有这样的话会增加2.2 GB的不确定性或0.26 GB的掩码。
2.2 GB听起来像一个足够小的数字,但ccdproc.combine
堆叠了NumPy数组。这意味着它将创建一个新数组并将ccd
的数据复制到新数组中。那将加倍那里的记忆。堆叠它们是有意义的,因为即使它需要更多的内存,它实际上进行“组合”时会快得多,但它还没有。
总而言之,4.4 GB已经耗尽了你的RAM。有些计算机只有4GB RAM,不要忘记你的操作系统和其他程序也需要一些RAM。但是,如果你有8GB或更多,你不太可能用完你的RAM,但考虑到数字和你的观察,我认为你只有4-6GB的RAM。
有趣的问题实际上是如何避免这个问题。这实际上取决于你拥有的内存量:
这很棘手,因为在扣除所有CCDData
对象的大小以及操作系统和其他进程所需的内容后,您将没有太多可用内存。在那种情况下,最好一次处理例如5个偏差图像,然后组合第一组合的结果。这可能会起作用,因为您使用average
作为方法(如果您使用median
则无效),因为(A+B+C+D) / 4
等于((A+B)/2 + (C+D)/2)/2
。
那就是(我实际上没有检查过这段代码,所以请在运行之前仔细检查一下):
biasImages = []
biasImagesCombined = []
for idx, filename in enumerate(allfiles.files_filtered(NAXIS1=3128,NAXIS2=3080,OBSTYPE = 'BIAS')):
ccd = fits.getdata(allfiles.location + filename)
ccd = cp.CCDData(ccd, unit = u.adu)
ccd = cp.subtract_overscan(ccd,overscan_axis = 1, fits_section = '[3099:3124,:]')
ccd = cp.trim_image(ccd,fits_section = '[27:3095,3:3078]')
biasImages.append(ccd)
# Combine every 5 bias images. This only works correctly if the amount of
# images is a multiple of 5 and you use average as combine-method.
if (idx + 1) % 5 == 0:
tmp_bias = cp.combine(biasImages, method='average')
biasImages = []
biasImagesCombined.append(tmp_bias)
master_bias = cp.combine(biasImagesCombined, output_file = path + 'mbias_avg.fits', method='average')
在这种情况下,你可能有500 MB备用,所以你可以简单地使用mem_limit
to limit the amount of RAM the combine
。在这种情况下,只需将最后一行更改为:
# To account for additional memory usage I chose 100 MB of additional memory
# you could try to adapt the actual number.
master_bias = cp.combine(biasImages, mem_limit=1024*1024*100, ioutput_file=path + 'mbias_avg.fits', method='average')
在这种情况下,您可能有1 GB的可用RAM。它仍然与4GB选项相同,但您可以使用更高的mem_limit
。我将从500 MB开始:mem_limit=1024*1024*500
。
在这种情况下,我一定错过了一些东西,因为使用~4.5GB的RAM实际上不会耗尽RAM。