当前位置:文档之家› WIS测井数据格式

WIS测井数据格式

测井曲线wis文件格式转换为ASCII文本格式小软件的开发(C与Python结合开发)分类:C/C++ 2011-03-25 12:45 627人阅读评论(2) 收藏举报在油田开发地质研究工作中,测井曲线是必不可少的数据文件之一。

Forward软件是测井软件中非常优秀的产品,Forward中使用的是wis二进制格式,可是很多其他类型的软件不能直接识别wis格式,所以需要我们将wis格式文本格式。

Forward软件有一个transfer 小软件,不能实现批量处理,每次只能转换一个文件,但实际工作中通常一次要转换上百个文件,这就有点不方便了,因此,我在业余时间,阅读了Forward软件中自带的wis格式说明(如下,第一章内容),利用C和Python编写了一个可以批量处理的小软件。

第1章WIS测井数据文件格式WellBase平台底层数据文件使用WIS格式,WIS文件分为文件头、对象入口记录和对象数据三部分。

数据存放以块为单位。

WIS文件能存放三种类型的对象,根据对象的类型分为通道对象、表对象和流对象。

通道对象一般用来存放采集数据和处理结果(如测井曲线),表对象用来存放二维表数据(如解释结论),流对象用来存放二进制数据块(如解释参数,用户数据)。

1.1 WIS文件结构1.1.1 文件标识WIS文件标识从文件偏移零开始,为10个字节的字符。

当前版本的标识为WIS 1.0。

1.1.2 文件头结构头结构紧接文件标识。

描述WIS文件的公共信息。

结构定义如下:typedef struct tagWIS_HEAD{WORD MachineType;WORD MaxObjectNumber;WORD ObjectNumber;WORD BlockLen;DWORD DataOffset;DWORD ;DWORD TimeCreate;char Reserved[32];}WIS_HEAD;偏移字节数描述0 2 机器类型=1 为PC;=2为SUN;=3为IBM;=4为HP。

2 2 允许记录的最大对象数。

缺省为512个,该值可以在文件产生时给出。

4 2 当前记录的对象总数(包括删除和抛弃的对象)。

6 2 块长。

WIS文件对象占用的磁盘空间以块为单位,该值指示每一数据块的字节数。

8 4 对象入口记录从文件开始的偏移量。

12 4 对象数据记录从文件开始的偏移量。

16 4 WIS文件的字节数大小。

20 4 WIS文件产生的时间。

24 32 保留字节。

1.1.3 对象入口对象入口描述每个对象的公共信息,开始位置由头结构给出。

每个对象的描述信息前后相连。

结构定义如下:typedef struct tagWIS_OBJECT_ENTRY{char Name[16];long Status;short Attribute;short SubAttribute;DWORD Position;DWORD BlockNum;DWORD TimeCreate;char Reserved[32];}WIS_OBJECT_ENTRY;偏移字节数描述0 16 对象的名称,以零结尾的字符串。

16 4 对象的状态:=0为正常;=1为抛弃;=2为删除。

20 2 对象的主属性:=1为通道对象;=2为表对象;=3为流对象。

22 2 对象的子属性,描述对应主属性的子属性。

24 4 对象数据体从文件开始处的偏移量。

28 4 对象数据体占用磁盘的块数。

32 4 对象产生的时间。

36 4 对象最近修改的时间。

40 32 保留字节。

1.1.4 对象数据体对象数据体记录各个对象的具体特性及数据。

根据不同的主属性分三种类型。

对象数据体在WIS文件中的位置由对象入口指定。

1.1.5 通道对象通道对象用来存放采集和计算结果数据(如测井曲线)。

分为通道信息和通道数据两部分。

WIS文件将在一定时空内对某一采集或计算的物理信息数据集统称为通道数据。

通道信息描述通道数据的存放形式,分为基本信息和维信息,基本信息描述信息的基本物理含义,维信息描述信息的时空特性,可以等间隔(连续)或非等间隔(离散)。

