001/* 002 * $Id: HDF.java,v 1.7 2011/03/24 16:06:33 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031package edu.wisc.ssec.mcidasv.data.hydra; 032 033import java.io.*; 034import java.nio.*; 035import java.nio.channels.*; 036 037/** 038 * Provides access to HDF4 files via the plug_hdf executable. 039 */ 040public class HDF { 041 042 private static final int INT_SIZE = 4; 043 044 Process process; 045 InputStream readable; 046 OutputStream writable; 047 048 public HDF(String exe) throws IOException { 049 Runtime rt = Runtime.getRuntime(); 050 process = rt.exec(exe); 051 writable = process.getOutputStream(); 052 readable = process.getInputStream(); 053 } 054 055 int command(int cmd_id, byte[] paramBlock) 056 throws IOException { 057 byte[] cc = intToByteArray(cmd_id); 058 byte[] b_array = new byte[4+paramBlock.length]; 059 System.arraycopy(cc,0,b_array,0,4); 060 System.arraycopy(paramBlock,0,b_array,4,paramBlock.length); 061 writable.write(b_array); 062 writable.flush(); 063 064 b_array = new byte[4]; 065 int n = readable.read(b_array,0,4); 066 if (n != 4) throw new IOException("problem reading return code from command: "+cmd_id); 067 int rc = byteArrayToInt(b_array); 068 return rc; 069 } 070 071 synchronized int start(String filename) throws Exception { 072 int rc = command(2, stringBlock(filename)); 073 if (rc >= 0) { 074 return readStruct(); 075 } 076 else { 077 throw new Exception("start failed on "+filename+", returned: "+rc); 078 } 079 } 080 081 byte[] stringBlock(String name) throws IOException { 082 int len = name.length(); 083 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 084 DataOutputStream das = new DataOutputStream(bos); 085 das.writeInt(len); 086 byte[] int_byte = bos.toByteArray(); 087 byte[] str_bytes = name.getBytes(); 088 byte[] byte_array = new byte[4+len]; 089 System.arraycopy(int_byte, 0, byte_array, 0, 4); 090 System.arraycopy(str_bytes, 0, byte_array, 4, len); 091 return byte_array; 092 } 093 094 byte[] intToByteArray(int a) throws IOException { 095 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 096 DataOutputStream das = new DataOutputStream(bos); 097 das.writeInt(a); 098 byte[] int_byte = bos.toByteArray(); 099 return int_byte; 100 } 101 102 byte[] intArrayToByteArray(int[] a) throws Exception { 103 int a_len = a.length; 104 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 105 DataOutputStream das = new DataOutputStream(bos); 106 das.writeInt(a_len); 107 for (int k=0; k<a_len;k++) das.writeInt(a[k]); 108 byte[] b_array = bos.toByteArray(); 109 return b_array; 110 } 111 112 int byteArrayToInt(byte[] b) throws IOException { 113 ByteArrayInputStream bis = new ByteArrayInputStream(b); 114 DataInputStream dis = new DataInputStream(bis); 115 int d = dis.readInt(); 116 return d; 117 } 118 119 int[] byteArrayToInt(int n_elems, byte[] b) throws IOException { 120 ByteArrayInputStream bis = new ByteArrayInputStream(b); 121 DataInputStream dis = new DataInputStream(bis); 122 int[] iarray = new int[n_elems]; 123 for (int k=0; k<n_elems; k++) { 124 int d = dis.readInt(); 125 iarray[k] = d; 126 } 127 return iarray; 128 } 129 130 int readStruct() throws IOException { 131 byte[] b_array = new byte[4]; 132 int n = readable.read(b_array,0,4); 133 if (n != 4) throw new IOException("number of bytes read not what expected"); 134 int d = byteArrayToInt(b_array); 135 return d; 136 } 137 138 String readString() throws IOException { 139 byte[] b_array = new byte[4]; 140 int n = readable.read(b_array,0,4); 141 if (n != 4) throw new IOException("number of bytes read not what expected"); 142 int nelem = byteArrayToInt(b_array); 143 b_array = new byte[nelem]; 144 n = readable.read(b_array,0,nelem); 145 if (n != nelem) throw new IOException("number of bytes read not what expected"); 146 return new String(b_array); 147 } 148 149 synchronized HDFArray readattr(int id, int attr_index) throws Exception { 150 byte[] ba = intToByteArray(id); 151 byte[] sb = intToByteArray(attr_index); 152 byte[] cb = new byte[4+sb.length]; 153 System.arraycopy(ba,0,cb,0,4); 154 System.arraycopy(sb,0,cb,4,sb.length); 155 156 int rc = command(4, cb); 157 if (rc >= 0) { 158 String data_type = readString(); 159 int element_count = readStruct(); 160 HDFArray obj = readRawBlock(data_type, element_count); 161 return obj; 162 } 163 else { 164 throw new Exception("readattr failed on id,attr_index: "+id+","+attr_index); 165 } 166 } 167 168 synchronized int getdimid(int sds_id, int dim_index) throws Exception { 169 byte[] ba = intToByteArray(sds_id); 170 byte[] sb = intToByteArray(dim_index); 171 byte[] cb = new byte[4+sb.length]; 172 System.arraycopy(ba,0,cb,0,4); 173 System.arraycopy(sb,0,cb,4,sb.length); 174 175 int rc = command(10, cb); 176 if (rc >= 0) { 177 return readStruct(); 178 } 179 else { 180 throw new Exception("getdimid failed on sds_id,dim_index: "+sds_id+","+dim_index); 181 } 182 } 183 184 synchronized HDFDimension diminfo(int dim_id) throws Exception { 185 byte[] ba = intToByteArray(dim_id); 186 187 int rc = command(11, ba); 188 if (rc >= 0) { 189 String dim_name = readString(); 190 int dim_size = readStruct(); 191 int dim_type_code = readStruct(); 192 int dim_n_attrs = readStruct(); 193 return new HDFDimension(dim_name, dim_size, dim_type_code, dim_n_attrs); 194 } 195 else { 196 throw new Exception("diminfo failed on dim_id: "+dim_id+" returned: "+rc); 197 } 198 199 } 200 201 synchronized HDFVariableInfo getinfo(int sds_id) throws Exception { 202 byte[] ba = intToByteArray(sds_id); 203 int rc = command(13, ba); 204 if (rc>=0) { 205 String var_name = readString(); 206 int var_rank = readStruct(); 207 208 byte[] b_array = new byte[4]; 209 int n = readable.read(b_array, 0, 4); 210 int n_words = byteArrayToInt(b_array); 211 212 byte[] b_array2 = new byte[n_words*4]; 213 n = readable.read(b_array2, 0, b_array2.length); 214 if (n != b_array2.length) throw new Exception("msg"); 215 int[] var_dim_lengths = byteArrayToInt(var_rank, b_array2); 216 217 int var_data_type = readStruct(); 218 int var_num_attrs = readStruct(); 219 220 return new HDFVariableInfo(var_name, var_rank, var_dim_lengths, var_data_type, var_num_attrs); 221 } 222 else { 223 throw new Exception("getinfo failed on sds_id: "+sds_id+" returned: "+rc); 224 } 225 } 226 227 synchronized HDFFileInfo fileinfo(int sd_id) throws Exception { 228 byte[] ba = intToByteArray(sd_id); 229 int rc = command(12, ba); 230 if (rc>=0) { 231 int num_datasets = readStruct(); 232 int num_global_attrs = readStruct(); 233 return new HDFFileInfo(num_datasets, num_global_attrs); 234 } 235 else { 236 throw new Exception("fileinfo failed on sd_id: "+sd_id+", returned: "+rc); 237 } 238 } 239 240 synchronized int select(int id, int index) throws Exception { 241 byte[] ba = intToByteArray(id); 242 byte[] sb = intToByteArray(index); 243 byte[] cb = new byte[4+sb.length]; 244 245 System.arraycopy(ba,0,cb,0,4); 246 System.arraycopy(sb,0,cb,4,sb.length); 247 248 int rc = command(3, cb); 249 if (rc >= 0) { 250 return readStruct(); 251 } 252 else { 253 throw new Exception("select failded on id, index: "+id+","+index+" returned: "+rc); 254 } 255 } 256 257 synchronized HDFArray readRawBlock(String data_type, int element_count) throws IOException { 258 byte[] b_array = new byte[4]; 259 int n = readable.read(b_array,0,4); 260 if (n != 4) throw new IOException("msg"); 261 int nbytes = byteArrayToInt(b_array); 262 263 ByteBuffer b_buf = ByteBuffer.allocate(nbytes); 264 byte[] bb = b_buf.array(); 265 266 //- workaround for problem seen only on MAC OS X 267 int ntotal = 0; 268 while(ntotal < nbytes) { 269 n = readable.read(bb, ntotal, nbytes-ntotal); 270 ntotal += n; 271 } 272 273 if (data_type.equals("s")) { 274 return HDFArray.make(new String[] {new String(bb)}); 275 } 276 277 // use java.nio to format bytes 278 b_buf.rewind(); 279 280 if ((data_type.equals("I")) || (data_type.equals("i"))) { 281 IntBuffer buf = b_buf.asIntBuffer(); 282 int[] array = new int[element_count]; 283 buf.get(array); 284 return HDFArray.make(array); 285 } 286 if ((data_type.equals("H")) || (data_type.equals("h"))) { 287 ShortBuffer buf = b_buf.asShortBuffer(); 288 short[] array = new short[element_count]; 289 buf.get(array); 290 return HDFArray.make(array); 291 } 292 if ((data_type.equals("D")) || (data_type.equals("d"))) { 293 DoubleBuffer buf = b_buf.asDoubleBuffer(); 294 double[] array = new double[element_count]; 295 buf.get(array); 296 return HDFArray.make(array); 297 } 298 if ((data_type.equals("F")) || (data_type.equals("f"))) { 299 FloatBuffer buf = b_buf.asFloatBuffer(); 300 float[] array = new float[element_count]; 301 buf.get(array); 302 return HDFArray.make(array); 303 } 304 305 return null; 306 } 307 308 synchronized int endaccess(int sds_id) throws Exception { 309 int rc = command(7, intToByteArray(sds_id)); 310 if (rc >= 0) { 311 return rc; 312 } 313 else { 314 throw new Exception("endaccess failed on sds_id: "+sds_id+" returned: "+rc); 315 } 316 } 317 318 synchronized int findattr(int id, String name) throws Exception { 319 byte[] ba = intToByteArray(id); 320 byte[] sb = stringBlock(name); 321 byte[] cb = new byte[4+sb.length]; 322 System.arraycopy(ba,0,cb,0,4); 323 System.arraycopy(sb,0,cb,4,sb.length); 324 325 int rc = command(5, cb); 326 if (rc >= 0) { 327 return readStruct(); 328 } 329 else { 330 throw new Exception("findattr failed on id, name: "+id+","+name+" returned: "+rc); 331 } 332 } 333 334 synchronized int nametoindex(int id, String name) throws Exception { 335 byte[] ba = intToByteArray(id); 336 byte[] sb = stringBlock(name); 337 byte[] cb = new byte[4+sb.length]; 338 System.arraycopy(ba,0,cb,0,4); 339 System.arraycopy(sb,0,cb,4,sb.length); 340 341 int rc = command(8, cb); 342 if (rc >= 0) { 343 return readStruct(); 344 } 345 else { 346 throw new Exception("nametoindex failed on id,name: "+id+","+name+" returned: "+rc); 347 } 348 } 349 350 synchronized HDFArray readdata(int sds_id, int[] start, int[] stride, int[] edges) throws Exception { 351 int len = 0; 352 353 byte[] ba_id = intToByteArray(sds_id); 354 len += 4; 355 byte[] ba_start = intArrayToByteArray(start); 356 len += ba_start.length; 357 byte[] ba_stride = intArrayToByteArray(stride); 358 len += ba_stride.length; 359 byte[] ba_edges = intArrayToByteArray(edges); 360 len += ba_edges.length; 361 byte[] b_array = new byte[len]; 362 363 len = 0; 364 System.arraycopy(ba_id,0,b_array,len,ba_id.length); 365 len += ba_id.length; 366 System.arraycopy(ba_start,0,b_array,len,ba_start.length); 367 len += ba_start.length; 368 System.arraycopy(ba_stride,0,b_array,len,ba_stride.length); 369 len += ba_stride.length; 370 System.arraycopy(ba_edges,0,b_array,len,ba_edges.length); 371 372 int rc = command(6, b_array); 373 if (rc >= 0) { 374 String data_type = readString(); 375 int elementCount = readStruct(); 376 return readRawBlock(data_type, elementCount); 377 } 378 else { 379 throw new Exception("readdata failed on sds_id: "+sds_id+" returned: "+rc); 380 } 381 } 382 383 synchronized int vStart(int f_id) throws Exception { 384 byte[] ba = intToByteArray(f_id); 385 int rc = command(16, ba); 386 if (rc >= 0) { 387 return readStruct(); 388 } 389 else { 390 throw new Exception("vStart failed on "+f_id+", returned: "+rc); 391 } 392 } 393 394 synchronized int vEnd(int v_id) throws Exception { 395 byte[] ba = intToByteArray(v_id); 396 int rc = command(18, ba); 397 if (rc >= 0) { 398 return readStruct(); 399 } 400 else { 401 throw new Exception("vEnd failed on "+v_id+", returned: "+rc); 402 } 403 } 404 405 synchronized int hOpen(String filename) throws Exception { 406 int rc = command(14, stringBlock(filename)); 407 if (rc >= 0) { 408 return readStruct(); 409 } 410 else { 411 throw new Exception("hopen failed on "+filename+", returned: "+rc); 412 } 413 } 414 415 synchronized int hClose(int f_id) throws Exception { 416 byte[] ba = intToByteArray(f_id); 417 int rc = command(15, ba); 418 if (rc >= 0) { 419 return readStruct(); 420 } 421 else { 422 throw new Exception("h_close failed on "+f_id+", returned: "+rc); 423 } 424 } 425 426 synchronized int vsFind(int f_id, String data_name) throws Exception { 427 byte[] ba = intToByteArray(f_id); 428 byte[] sb = stringBlock(data_name); 429 byte[] cb = new byte[4+sb.length]; 430 System.arraycopy(ba,0,cb,0,4); 431 System.arraycopy(sb,0,cb,4,sb.length); 432 433 int rc = command(17, cb); 434 if (rc >= 0) { 435 return readStruct(); 436 } 437 else { 438 throw new Exception("vsFind failed on "+f_id+",data_name: "+data_name+", returned: "+rc); 439 } 440 } 441 442 synchronized int vsAttach(int f_id, int v_id) throws Exception { 443 byte[] ba = intToByteArray(f_id); 444 byte[] sb = intToByteArray(v_id); 445 byte[] cb = new byte[4+sb.length]; 446 447 System.arraycopy(ba,0,cb,0,4); 448 System.arraycopy(sb,0,cb,4,sb.length); 449 int rc = command(18, cb); 450 if (rc >= 0) { 451 return readStruct(); 452 } 453 else { 454 throw new Exception("vsAttach failed on "+f_id+",v_id: "+v_id+", returned: "+rc); 455 } 456 } 457 458 synchronized int vsDetach(int v_id) throws Exception { 459 byte[] ba = intToByteArray(v_id); 460 int rc = command(21, ba); 461 if (rc >= 0) { 462 return readStruct(); 463 } 464 else { 465 throw new Exception("vsDetach failed on "+v_id+", returned: "+rc); 466 } 467 } 468 469 synchronized HDFArray vsRead(int v_id, String name, int start_idx, int nrecs, int stride) throws Exception { 470 int len = 0; 471 byte[] ba = intToByteArray(v_id); 472 len += 4; 473 byte[] sb = stringBlock(name); 474 len += sb.length; 475 byte[] st = intToByteArray(start_idx); 476 len += 4; 477 byte[] nr = intToByteArray(nrecs); 478 len += 4; 479 byte[] se = intToByteArray(stride); 480 len += 4; 481 482 byte[] cb = new byte[len]; 483 len = 0; 484 System.arraycopy(ba, 0, cb, len, ba.length); 485 len += ba.length; 486 System.arraycopy(sb, 0, cb, len, sb.length); 487 len += sb.length; 488 System.arraycopy(st, 0, cb, len, st.length); 489 len += st.length; 490 System.arraycopy(nr, 0, cb, len, nr.length); 491 len += nr.length; 492 System.arraycopy(se, 0, cb, len, se.length); 493 494 int rc = command(19, cb); 495 if (rc >= 0) { 496 String data_type = readString(); 497 int elementCount = readStruct(); 498 return readRawBlock(data_type, elementCount); 499 } 500 else { 501 throw new Exception("vsRead failed on "+v_id+",name: "+name+",(start,nrecs,stride):"+start_idx+" "+nrecs+" "+stride+", returned: "+rc); 502 } 503 } 504 505 synchronized public void close() throws IOException { 506 process.destroy(); 507 readable.close(); 508 writable.close(); 509 } 510 511 }