2012-05-31 68 views
2

我有一个文件头值的字典(时间,帧数,年份,月份等),我想写入一个numpy数组。我目前代码如下:从字典中写入numpy数组

arr=np.array([(k,)+v for k,v in fileheader.iteritems()],dtype=["a3,a,i4,i4,i4,i4,f8,i4,i4,i4,i4,i4,i4,a10,a26,a33,a235,i4,i4,i4,i4,i4,i4"]) 

但我得到一个错误,“只能串联元组(未‘INT’)到元组

基本上,最终结果需要是阵列存储整个文件头信息(它是512字节)和每个帧的数据(头和数据,每帧49408字节)。有没有更简单的方法来做到这一点?

编辑:澄清(为我自己) ,我需要将数据从文件的每一帧写入一个数组,我给出了matlab代码作为基础,下面是给出的代码的一个大概的概念:

data.frame=zeros([512 96]) 
frame=uint8(fread(fid,[data.numbeams,512]),'uint8')) 
data.frame=frame 

如何将“frame”转换为python?

+0

你的错误无关,与numpy的。它来自'[(k,)+ v中的'(k,)+ v',fileheader.iteritems()]中的v。这听起来像你想要使用键的名称作为numpy数组中的记录名称?如果是这样,您需要构建dtype以使用这些名称。另外请记住,'字典是无序的,这可能会导致你现在写的东西出现问题。 –

+0

谢谢!我怎样才能把所有的值以有序的格式? (我基本上没有python经验) –

回答

2

你可能会更好的只是保持头文件数据字典。你真的需要它作为一个数组吗? (如果是这样,为什么呢?有一个优点,那就是将标题放在一个数组中,但它比简单的dict更复杂,并且不那么灵活。)

dict的一个缺点是没有可预测性为了它的钥匙。如果您需要按常规顺序将您的标题写回到磁盘(类似于C结构),则需要单独存储字段顺序及其值。如果是这样的话,你可以考虑一个有序的字典(collections.OrderedDict)或者只是把一个简单的类放在一起来保存你的标题数据并在那里存储订单。

除非有充分的理由将它放入一个numpy数组中,否则您可能不想。

但是,结构化数组将保留您的头的顺序,并且可以更容易地将它的二进制表示写入磁盘,但在其他方面不灵活。

如果你确实想使头一个数组,你会做这样的事情:

import numpy as np 

# Lists can be modified, but preserve order. That's important in this case. 
names = ['Name1', 'Name2', 'Name3'] 
# It's "S3" instead of "a3" for a string field in numpy, by the way 
formats = ['S3', 'i4', 'f8'] 

# It's often cleaner to specify the dtype this way instead of as a giant string 
dtype = dict(names=names, formats=formats) 

# This won't preserve the order we're specifying things in!! 
# If we iterate through it, things may be in any order. 
header = dict(Name1='abc', Name2=456, Name3=3.45) 

# Therefore, we'll be sure to pass things in in order... 
# Also, np.array will expect a tuple instead of a list for a structured array... 
values = tuple(header[name] for name in names) 
header_array = np.array(values, dtype=dtype) 

# We can access field in the array like this... 
print header_array['Name2'] 

# And dump it to disk (similar to a C struct) with 
header_array.tofile('test.dat') 

在另一方面,如果你只是想访问该值在头,只是不停地作为dict。这样更简单。


基于听起来像你在做什么,我会做这样的事情。我使用numpy数组来读取标题,但标题值实际上是作为类属性(以及标题数组)存储的。

这看起来比实际上更复杂。

我只是定义了两个新类,一个用于父文件,另一个用于框架。你可以用少一点的代码来做同样的事情,但是这给了你更复杂事物的基础。

import numpy as np 

class SonarFile(object): 
    # These define the format of the file header 
    header_fields = ('num_frames', 'name1', 'name2', 'name3') 
    header_formats = ('i4', 'f4', 'S10', '>I4') 

    def __init__(self, filename): 
     self.infile = open(filename, 'r') 
     dtype = dict(names=self.header_fields, formats=self.header_formats) 

     # Read in the header as a numpy array (count=1 is important here!) 
     self.header = np.fromfile(self.infile, dtype=dtype, count=1) 

     # Store the position so we can "rewind" to the end of the header 
     self.header_length = self.infile.tell() 

     # You may or may not want to do this (If the field names can have 
     # spaces, it's a bad idea). It will allow you to access things with 
     # sonar_file.Name1 instead of sonar_file.header['Name1'], though. 
     for field in self.header_fields: 
      setattr(self, field, self.header[field]) 

    # __iter__ is a special function that defines what should happen when we 
    # try to iterate through an instance of this class. 
    def __iter__(self): 
     """Iterate through each frame in the dataset.""" 
     # Rewind to the end of the file header 
     self.infile.seek(self.header_length) 

     # Iterate through frames... 
     for _ in range(self.num_frames): 
      yield Frame(self.infile) 

    def close(self): 
     self.infile.close() 

class Frame(object): 
    header_fields = ('width', 'height', 'name') 
    header_formats = ('i4', 'i4', 'S20') 
    data_format = 'f4' 

    def __init__(self, infile): 
     dtype = dict(names=self.header_fields, formats=self.header_formats) 
     self.header = np.fromfile(infile, dtype=dtype, count=1) 

     # See discussion above... 
     for field in self.header_fields: 
      setattr(self, field, self.header[field]) 

     # I'm assuming that the size of the frame is in the frame header... 
     ncols, nrows = self.width, self.height 

     # Read the data in 
     self.data = np.fromfile(infile, self.data_format, count=ncols * nrows) 

     # And reshape it into a 2d array. 
     # I'm assuming C-order, instead of Fortran order. 
     # If it's fortran order, just do "data.reshape((ncols, nrows)).T" 
     self.data = self.data.reshape((nrows, ncols)) 

你会用它与此类似:

dataset = SonarFile('input.dat') 

for frame in dataset: 
    im = frame.data 
    # Do something... 
+0

那么,我想头部信息不需要在一个数组中。但是,我确实需要数组中的帧信息来创建图像。在这里忍受着我 - 我被抛到了最深处,并负责翻译matlab代码以处理数据图像。我知道以下内容:文件头是512字节,每个帧的大小是49408字节,其中256个是帧头,编写matlab代码的人设置了一个初始的零维数组[512,96](这是一个96波束的声纳)。我需要处理每个文件的每个帧。 –

+0

您是否需要将其写回原始文件格式? –

+0

否定的,我想最终将最终数据导出到.txt文件中。现在,我需要读入每个文件和相关的图像数据;它的格式是二进制的。我们最终的结果(拍摄线路)是将这些图像文件(通过声纳相机收集)自动定位在声纳光束中(用于可视化,实质上是黑色背景上的白色圆圈)。如果这有意义,我需要最终将检测到的目标的坐标位置存储在一个文件中。非常感谢你的帮助,我是一个初学者! –

1

问题似乎是vint而不是tuple。尝试:

arr=np.array([(k,v) for k,v in fileheader.iteritems()],dtype=["a3,a,i4,i4,i4,i4,f8,i4,i4,i4,i4,i4,i4,a10,a26,a33,a235,i4,i4,i4,i4,i4,i4"]) 
+0

'k'将会是一个字符串,在这里,给出数组的dtype没有任何意义。 OP可能只是想'v',但我不确定.... –

+0

我从fileheader中的变量获得了每个dtype ... a3是3字符串文件类型,a是版本,i4是int32帧数等等。文件中的一些头文件对应于字符串,一些是浮点数,大多数是32位整数。这有帮助吗? –