最大允许有四维信息,通道信息共占用一个块空间,结构定义如下:typedef struct tagWIS_CHANNLE{char Unit[8];char AliasName[16];char AliasUnit[16];WORD R epCode;WORD C odeLen;float MinVal;float MaxVal;WORD R eserved;WORD N umOfDimension;WIS_CHANNEL_DIMENSION DimInfo[4];}WIS_CHANNEL;偏移字节数描述0 8 对象的单位,以零结尾的字符串。

8 16 对象的别名,以零结尾的字符串。

24 16 单位的别名,以零结尾的字符串。

40 2 对象数据类型,参见3.2.1。

42 2 数据类型的长度。

44 4 对象的最小值(测井曲线缺省左刻度值)。

48 4 对象的最大值(测井曲线缺省右刻度值)。

52 2 保留字节。

54 2 对象维信息数。

56 4*56 对象维信息。

通道维信息结构定义如下:typedef struct tagWIS_CHANNLE_DIMENSION{char Name[8];char Unit[8];char AliasName[16];float StartVal;float Delta;DWORD Samples;DWORD MaxSamples;DWORD Size;WORD RepCode;WORD Reserved;}WIS_CHANNEL_DIMENSION;偏移字节数描述0 8 维的名称,以零结尾的字符串。

8 8 维的单位,以零结尾的字符串。

16 16 维的别名,以零结尾的字符串。

32 4 维的开始值。

36 4 维的采集或计算增量。

对于离散数据,该值为0,数据中记录该维的值。

40 4 维的数据采样点数。

如果该值为0,采样点数为可变值,数据中记录该值。

对于第一维数据,该值不能为0。

44 4 维的数据采样最大点数。

该值仅当采样点数信息为0(可变采样点)时有效,该维信息在数据中所占用的字节数通过该值计算。

48 4 该维上每一采样点所占用的字节数。

52 2 维的数据类型,参见3.2.1。

54 2 保留字节。

通道数据从通道描述信息的下一块开始。

下面为一个包含深度和时间维的物理信息数据体的存放顺序。

第一维为深度,第二维为时间。

[A1]+[N2]+[B1]+X1+[B2]+X2+···+[BN]+XN+[A2]+[N2]+[B1]+X1+[B2]+X2+···+[BN]+XN+······[AN]+[N2]+[B1]+X1+[B2]+X2+···+[BN]+XN其中:A1,A2,···,AN代表深度值,当深度维信息结构中的Delta为零时,记录此值。

N2代表当前深度点上的时间采样点数,当时间维信息结构中的采样点数为零时,记录此值。

B1,B2,···,BN代表时间值,当时间维信息结构中的Delta为零时,记录此值。

X1,X2,···,N代表物理信息的值。

1.1.6 表对象表对象用来存放二维表数据,分为表信息和表数据体两个部分。

表信息由不同的表项组成,每一表项称为字段。

表信息结构定义如下:typedef struct tagWIS_TABLE{DWORD RecordCount;DWORD FieldCount;WIS_TABLE_FIELD *pField;}WIS_TABLE;偏移字节数描述0 4 表的记录数。

4 4 表的字段数。

8 4 指向字段信息结构的指针。

字段信息结构定义如下:typedef struct tagWIS_TABLE_FIELD{char Name[32];WORD RepCode;WORD Length;DWORD Reserved;}WIS_TABLE_FIELD;偏移字节数描述0 32 字段的名称,以零结尾的字符串。

32 2 字段值的浮点类型,参见3.2.1。

34 2 字段值的长度。

表数据体(记录)从表信息记录的下一块开始。

1.1.7 流对象流对象用来存放二进制数据块。

开始为4个字节的无符号长整形数,代表数据流的长度。

接着为该流的二进制值。

