本帖最后由 lianyi_dyq 于 2009-11-2 16:05 编辑
1 输入与输出 IDL中输入输出的基本原则是:“只要有数据,就可以将其读进IDL”,IDL对数据的格式没有要求,也就是任何数据格式都能自由的解析,这使得IDL成为目前功能最强、最灵活的科学可视化分析语言。 1.1 标准输入输出 1.1.1 输入输出函数 IDL中读写ASCII码文本是很重要的一部分。标准输入是键盘输入,标准输出指的是屏幕输出显示。表1-1中列出了标准输入输出的几个函数。 1.1.2 格式化输出 数据的格式化输出是按照设计的格式进行输出。IDL支持“%”和“\”。 标准的输入输出时可以进行格式的自由控制,格式化控制的格式为:[n]FC[+][-][width],各个字段代表的含义见表1-2
如下面的 例子 PRO Test_format COMPILE_OPT idl2 ; PRINT, FORMAT = '(A6)', '123456789' PRINT, FORMAT = '(I2,$)', INDGEN(6) ; PRINT, FORMAT = '("First", 20X, "Last", T10, "Middle")' PRINT, FORMAT = '("First", 20X, "Last", T4, "Middle")' ; PRINT, FORMAT = '("First", 5X, "Last", TL2, "Middle")' ; PRINT, SYSTIME(/JULIAN) PRINT, FORMAT='(C())', SYSTIME(/JULIAN) PRINT, FORMAT='(C(CMOI,"/",CDI))',SYSTIME(/JULIAN) PRINT, FORMAT='(C(CHI2.2,":",CMI2.2,":",CSF05.2))',SYSTIME(/JULIAN) ; PRINT, FORMAT='(%"I have %d monkeys, %s,", " and ", I0, " parrots.")', 10, 'Scott', 5 PRINT, format='(%"I have \xb1%d monkeys [url=file://%22)]\\")'[/url], 5 ; print,'0F'X ; 十六进制转十进制 print,"17 ; 八进制转十进制 print, 119, format='(B)';十进制转二进制的 print, 119, format='(O)';十进制转到八进制 print, 119, format='(Z)';十进制转到十六进制 END
|
1.2 文件读写 1.2.1 打开文件 IDL从磁盘上的文件读写数据,必须首先把一个逻辑设备号连接到一个特定的文件,然后进行文件操作如打开、关闭和读取等。IDL中的逻辑设备号范围是-2—128,其中1--99是可以用户任意指定的,100-128是根据get_lun和free_lun来管理的,其他是特殊函数专用的。 0是常规标准输入流,一般是键盘。也就是说下面命令是一致的: -1是常规标准输出流,一般是显示屏幕,下面命令的功能是一致的: IDL> PRINTF, -1, X IDL> PRINTF, -1, X | -2是错误流,一般是显示屏幕。 文件操作相关的函数见表1-4。
1.2.2 读写ASCII码文件 IDL在读写该文件分为有两种格式化文件:自由文件格式和确定的文件格式。 自由文件格式是用逗号或空白(tab键和空格键)分开文件中的每个元素的ASCII文件。确定的格式文件是用格式说明按照给定的规范进行编排的。二者相比后者比前者更正规一些。 1.2.2.1 读写自由文件格式 IDL下用ReadF从文件中读入自由格式数据,Printf写入自由格式数据到文件中。IDL中读写自由格式文件遵循下面的几个规则: 1) 如果读入到字符串变量中,那么,在当前行剩下的所有字符都将读入该变量中。 2) 输入数据必须用逗号或空白分隔(空格键或tab键)。 3) 输入通过数字变量完成。数组和结构都可作为数字变量的集合。 4) 如果当前读入行是空的,并且还有变量要求输入,则读取另一行。 5) 如果当前读入行不是空的,但是没有变量要求输入,则忽略此行剩下的数。 6) 尽量将数据转换为变量所希望的数据类型。 7) 复数数据必须有实数和虚数两部分,用逗号分隔,并用括号括起来。 1.2.2.2 读写确定的文件格式 读写确定文件格式可同样用ReadF和PrintF命令,它们刚才已用于自由格式文件,但现在文件格式已由Format关键字明确声明。(在读写标准输入和输出时,也可将Format关键字用于Read 和Print命令)。 1.2.2.2.1 通用的格式说明符 通用格式说明符Format关键字的语法参考1.1.2. 1.2.2.2.2 逗号分隔的确定格式 有时数据文件必须用确定格式书写,以方便它们被其它软件读取。用逗号分隔的数据文件就是这类文件的典型代表。 Format=’(F10.3, A1, 2x, F10.3, A1, 2x, F10.3)’ 1.2.2.2.3 字符串中读取格式数据 ReadS是一个有用的IDL命令,可以从字符串变量而不是从文件中为自由格式或确定格式读取数据。ReadS运用了和命令Read和ReadF相同的读取格式数据规则。也就是说,使用ReadS 就象从数据文件中读取一样,所不同的是所读的对象是一个字符串变量。 当大量信息需从文件头部读取时,此命令特别有用。例如,假设ASCII 数据文件的第一行说明了数据文件的行数和列数,此文件头可以从文件中读取,并且可创建一个大小正确的数组来读取数据。 IDL> firstLine=' 10 24500 12 June 1996' IDL> columns=0 IDL> rows=0 IDL> date='' IDL> reads,firstline,columns,rows,date 10 24500 12 June 1996 IDL> print,columns;,rows,date 10 IDL> print,rows;,date 24500 IDL> print,date 12 June 1996 |
1.2.2.3 向导式读取函数 IDL中提供了ASCII_TEMPLATE,QUERY_ASCII和READ_ASCII函数。 asciiFile =currentPath+'\data\ascii.txt' ;依次读取 OPENR,lun,asciifile,/get_lun IF lun EQ -1 THEN RETURN; tmp = '' WHILE(~EOF(lun)) DO BEGIN READF,lun,tmp ENDWHILE FREE_LUN,lun ;分块读取 tmp = STRARR(3) data = FLTARR(2,4) fdata = INTARR(20) OPENR,lun,asciifile,/get_lun READF,lun,tmp READF,lun,data FREE_LUN,lun ;自定义格式读取 tmp ='' row =0 columns =0 type =0 OPENR,lun,asciifile,/get_lun ; READF,lun,tmp READS,tmp,row,columns,type data =MAKE_ARRAY(row,columns,type = type) READF,lun,tmp READF,lun,tmp READF,lun,data FREE_LUN,lun template =Ascii_template(asciiFile) data = Read_ascii(asciiFile,TEMPLATE=template,count = yNum) help,data print,data.(0)
|
1.2.2.4 综合应用举例 针对上面介绍的三种读取方式,对同一个数据采用了不同的读取方式进行了读取,附代码。 1.2.3 读写二进制文件 二进制数据文件基本是以一长串的二进制字节存在文件中,这些字节的含义(也就是说,这些字节如何翻译成特定数据类型和结构的)很难描述的,除非刚开始就知道文件写入的是什么内容。二进制数据比格式化数据紧凑得多,经常用于存储大数据文件。有两种命令读写二进制数据,它们与前面用来读取格式数据文件的ReadF和 Print 命令等效。它们是ReadU和WriteU命令。 要读取非格式数据文件,简单定义变量,打开文件读取,并用ReadU命令将字节一个接一个地读入变量中。如果给定了变量的数据类型和组织结构,每个变量按其要求从文件中读出相应的字节数。 1.2.3.1 读写常规二进制文件 IDL> B = BYTARR(192, 192, /NOZERO) IDL> ; Read the data into B: IDL> READU, 1, B IDL> ; Close the file: IDL> CLOSE, 1 IDL> ; Display the image: IDL> TV, B |
1.2.3.2 读写带头文件的二进制文件 当数据中含有特定的头文件时,读取的时候有时希望直接跳过,此时需要用Point_Lun函数,该函数支持对文件进行字节定位。 调用格式为POINT_LUN, Unit, Position,其中Unit是文件打开后的lun,Position一般是需要跳转的字节数。 1.2.3.3 关联变量读写二进制文件 IDL关联变量是把一个IDL数组或结构变量的组织结构映射到数据文件的内容上。文件被看作是这些重复单元的一个数组。 第一个单元的索引号是0,第二个单元的索引号1等等。关联变量不象常规变量那样将整个数据组都存储在内存里。而是当一关联变量被引用时,IDL仅对需要的部分数据执行相关的输入或输出请求,这部分数据就是要读入内存的。 有时候大型的二进制数据文件都由一系列的重复单元组成。一个IDL关联变量通常是处理这种数据形式的最好方式(有时候是唯一的方式)。 关联变量有下面的几个优点: 当该变量被用于表达式时,才产生文件的输入和输出动作。不需要单独的读或写命令。 数据集的大小不受内存容量的限制,因为有时它可处理大型的数据集。对于物理存储器来说是太大的数据,通过把此数据分成块就能很容易地处理。 不必提前声明用于映射该数据的数组或结构的数量。 关联变量是效率最高的I/O形式。 1.2.3.4 向导式读取函数 READ_BINARY和BINARY_TEMPLATE Read_Binary是直接读取二进制文件的函数,用法可参考下面的语句:
vHeadData = READ_BINARY(FILEPATH('head.dat', $ SUBDIRECTORY=['examples', 'data']), DATA_DIMS=[80,100,57]) IVOLUME, vHeadData |
1.2.3.5 例子 读FY-3的9210AWX文件,FY-2C的卫星黑体亮度温度产品,下面的格式说明是参考国家卫星气候中心的《风云二号C卫星业务产品使用手册》。 PRO test_ReadBinAWX ; currentPath = sourceroot() file = currentPath+'data\FY2C_TBB_IR1_OTG_20061130_AOAD.AWX' ; OpenR, file_lun, file ,/Get_Lun ;定位到信息部分 point_lun,file_lun,20 HeadLine =indgen(3) readu,file_lun,HeadLine ;HeadLine[0]-数据的头文件长度 $ ;HeadLine[]-文件头文件记录数 $ ;HeadLine[2]-数据的记录数 point_lun,file_lun,58 ;定位到信息部分 BeginDate=indgen(5) ;依次为年月日时分 EndDate =indgen(5) ;依次为年月日时分 LatLong=indgen(4) ;依次为左上角纬度经度右下角经度纬度 readu,file_lun,BeginDate readu,file_lun,EndDate readu,file_lun,LatLong ; data = bytarr(HeadLine[2],(HeadLine[0])) ;定位到数据部分 point_lun,file_lun,HeadLine[0]*HeadLine[1] readu,file_lun,data Free_Lun,lun END
|
1.3 读写通用格式文件 IDL可以读写许多常用文件格式,这些文件格式已在表1-5中列出。
1.3.1 图像文件信息查询 IDL中提供了常用图像文件格式的查询程序。这些程序允许在没有真正读取其数据的情况下,就可以查询图像文件,并可以存取随着图像数据文件一起存储在文件里的元数据(关于数据的一些信息)。 下面是新的图像查询程序列表: Query_BMP Query_DICOM Query_GIF Query_JPEG Query_PICT Query_PNG Query_PPM Query_SRF Query_TIFF 所有这些查询命令都是以同样的方式工作。它们都是返回0或1的函数,通过返回值确定是否成功地(返回值为1)读取了图像文件里的元数据。如果它们成功地读取了文件,将保存文件信息的IDL结构变量作为输出命令返回给用户。用户通过存取这个结构里面的字段从而获取文件的有关信息。 1.3.2 JPEG文件操作 1.3.2.1 JPEG读操作 用Read_JPEG命令就可以读取并显示一个JPEG文件。 假设正在8位显示器上显示24位的图像,应该使用TV命令里的关键字True: IDL> TV, thisimage, true=1 1.3.2.2 JPEG写操作 对图形窗口进行拍照可以用TVRD函数。 IDL> image3D=TVRD(true=1) 最后,用Write_JPEG命令,将图像用输出为JPEG文件,运行命令: IDL> Write_JPEG, ‘test.jpg’, image3D, true=1, quality=75 1.3.2.3 举例 对一个jpg文件进行查询及读取操作。 PRO test_CommonImg currentPath =file_dirname(routine_file_path(“test_CommonImg”)) imgFile =currentPath+'\data\idl.jpg' ;文件信息查询 queryStatus = QUERY_IMAGE(imgFile, imageInfo,type = type) HELP,imageInfo,/str IF queryStatus EQ 1 THEN BEGIN CASE type OF 'BMP': BEGIN END 'JPEG': BEGIN jpgStatus=QUERY_JPEG(imgFile, fileinfo) IF jpgStatus THEN BEGIN HELP,fileInfo,/str READ_JPEG,imgFile,data TV,data,/true image=TVRD(0,0,127,287,/true) Write_Jpeg,currentPath+'\data\result.jpg', image,true=1, quality=75 ENDIF END ELSE: BEGIN END ENDCASE ENDIF END |
1.3.3 HDF数据读入 HDF有两种基本对象—组(Group)和数据集(Dataset),同时也有一些其他的辅助对象,如数据类型(Datatype)、数据空间(Dataspace)、属性(Attribute)。HDF组织结构有些类似于Windows 中的文件结构,组相当于一个文件夹,数据集相当于一个数据文件,文件夹里面可以包含数据文件,也可以包含其他的组对象,这样嵌套下去,就形成了一个复杂的数据对象,这点正好的对应于HDF逻辑结构的层次性。 HDF文件的操作 读取-编辑 HDF_OPEN: 这个过程首先要打开HDF文件,通过create关键字来确定是读取文件还是创建一个新的文件。 HDF_DFAN_ADDFDS: 添加文件描述;Optionally, add a file description. HDF_DFAN_ADDFID: 添加文件Optionally, add a file annotation. 对HDF 文件添加数据用到的过程: 添加8位图像,用HDF_DFR8_ADDIMAGE 或DFR8_PUTIMAGE; 添加颜色表,用HDF_DFP_ADDPAL或HDF_DFP_PUTPAL; 添加24位图像,用HDF_DF24_ADDIMAGE 或HDF_DF24_PUTIMAGE; 添加多数据时,需要用下面的命令: HDF_SD_CREATE 或 HDF_SD_SELECT 建立一个SDS或选择一个现有的SDS; HDF_SD_DIMSET 设置维数信息; HDF_SD_ATTRSET 设置属性信息; HDF_SD_SETINFO 添加一个数据信息; HDF_SD_ADDDATA 添加数据; HDF_SD_SETEXTFILE移动数据到外部存储文件; HDF_SD_ENDACCESS 结束读取SDS; 添加数据表(vData)时需要用下面的命令: HDF_VD_ATTACH 获取一个数据表的标识;to get a Vdata identifier. HDF_VD_SETINFO写入数据表的信息; HDF_VD_FDEFINE to prepare non-trivial fields (optional). HDF_VD_WRITE 写入数据表; 将数据表(Vdata)添加到数据组合(Vgroup)中时,用下面的命令: HDF_VG_ATTACH to get a Vgroup identifier. HDF_VG_SETINFO to set the Vgroup name and class (optional). HDF_VG_INSERT to add the Vdata to a Vgroup. HDF_VG_DETACH to close the Vgroup. HDF_CLOSE to close the file 示例数据 |