Arrays 使用astropy和numpy处理超大阵列

Arrays 使用astropy和numpy处理超大阵列,arrays,list,numpy,astropy,Arrays,List,Numpy,Astropy,出于某些原因,我需要使用astropy将移动距离转换为红移。基本上,这包括读入、循环和写出一个列表或numpy数组。。。我的问题是,我的每个列表通常由~9.5 x 10^6个元素组成。每次我尝试使用numpy.savetxt将输出保存到一个新的txt文件时,这都会给我MemoryError。内存使用量快速增长,最终会稍微慢一点,但总是高于我的128Gb限制 如果有人知道我如何改进下面的脚本,我非常愿意倾听。谢谢大家! import os import sys import glob import

出于某些原因,我需要使用astropy将移动距离转换为红移。基本上,这包括读入、循环和写出一个列表或numpy数组。。。我的问题是,我的每个列表通常由~9.5 x 10^6个元素组成。每次我尝试使用numpy.savetxt将输出保存到一个新的txt文件时,这都会给我MemoryError。内存使用量快速增长,最终会稍微慢一点,但总是高于我的128Gb限制

如果有人知道我如何改进下面的脚本,我非常愿意倾听。谢谢大家!

import os
import sys
import glob
import math
import numpy
import astropy
import astropy.units as unit
from astropy.cosmology import *
cosmo = FlatLambdaCDM(H0=70, Om0=0.3)

inFile=sys.argv[1]
outFile=sys.argv[2]

comovingDistance = numpy.loadtxt(inFile, usecols=(2,))

Redshift = numpy.zeros(len(comovingDistance)) 
for i in range(len(comovingDistance)):
    Redshift[i] = z_at_value(cosmo.comoving_distance, comovingDistance[i] * unit.kpc)

output = open(outFile,'w')
numpy.savetxt(output, Redshift, fmt='%1.8e')
output.close()
下面是错误日志文件:

Traceback (most recent call last):
  File "comoving2redshift.py", line 21, in <module>
    Redshift[i] = z_at_value(cosmo.comoving_distance, comovingDistance[i] * unit.kpc)
  File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/cosmology/funcs.py", line 119, in z_at_value
    fval_zmax = func(zmax)
  File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/cosmology/core.py", line 1195, in comoving_distance
    return self._comoving_distance_z1z2(0, z)
  File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/cosmology/core.py", line 1219, in _comoving_distance_z1z2
    return self._hubble_distance * vectorize_if_needed(f, z1, z2)
  File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/units/quantity.py", line 924, in __mul__
    return super(Quantity, self).__mul__(other)
  File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/units/quantity.py", line 368, in __array_prepare__
    from .quantity_helper import UNSUPPORTED_UFUNCS, UFUNC_HELPERS
MemoryError
回溯(最近一次呼叫最后一次):
文件“comoving2redshift.py”,第21行,在
红移[i]=z_在_值处(cosmo.comoving_距离,comoving距离[i]*单位.kpc)
文件“/afs/mpa/home/minh/.local/lib/python2.7/site packages/astropy/cosmology/funcs.py”,第119行,z_at_值
fval_zmax=func(zmax)
文件“/afs/mpa/home/minh/.local/lib/python2.7/site packages/astropy/cosmology/core.py”,第1195行,共移动距离
返回自移动距离z1z2(0,z)
文件“/afs/mpa/home/minh/.local/lib/python2.7/site packages/astropy/cosmology/core.py”,第1219行,in z1z2
返回自我。如果需要,哈勃距离*矢量化(f,z1,z2)
文件“/afs/mpa/home/minh/.local/lib/python2.7/site packages/astropy/units/quantity.py”,第924行,in\uu mul__
返回超级(数量、自身)。\uuuuu多个(其他)
文件“/afs/mpa/home/minh/.local/lib/python2.7/site packages/astropy/units/quantity.py”,第368行,在数组中__
from.quantity\u helper导入不支持的\u UFUNCS,UFUNC\u HELPERS
记忆者

我不知道numpy有什么固有的解决方案,但您可以通过将每个解决方案立即写入文件,而不是在for循环之后,来节省一些内存分配。这将保存
Redshift
的内存分配,以及
numpy.savetxt()
将浮点格式化为字符串时在后台完成的内存分配

inFile=sys.argv[1]
outFile=sys.argv[2]

comovingDistance = numpy.loadtxt(inFile, usecols=(2,))

with open(outFile, 'w') as fp:
    for distance in comovingDistance:
        fp.write("{:1.8e}\n".format(
            z_at_value(cosmo.comoving_distance, distance * unit.kpc)))

(注意:未测试)

作为我建议的其他解决方案的替代方案,您可以拆分输入文件,迭代新的(临时)输入文件集,并在最后连接输入文件。 下面是一个bash包装器脚本,从外部看,它的工作方式应该与问题中的Python脚本相同(一个输入文件参数,一个输出文件参数)


您可能希望使用临时目录,而不是依赖唯一的前缀。

您在哪一行获得
MemoryError
?@Divakar我在问题中添加了错误日志文件。
z_At_value
中的注释似乎与您的情况相关,您可能希望尝试这种方法。另外,您是否尝试查看
z_at_value
是否已矢量化?很可能您不需要迭代您自己,只需执行
Redshift=z_at_值(cosmo.comoving_distance,comovingtance*unit.kpc)
即可,无需分配
Redshift
数组。@Evert谢谢!我也想过了,事实上我就是这么做的,因为似乎没有比这更聪明的方法了。@Jaime谢谢你关于astropy文档的通知。我读得很快,错过了使用同一宇宙学计算许多量的部分。插值确实拯救了这一天。
#! /bin/bash                                                                                   

nlines=10000                                                                                   
input=$1                                                                                       
output=$2                                                                                      

# use a unique prefix!                                                                         
prefix='tmpsplit'                                                                              
split --lines=$nlines $input $prefix                                                           

outfiles=()                                                                                    
# Assume we only split to a maximum of 26^2 files
# This is the default for split anyway                                              
for filename in ${prefix}??                                                                    
do                                                                                             
        outfile="${filename}-out"                                                              
        ./calcdist.py $filename $outfile                                                      
done                                                                                           

# This assumes the shells orders the glob expansion alphabetically                             
cat ${prefix}*out > $output                                                                    

# Clean up                                                                                     
rm ${prefix}*