第二章WIS测井数据格式转换文本格式C程序代码代码如下:view plaincopy to clipboardprint?1. /*2. * Copyright (c) 2011, Sun Yunqiang3. * All rights reserved.4. * Software: wis2txt_win5. * Version: 1.06. * Author: Sun Yunqiang7. * English Name: Alex Sun8. * Release Date: 18/03/20119. */10.11. /** ***************************************************************** */12./** This Program is for converting wis format txt format file */13. /** Command: wis2txt_win.exe args1 args2 */14. /** Description:*/15. /** wis2txt_win.exe: the executable command */16. /** args1: the first argument that is the wis */17. /** args2: the second argument that is the txt */18. /** ***************************************************************** */19.20. #include <windows.h>21. #include <stdio.h>22. #include <stdlib.h>23. #include <string.h>24. #include <ctype.h>25. #include <time.h>26. #include <math.h>27.28. #define ROW 6553629. #define COL 51230.31.32. /* **************************************** */33. /* Below blocks are the structs of wis file */34. /* **************************************** */35. typedef struct tagWIS_HEAD36. {37. WORD MachineType; // 0-PC 1-SUN 2-IBM 3-HP38. WORD MaxObjectNumber;39. WORD ObjectNumber;40. WORD BlockLen;41. DWORD EntryOffset;42. DWORD DataOffset;43. DWORD ;44. time_t TimeCreate;45. char Reserved[32];46. }WIS_HEAD;47.48. typedef struct tagWIS_OBJECT_ENTRY49. {50. char Name[16];51. long Status;52. short Attribute; // 1-通道对象 2-表对象 3-流对象53. short SubAttribute; // 1-曲线对象 2-波形对象 3-地层测试对象 4-时深时对象54. DWORD Position; // 对象数据体从文件开始处的偏移量55. DWORD BlockNum;56. time_t TimeCreate;57. time_t TimeWrite;58. char Reserved[32];59. }WIS_OBJECT_ENTRY;60.61. typedef struct tagWIS_CHANNEL_DIMENSION62. {63. char Name[8];64. char Unit[8];65. char AliasName[16];66. float StartVal;67. float Delta;68. DWORD Samples;69. DWORD MaxSamples;70. DWORD Size;71. WORD RepCode;72. WORD Reserved;73. }WIS_CHANNEL_DIMENSION;74.75. typedef struct tagWIS_CHANNEL76. {77. char Unit[8];78. char AliasName[16];79. char AliasUnit[16];80. WORD RepCode;81. WORD CodeLen;82. float MinVal;83. float MaxVal;84. WORD Reserved;85. WORD NumOfDimension;86. WIS_CHANNEL_DIMENSION DimInfo[4];87. }WIS_CHANNEL;88.89. typedef struct tagWIS_STREAM90. {91. DWORD Length;92. DWORD Offset;93. }WIS_STREAM;94.95. typedef struct tagWIS_TABLE_FIELD96. {97. char Name[32];98. WORD RepCode;99. WORD Length;100. DWORD Reserved;101. } WIS_TABLE_FIELD;102.103. typedef struct tagWIS_TABLE104. {105. DWORD RecordCount;106. DWORD FieldCount;107. WIS_TABLE_FIELD *pField;108. }WIS_TABLE;109.110.111. typedef struct tagWIS_TABLE_DEFAULT_FILED 112. {113. char Name[16];114. char Alias[16];115. char Unit[8];116. char Type[8];117. WORD Length;118. WORD Count;119. char DefVal[64][12];120. } WIS_TABLE_DEFAULT_FIELD;121.122.123. typedef struct tagWIS_DEFAULT_TABLE124. {125. char Name[16];126. char Alias[16];127. char Attrb[8];128. DWORD FieldCount;129. WIS_TABLE_DEFAULT_FIELD *pField;130. } WIS_DEFAULT_TABLE;131.132.133.134. /* 曲线的信息结构体*/135. typedef struct tagCURVE_HEAD136. {137. char Name[16]; // 曲线的名字138. char Unit[8]; // 曲线的单位139. float startMD; // 曲线的起始深度140. float stopMD; // 曲线的结束深度141. int pointNum; // 数据样点数142. int position; // 数据位置143. struct tagCURVE_HEAD *next;144. } CURVE_HEAD;145.146. /* 曲线的数据结构体 */147. typedef struct tagCURVE_DATA148. {149. char Name[16]; // 曲线的名字150. char Unit[8]; // 曲线的单位151. float Depth[ROW]; // 曲线的深度值152. float Value[ROW]; // 曲线的值153. struct tagCURVE_DATA *next;154. } CURVE_DATA;155.156.157.158.159. /* ************************************************************* */160. /* Below block is the Main program of processing wis format file */ 161. /* ************************************************************* */162.163. int main(int argc, char *argv[])164. {165. FILE *wisfile; // 输入文件166. FILE *txtfile; // 输出文件167. char *in = argv[1];168. char *out = argv[2];169. // char *in = "demoa.wis";170. // char *out = "demoa.txt";171.172. if(argc != 3 )173. {174. printf("ERROR: Command parameters is not defined correctly!/n"); 175. exit(1);176. }177.178.179. wisfile = fopen(in, "rb");180. if(wis NULL)181. {182. printf("ERROR: Read ");183. exit(1);184. }185. txtfile = fopen(out, "w");186. if(txt NULL)187. {188. printf("ERROR: Write ");189. exit(1);190. }191.192. /* Process wis file, Read it and transfer it to text */193.194. /** wis文件标识符从文件偏移0开始,为10个字节的字符 */195. char wisid[10];196. fread(wisid, 10, 1, wisfile);197. // printf("文件标识符: %s/n", wisid);198. fprintf(txtfile, "ASCII WIS %c%c%c/n", wisid[4], wisid[5], wisid[6]); 199.200. /** 头文件紧接文件标识 */201. WIS_HEAD *wishead;202. wishead = (WIS_HEAD *)malloc(sizeof(WIS_HEAD));203. fseek(wisfile, 10, SEEK_SET);204. fread(wishead, sizeof(WIS_HEAD), 1, wisfile);205. // printf("对象入口记录从文件开始的偏移量EntryOffset: %d/n", wishead->EntryOffset);206. // printf("对象数据记录从文件开始的偏移量DataOffset: %d/n", wishead->DataOffset);207. // printf("当前记录的对象总数ObjectNumber: %d/n", wishead->ObjectNumber);208.209.210. /** 对象入口,位置由头结构中EntryOffset参数指定最多512条曲线 */ 211. /** curvePosition数组保存曲线数据开始的位置 WIS_OBJECT_ENTRY->Position的值 */212. /** curveName数组保存每条曲线的名称 */213. /** curveNum变量文件中保存曲线的数目 */214. int curvePosition[512];215. int curveName[512][16];216. int curveNum = 0; // curveNum is the identifer of the curves number 217. fseek(wisfile, wishead->EntryOffset, SEEK_SET);218. // fseek(wisfile, 10+sizeof(WIS_HEAD), SEEK_SET);219. while(1)220. {221. WIS_OBJECT_ENTRY *objectEntry;222. objectEntry = (WIS_OBJECT_ENTRY *)malloc(sizeof(WIS_OBJECT_ ENTRY));223. fread(objectEntry, sizeof(WIS_OBJECT_ENTRY), 1, wisfile);224.225. if(objectEntry->Attribute == 0)226. {227. break;228. }229. else if(objectEntry->Attribute == 1)230. {231. // printf("通道类型: %d/n",objectEntry->Attribute);232. // printf("No. %d/n", curveNum);233. // printf("曲线对象的名称Name: %s/n", objectEntry->Name); 234. // fprintf(outfile, "%s ", objectEntry->Name); // 打印曲线名字235. // printf("对象数据体绝对偏移量Position: %d/n/n", objectEntry->Position);236. curvePosition[curveNum] = objectEntry->Position;237. int i=0;238. for(i=0; i<16; i++)239. {240. curveName[curveNum][i] = objectEntry->Name[i];241. }242.243. curveNum++;244. }245. else246. {247. continue;248. }249.250. }251. printf("/n%s文件的曲线数目: %d/n/n", in, curveNum);252.253.254.255. /* ****************************************************************** */ 256. /* Below block read every curve head information and put it in a link */ 257. /* ****************************************************************** */ 258.259. /** 创建链表 data_node 开始读取数据 */260. /** num变量每条曲线的行数 */261. CURVE_HEAD *first_head = NULL;262. float delta = 0.0;263.264. CURVE_HEAD *data_head = NULL;265. int num = 0;266. for(num = 0; num < curveNum ; num++) // num相当于第几条曲线267. {268.269. data_head = (CURVE_HEAD *)malloc(sizeof(CURVE_HEAD)); 270. data_head->position = curvePosition[num];271.272. fseek(wisfile, curvePosition[num], SEEK_SET);273. WIS_CHANNEL *channel;274. channel = (WIS_CHANNEL *)malloc(sizeof(WIS_CHANNEL)); 275. fread(channel, sizeof(WIS_CHANNEL), 1, wisfile);276. // printf("对象的单位Unit: %s/n", channel->Unit);277. // printf("对象的别名AliasName: %s/n", channel->AliasName);278. // printf("单位的别称AliasUnit: %s/n", channel->AliasUnit);279. // printf("对象的最小值MinVal: %f/n", channel->MinVal);280. // printf("对象的最大值MaxVal: %f/n", channel->MaxVal);281. // printf("对象维信息数NumOfDimension: %d/n", channel->NumOfDimension);282. // printf("维的开始值StartVal: %f/n", channel->DimInfo[0].StartVal); 283. // printf("维的增量值Delta: %f/n", channel->DimInfo[0].Delta);284.285. data_head->pointNum = channel->DimInfo[0].MaxSamples; // 深度采样点的个数286. data_head->startMD = channel->DimInfo[0].StartVal; // 起始深度287. delta = channel->DimInfo[0].Delta; // 间隔点值288. data_head->stopMD = channel->DimInfo[0].StartVal + delta * channel->DimInfo[0].MaxSamples; // 结束深度289.290.291. int i = 0;292. for(i=0; i<16; i++)293. {294. data_head->Name[i] = curveName[num][i];295. }296. for(i=0; i<8; i++)297. {298. data_head->Unit[i] = channel->Unit[i];299. }300.301. printf("No.%d/t", num+1); // 曲线编号302. printf("%s/t", data_head->Name); // 曲线名303. printf("%s/t", data_head->Unit); // 曲线单位304. printf("%d/t", data_head->pointNum); // 采样点数305. printf("%9.3f/t", delta); // 采样点间隔306. printf("%9.3f/t", data_head->startMD); // 起始深度307. printf("%9.3f/n", data_head->stopMD); // 结束深度308.309.310.311. data_head->next = first_head;312. first_head = data_head;313. }314.315.316.317. /* *********************************************************************** */ 318. /* Below block is for deciding the min and max Depth, and the max line n um */319. /* *********************************************************************** */ 320.321. // 从这里开始判断所有曲线中最小深度和最大深度值322. float minDepth = 0.0;323. float maxDepth = 0.0;324. minDepth = first_head->startMD;325. maxDepth = first_head->stopMD;326. for(data_head = first_head; data_head!= NULL; data_head=data_head-> next)327. {328. if(minDepth>data_head->startMD)329. {330. minDepth = data_head->startMD;331. }332. if(maxDepth < data_head->stopMD)333. {334. maxDepth = data_head->stopMD;335. }336. }337. // printf("最小深度值:%f/n", minDepth);338. // printf("最大深度值:%f/n", maxDepth);339.340. // 利用最小最大深度值和间隔点值,确定输出的采样点数341. float depth[ROW];342. int lineNum = 0;343. lineNum = (maxDepth - minDepth) / delta;344. // printf("采样点个数:%d/n", lineNum);345.346. int row=0;347. for(row=0; row<lineNum; row++)348. {349. depth[row] = minDepth + delta * row;350. }351.352.353.354. /* ******************************************************** */355. /* Below block put every point value into a link as a curve */356. /* ******************************************************** */357.358. // 从这里开始将数据值放入曲线各自对应的链表里359.360. CURVE_DATA *first_node = NULL;361. CURVE_DATA *data_node = NULL;362.363. data_head = first_head;364.365. for(num = 0; num < curveNum ; num++)366. {367. data_node = (CURVE_DATA *)malloc(sizeof(CURVE_DATA)); 368. int i = 0;369. for(i=0; i<16; i++)370. {371. data_node->Name[i] = data_head->Name[i];372. }373. for(i=0; i<8; i++)374. {375. data_node->Unit[i] = data_head->Unit[i];376. }377. // printf("曲线名称:%s/n", data_node->Name);378. // printf("曲线单位:%s/n", data_node->Unit);379.380. int startLine = 0;381. for(row=0; row<lineNum; row++)382. {383. if( abs(depth[row]-data_head->startMD)<= delta384. && depth[row] >= data_head->startMD )385. {386. startLine = row;387. break;388. }389. }390. // printf("起始点:%d/n", startLine);391.392. // fseek(wisfile, data_head->position, SEEK_SET);393. fseek(wisfile, data_head->position+2*sizeof(WIS_CHANNEL)+464, SE EK_SET);394.395. // printf("测试样点数%d/n", data_head->pointNum);396. for(row=0; row<lineNum; row++)397. {398. float data[1];399. data[0] = -9999.000;400. if(row>=startLine && (row-startLine) < data_head->pointNum) 401. {402. fread(data, sizeof(float), 1, wisfile);403. data_node->Depth[row] = data_head->startMD + delta * (row-star tLine);404. data_node->Value[row] = data[0];405. }406. else407. {408. data_node->Depth[row] = minDepth + delta * row;409. data_node->Value[row] = -9999.000;410. }411.412. // printf("读取值:%f/n", data_node->Value[row]);413. }414.415.416. data_node->next = first_node;417. first_node = data_node;418. if(data_head->next == NULL)419. {420. break;421. }422.423. data_head = data_head->next;424. // printf("下一条曲线名:%s/n", data_head->Name);425. }426.427.428. /* **************************************************** */429. /* Below block print all point value for every curve */430. /* The important thing is how to decide the right depth */431. /* **************************************************** */432.433. // 从这里开始写入文本434.435. // Print Curve Name436. fprintf(txtfile, "DEPTH ");437. for(data_node=first_node; data_node!=NULL; data_node=data_node->n ext)438. {439. fprintf(txtfile, "%9s ", data_node->Name);440. }441. fprintf(txtfile, "/n");442. // printf("/n");443.444. // Print Curve Unit445. fprintf(txtfile, "M ");446. for(data_node=first_node; data_node!=NULL; data_node=data_node->n ext)447. {448. fprintf(txtfile, "%9s ", data_node->Unit);449. }450. fprintf(txtfile, "/n");451. // printf("/n");452.453. // Print curve value454. for(row=0; row<lineNum; row++)455. {456. if(depth[row] > maxDepth)457. {458. break;459. }460. fprintf(txtfile, "%-9.4f ", depth[row]);461. for(data_node=first_node; data_node!=NULL; data_node=data_node->next)462. {463. // fprintf(txtfile, "%-9.4f ", data_node->Depth[row]);464. fprintf(txtfile, "%9.3f ", data_node->Value[row]);465. }466. fprintf(txtfile, "/n");467. }468. // */469.470.471. // Process Over472. fclose(wisfile);473. fclose(txtfile);474. printf("/n%s Complete!/n", in);475. // system("PAUSE");476. // Program Over477. return 0;478. }右侧消息列表会显示每个Wis文件处理的信息!当然转换后的结果文件会存到所选取的路径中。

相关主题