我正在处理科学领域的大型数据数组,编码成二进制 FITS 文件。为了简单起见,假设我将 2GB 的 32 位浮点保存到一个文件中,旨在作为 2d 数组读取,并且我将文件作为惰性字节字符串加载
inp <- BL.readFile "myfile.fits"
如何将此文件解析为延迟的 Massiv 数组(
Array DS Ix2 Float
或 Array D Ix2 Float
)?
我想避免打电话给
compute
直到我的手术结束
我似乎找不到从 ByteString 加载 Massiv 数组的简单示例(这似乎应该是一个常见的用例)。我可以通过使用
sreplicateM
评估整个 ByteString 来加载它,将其解析为 Data.Massiv.Vector
,然后使用 resizeM
将其放入 Ix2
。不过,resizeM
需要我先打电话给compute
。
任何人都可以给我举一个如何将 Lazy ByteString 加载到 Massiv 数组并延迟计算的示例吗?
请随意指出解析为
D
或 DS
是错误的选择。我真正的问题是如何将文件中的二进制数据解析为 Array
并允许用户调用 size
slice
、:>
、!
等而不评估整个事情
我认为你想在这里使用
DL
数组,因为 - 与 DS
不同 - DL
支持多维数组,并且与 D
不同,它可以让你控制写入过程(即,你选择从文件加载矩阵时的索引)。
一个独立的示例如下:
import Control.Applicative
import qualified Data.Binary.Get as Bin
import qualified Data.ByteString.Lazy as BL
import Data.Massiv.Array
main :: IO ()
main = do
-- for real code, use lazy I/O for the input:
-- input <- BL.readFile "input.txt"
-- for this example, consider a 2x2 matrix in a lazy bytestring
let input :: BL.ByteString
input = BL.pack $ [ 0,0,0x80,0x3f -- 1
, 0,0,0x00,0x40 -- 2
, 0,0,0x40,0x40 -- 3
, 0,0,0x80,0x40 -- 4
]
nrow = 2
ncol = 2
-- use "binary" package to parse the floats into a lazy list
let floats = Bin.runGet (many Bin.getFloathost) input
-- create a DL array
array :: Array DL Ix2 Float
array = makeLoadArrayS (Sz (nrow :. ncol)) 0.0 $ \writer ->
sequence_ $ Prelude.zipWith writer indices floats
where indices = [(row :. col) | row <- [0..nrow-1], col <- [0..ncol-1]]
-- compute it
let array' :: Array P Ix2 Float
array' = compute array
print array'