001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.h5; 016 017import java.lang.reflect.Array; 018import java.math.BigDecimal; 019import java.text.DecimalFormat; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Vector; 023 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027import hdf.hdf5lib.H5; 028import hdf.hdf5lib.HDF5Constants; 029import hdf.hdf5lib.HDFArray; 030import hdf.hdf5lib.HDFNativeData; 031import hdf.hdf5lib.exceptions.HDF5DataFiltersException; 032import hdf.hdf5lib.exceptions.HDF5Exception; 033import hdf.hdf5lib.exceptions.HDF5LibraryException; 034import hdf.hdf5lib.structs.H5O_info_t; 035import hdf.hdf5lib.structs.H5O_token_t; 036 037import hdf.object.Attribute; 038import hdf.object.Dataset; 039import hdf.object.Datatype; 040import hdf.object.FileFormat; 041import hdf.object.Group; 042import hdf.object.HObject; 043import hdf.object.MetaDataContainer; 044import hdf.object.ScalarDS; 045 046import hdf.object.h5.H5Attribute; 047import hdf.object.h5.H5MetaDataContainer; 048import hdf.object.h5.H5ReferenceType; 049 050/** 051 * H5ScalarDS describes a multi-dimension array of HDF5 scalar or atomic data types, such as byte, int, short, long, 052 * float, double and string, and operations performed on the scalar dataset. 053 * 054 * The library predefines a modest number of datatypes. For details, read 055 * <a href="https://hdfgroup.github.io/hdf5/_h5_t__u_g.html#sec_datatype">HDF5 Datatypes in HDF5 User Guide</a> 056 * 057 * @version 1.1 9/4/2007 058 * @author Peter X. Cao 059 */ 060public class H5ScalarDS extends ScalarDS implements MetaDataContainer 061{ 062 private static final long serialVersionUID = 2887517608230611642L; 063 064 private static final Logger log = LoggerFactory.getLogger(H5ScalarDS.class); 065 066 /** 067 * The metadata object for this data object. Members of the metadata are instances of Attribute. 068 */ 069 private H5MetaDataContainer objMetadata; 070 071 /** the object properties */ 072 private H5O_info_t objInfo; 073 074 /** the number of palettes */ 075 private int NumberOfPalettes; 076 077 /** flag to indicate if the dataset is an external dataset */ 078 private boolean isExternal = false; 079 080 /** flag to indicate if the dataset is a virtual dataset */ 081 private boolean isVirtual = false; 082 /** the list of virtual names */ 083 private List<String> virtualNameList; 084 085 /** 086 * flag to indicate if the dataset buffers should be refreshed. 087 */ 088 protected boolean refresh = false; 089 090 /** 091 * flag to indicate if the datatype in file is the same as dataype in memory 092 */ 093 protected boolean isNativeDatatype = false; 094 095 /** 096 * Constructs an instance of a H5 scalar dataset with given file, dataset name and path. 097 * 098 * For example, in H5ScalarDS(h5file, "dset", "/arrays/"), "dset" is the name of the dataset, "/arrays" is the group 099 * path of the dataset. 100 * 101 * @param theFile 102 * the file that contains the data object. 103 * @param theName 104 * the name of the data object, e.g. "dset". 105 * @param thePath 106 * the full path of the data object, e.g. "/arrays/". 107 */ 108 public H5ScalarDS(FileFormat theFile, String theName, String thePath) { 109 this(theFile, theName, thePath, null); 110 } 111 112 /** 113 * @deprecated Not for public use in the future.<br> 114 * Using {@link #H5ScalarDS(FileFormat, String, String)} 115 * 116 * @param theFile 117 * the file that contains the data object. 118 * @param theName 119 * the name of the data object, e.g. "dset". 120 * @param thePath 121 * the full path of the data object, e.g. "/arrays/". 122 * @param oid 123 * the oid of the data object. 124 */ 125 @Deprecated 126 public H5ScalarDS(FileFormat theFile, String theName, String thePath, long[] oid) { 127 super(theFile, theName, thePath, oid); 128 unsignedConverted = false; 129 NumberOfPalettes = 0; 130 objMetadata = new H5MetaDataContainer(theFile, theName, thePath, this); 131 132 if (theFile != null) { 133 if (oid == null) { 134 // retrieve the object ID 135 byte[] refBuf = null; 136 try { 137 refBuf = H5.H5Rcreate_object(theFile.getFID(), this.getFullName(), HDF5Constants.H5P_DEFAULT); 138 this.oid = HDFNativeData.byteToLong(refBuf); 139 log.trace("constructor REF {} to OID {}", refBuf, this.oid); 140 } 141 catch (Exception ex) { 142 log.debug("constructor ID {} for {} failed H5Rcreate_object", theFile.getFID(), this.getFullName()); 143 } 144 finally { 145 if (refBuf != null) 146 H5.H5Rdestroy(refBuf); 147 } 148 } 149 log.trace("constructor OID {}", this.oid); 150 try { 151 objInfo = H5.H5Oget_info_by_name(theFile.getFID(), this.getFullName(), HDF5Constants.H5O_INFO_BASIC, HDF5Constants.H5P_DEFAULT); 152 } 153 catch (Exception ex) { 154 objInfo = new H5O_info_t(-1L, null, 0, 0, 0L, 0L, 0L, 0L, 0L); 155 } 156 } 157 else { 158 this.oid = null; 159 objInfo = new H5O_info_t(-1L, null, 0, 0, 0L, 0L, 0L, 0L, 0L); 160 } 161 } 162 163 /* 164 * (non-Javadoc) 165 * 166 * @see hdf.object.HObject#open() 167 */ 168 @Override 169 public long open() { 170 long did = HDF5Constants.H5I_INVALID_HID; 171 172 if (getFID() < 0) 173 log.trace("open(): file id for:{} is invalid", getPath() + getName()); 174 else { 175 try { 176 did = H5.H5Dopen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 177 log.trace("open(): did={}", did); 178 } 179 catch (HDF5Exception ex) { 180 log.debug("open(): Failed to open dataset {}", getPath() + getName(), ex); 181 did = HDF5Constants.H5I_INVALID_HID; 182 } 183 } 184 185 return did; 186 } 187 188 /* 189 * (non-Javadoc) 190 * 191 * @see hdf.object.HObject#close(int) 192 */ 193 @Override 194 public void close(long did) { 195 if (did >= 0) { 196 try { 197 H5.H5Fflush(did, HDF5Constants.H5F_SCOPE_LOCAL); 198 } 199 catch (Exception ex) { 200 log.debug("close(): H5Fflush(did {}) failure: ", did, ex); 201 } 202 try { 203 H5.H5Dclose(did); 204 } 205 catch (HDF5Exception ex) { 206 log.debug("close(): H5Dclose(did {}) failure: ", did, ex); 207 } 208 } 209 } 210 211 /** 212 * Retrieves datatype and dataspace information from file and sets the dataset 213 * in memory. 214 * 215 * The init() is designed to support lazy operation in a dataset object. When a 216 * data object is retrieved from file, the datatype, dataspace and raw data are 217 * not loaded into memory. When it is asked to read the raw data from file, 218 * init() is first called to get the datatype and dataspace information, then 219 * load the raw data from file. 220 * 221 * init() is also used to reset the selection of a dataset (start, stride and 222 * count) to the default, which is the entire dataset for 1D or 2D datasets. In 223 * the following example, init() at step 1) retrieves datatype and dataspace 224 * information from file. getData() at step 3) reads only one data point. init() 225 * at step 4) resets the selection to the whole dataset. getData() at step 4) 226 * reads the values of whole dataset into memory. 227 * 228 * <pre> 229 * dset = (Dataset) file.get(NAME_DATASET); 230 * 231 * // 1) get datatype and dataspace information from file 232 * dset.init(); 233 * rank = dset.getRank(); // rank = 2, a 2D dataset 234 * count = dset.getSelectedDims(); 235 * start = dset.getStartDims(); 236 * dims = dset.getDims(); 237 * 238 * // 2) select only one data point 239 * for (int i = 0; i < rank; i++) { 240 * start[0] = 0; 241 * count[i] = 1; 242 * } 243 * 244 * // 3) read one data point 245 * data = dset.getData(); 246 * 247 * // 4) reset selection to the whole dataset 248 * dset.init(); 249 * 250 * // 5) clean the memory data buffer 251 * dset.clearData(); 252 * 253 * // 6) Read the whole dataset 254 * data = dset.getData(); 255 * </pre> 256 */ 257 @Override 258 public void init() { 259 if (inited) { 260 // already called. Initialize only once 261 resetSelection(); 262 log.trace("init(): H5ScalarDS already initialized"); 263 return; 264 } 265 266 long did = HDF5Constants.H5I_INVALID_HID; 267 long tid = HDF5Constants.H5I_INVALID_HID; 268 long sid = HDF5Constants.H5I_INVALID_HID; 269 long nativeTID = HDF5Constants.H5I_INVALID_HID; 270 271 did = open(); 272 if (did >= 0) { 273 try { 274 H5.H5Drefresh(did); 275 } 276 catch (Exception ex) { 277 log.debug("H5Drefresh(): ", ex); 278 } 279 // check if it is an external or virtual dataset 280 long pid = HDF5Constants.H5I_INVALID_HID; 281 try { 282 pid = H5.H5Dget_create_plist(did); 283 try { 284 int nfiles = H5.H5Pget_external_count(pid); 285 isExternal = (nfiles > 0); 286 int layoutType = H5.H5Pget_layout(pid); 287 if (isVirtual = (layoutType == HDF5Constants.H5D_VIRTUAL)) { 288 try { 289 long vmaps = H5.H5Pget_virtual_count(pid); 290 if (vmaps > 0) { 291 virtualNameList = new Vector<>(); 292 for (long next = 0; next < vmaps; next++) { 293 try { 294 String fname = H5.H5Pget_virtual_filename(pid, next); 295 virtualNameList.add(fname); 296 log.trace("init(): virtualNameList[{}]={}", next, fname); 297 } 298 catch (Exception err) { 299 log.trace("init(): vds[{}] continue", next); 300 } 301 } 302 } 303 } 304 catch (Exception err) { 305 log.debug("init(): vds count error: ", err); 306 } 307 } 308 log.trace("init(): pid={} nfiles={} isExternal={} isVirtual={}", pid, nfiles, isExternal, isVirtual); 309 } 310 catch (Exception ex) { 311 log.debug("init(): check if it is an external or virtual dataset: ", ex); 312 } 313 } 314 catch (Exception ex) { 315 log.debug("init(): H5Dget_create_plist() failure: ", ex); 316 } 317 finally { 318 try { 319 H5.H5Pclose(pid); 320 } 321 catch (Exception ex) { 322 log.debug("init(): H5Pclose(pid {}) failure: ", pid, ex); 323 } 324 } 325 326 NumberOfPalettes = readNumberOfPalette(did); 327 328 try { 329 sid = H5.H5Dget_space(did); 330 rank = H5.H5Sget_simple_extent_ndims(sid); 331 space_type = H5.H5Sget_simple_extent_type(sid); 332 if (space_type == HDF5Constants.H5S_NULL) 333 isNULL = true; 334 else 335 isNULL = false; 336 tid = H5.H5Dget_type(did); 337 log.trace("init(): tid={} sid={} rank={} space_type={} ", tid, sid, rank, space_type); 338 339 if (rank == 0) { 340 // a scalar data point 341 isScalar = true; 342 rank = 1; 343 dims = new long[] { 1 }; 344 log.trace("init(): rank is a scalar data point"); 345 } 346 else { 347 isScalar = false; 348 dims = new long[rank]; 349 maxDims = new long[rank]; 350 H5.H5Sget_simple_extent_dims(sid, dims, maxDims); 351 log.trace("init(): rank={}, dims={}, maxDims={}", rank, dims, maxDims); 352 } 353 354 try { 355 int nativeClass = H5.H5Tget_class(tid); 356 if (nativeClass == HDF5Constants.H5T_REFERENCE) { 357 long lsize = 1; 358 if (rank > 0) { 359 log.trace("init():rank={}, dims={}", rank, dims); 360 for (int j = 0; j < dims.length; j++) { 361 lsize *= dims[j]; 362 } 363 } 364 datatype = new H5ReferenceType(getFileFormat(), lsize, tid); 365 } 366 else 367 datatype = new H5Datatype(getFileFormat(), tid); 368 369 log.trace("init(): tid={} is tclass={} has isText={} : isNamed={} : isVLEN={} : isEnum={} : isUnsigned={} : isStdRef={} : isRegRef={}", 370 tid, datatype.getDatatypeClass(), ((H5Datatype) datatype).isText(), datatype.isNamed(), datatype.isVLEN(), 371 datatype.isEnum(), datatype.isUnsigned(), ((H5Datatype) datatype).isStdRef(), ((H5Datatype) datatype).isRegRef()); 372 } 373 catch (Exception ex) { 374 log.debug("init(): failed to create datatype for dataset: ", ex); 375 datatype = null; 376 } 377 378 // Check if the datatype in the file is the native datatype 379 try { 380 nativeTID = H5.H5Tget_native_type(tid); 381 isNativeDatatype = H5.H5Tequal(tid, nativeTID); 382 log.trace("init(): isNativeDatatype={}", isNativeDatatype); 383 } 384 catch (Exception ex) { 385 log.debug("init(): check if native type failure: ", ex); 386 } 387 388 try { 389 pid = H5.H5Dget_create_plist(did); 390 int[] fillStatus = { 0 }; 391 if (H5.H5Pfill_value_defined(pid, fillStatus) >= 0) { 392 // Check if fill value is user-defined before retrieving it. 393 if (fillStatus[0] == HDF5Constants.H5D_FILL_VALUE_USER_DEFINED) { 394 try { 395 fillValue = H5Datatype.allocateArray((H5Datatype) datatype, 1); 396 } 397 catch (OutOfMemoryError e) { 398 log.debug("init(): out of memory: ", e); 399 fillValue = null; 400 } 401 catch (Exception ex) { 402 log.debug("init(): allocate fill value buffer failed: ", ex); 403 fillValue = null; 404 } 405 406 log.trace("init(): fillValue={}", fillValue); 407 try { 408 H5.H5Pget_fill_value(pid, nativeTID, fillValue); 409 log.trace("init(): H5Pget_fill_value={}", fillValue); 410 if (fillValue != null) { 411 if (datatype.isUnsigned() && !isFillValueConverted) { 412 fillValue = ScalarDS.convertFromUnsignedC(fillValue, null); 413 isFillValueConverted = true; 414 } 415 416 int n = Array.getLength(fillValue); 417 for (int i = 0; i < n; i++) 418 addFilteredImageValue((Number) Array.get(fillValue, i)); 419 } 420 } 421 catch (Exception ex2) { 422 log.debug("init(): fill value was defined: ", ex2); 423 fillValue = null; 424 } 425 } 426 } 427 } 428 catch (HDF5Exception ex) { 429 log.debug("init(): check if fill value is defined failure: ", ex); 430 } 431 finally { 432 try { 433 H5.H5Pclose(pid); 434 } 435 catch (Exception ex) { 436 log.debug("init(): H5Pclose(pid {}) failure: ", pid, ex); 437 } 438 } 439 440 inited = true; 441 } 442 catch (HDF5Exception ex) { 443 log.debug("init(): ", ex); 444 } 445 finally { 446 try { 447 H5.H5Tclose(nativeTID); 448 } 449 catch (Exception ex2) { 450 log.debug("init(): H5Tclose(nativeTID {}) failure: ", nativeTID, ex2); 451 } 452 try { 453 H5.H5Tclose(tid); 454 } 455 catch (HDF5Exception ex2) { 456 log.debug("init(): H5Tclose(tid {}) failure: ", tid, ex2); 457 } 458 try { 459 H5.H5Sclose(sid); 460 } 461 catch (HDF5Exception ex2) { 462 log.debug("init(): H5Sclose(sid {}) failure: ", sid, ex2); 463 } 464 } 465 466 // check for the type of image and interlace mode 467 // it is a true color image at one of three cases: 468 // 1) IMAGE_SUBCLASS = IMAGE_TRUECOLOR, 469 // 2) INTERLACE_MODE = INTERLACE_PIXEL, 470 // 3) INTERLACE_MODE = INTERLACE_PLANE 471 if ((rank >= 3) && isImage) { 472 interlace = -1; 473 isTrueColor = isStringAttributeOf(did, "IMAGE_SUBCLASS", "IMAGE_TRUECOLOR"); 474 475 if (isTrueColor) { 476 interlace = INTERLACE_PIXEL; 477 if (isStringAttributeOf(did, "INTERLACE_MODE", "INTERLACE_PLANE")) { 478 interlace = INTERLACE_PLANE; 479 } 480 } 481 } 482 483 close(did); 484 485 startDims = new long[rank]; 486 selectedDims = new long[rank]; 487 488 resetSelection(); 489 } 490 else { 491 log.debug("init(): failed to open dataset"); 492 } 493 refresh = false; 494 } 495 496 /** 497 * Get the token for this object. 498 * 499 * @return true if it has any attributes, false otherwise. 500 */ 501 public long[] getToken() { 502 H5O_token_t token = objInfo.token; 503 return HDFNativeData.byteToLong(token.data); 504 } 505 506 /** 507 * Check if the object has any attributes attached. 508 * 509 * @return true if it has any attributes, false otherwise. 510 */ 511 @Override 512 public boolean hasAttribute() { 513 objInfo.num_attrs = objMetadata.getObjectAttributeSize(); 514 515 if (objInfo.num_attrs < 0) { 516 long did = open(); 517 if (did >= 0) { 518 objInfo.num_attrs = 0; 519 520 try { 521 objInfo = H5.H5Oget_info(did); 522 523 if(objInfo.num_attrs > 0) { 524 // test if it is an image 525 // check image 526 Object avalue = getAttrValue(did, "CLASS"); 527 if (avalue != null) { 528 try { 529 isImageDisplay = isImage = "IMAGE".equalsIgnoreCase(new String((byte[]) avalue).trim()); 530 log.trace("hasAttribute(): isImageDisplay dataset: {} with value = {}", isImageDisplay, avalue); 531 } 532 catch (Exception err) { 533 log.debug("hasAttribute(): check image: ", err); 534 } 535 } 536 537 // retrieve the IMAGE_MINMAXRANGE 538 avalue = getAttrValue(did, "IMAGE_MINMAXRANGE"); 539 if (avalue != null) { 540 double x0 = 0; 541 double x1 = 0; 542 try { 543 x0 = Double.parseDouble(java.lang.reflect.Array.get(avalue, 0).toString()); 544 x1 = Double.parseDouble(java.lang.reflect.Array.get(avalue, 1).toString()); 545 } 546 catch (Exception ex2) { 547 x0 = x1 = 0; 548 } 549 if (x1 > x0) { 550 imageDataRange = new double[2]; 551 imageDataRange[0] = x0; 552 imageDataRange[1] = x1; 553 } 554 } 555 556 try { 557 checkCFconvention(did); 558 } 559 catch (Exception ex) { 560 log.debug("hasAttribute(): checkCFconvention(did {}):", did, ex); 561 } 562 } 563 } 564 catch (Exception ex) { 565 objInfo.num_attrs = 0; 566 log.debug("hasAttribute(): get object info failure: ", ex); 567 } 568 finally { 569 close(did); 570 } 571 objMetadata.setObjectAttributeSize((int) objInfo.num_attrs); 572 } 573 else { 574 log.debug("hasAttribute(): could not open dataset"); 575 } 576 } 577 578 log.trace("hasAttribute(): nAttributes={}", objInfo.num_attrs); 579 return (objInfo.num_attrs > 0); 580 } 581 582 /** 583 * Returns the datatype of the data object. 584 * 585 * @return the datatype of the data object. 586 */ 587 @Override 588 public Datatype getDatatype() { 589 if (!inited) 590 init(); 591 592 if (datatype == null) { 593 long did = HDF5Constants.H5I_INVALID_HID; 594 long tid = HDF5Constants.H5I_INVALID_HID; 595 596 did = open(); 597 if (did >= 0) { 598 try { 599 tid = H5.H5Dget_type(did); 600 log.trace("getDatatype(): isNativeDatatype={}", isNativeDatatype); 601 if (!isNativeDatatype) { 602 long tmptid = -1; 603 try { 604 tmptid = H5Datatype.toNative(tid); 605 if (tmptid >= 0) { 606 try { 607 H5.H5Tclose(tid); 608 } 609 catch (Exception ex2) { 610 log.debug("getDatatype(): H5Tclose(tid {}) failure: ", tid, ex2); 611 } 612 tid = tmptid; 613 } 614 } 615 catch (Exception ex) { 616 log.debug("getDatatype(): toNative: ", ex); 617 } 618 } 619 int nativeClass = H5.H5Tget_class(tid); 620 if (nativeClass == HDF5Constants.H5T_REFERENCE) { 621 long lsize = 1; 622 if (rank > 0) { 623 log.trace("getDatatype(): rank={}, dims={}", rank, dims); 624 for (int j = 0; j < dims.length; j++) { 625 lsize *= dims[j]; 626 } 627 } 628 datatype = new H5ReferenceType(getFileFormat(), lsize, tid); 629 } 630 else 631 datatype = new H5Datatype(getFileFormat(), tid); 632 } 633 catch (Exception ex) { 634 log.debug("getDatatype(): ", ex); 635 } 636 finally { 637 try { 638 H5.H5Tclose(tid); 639 } 640 catch (HDF5Exception ex) { 641 log.debug("getDatatype(): H5Tclose(tid {}) failure: ", tid, ex); 642 } 643 try { 644 H5.H5Dclose(did); 645 } 646 catch (HDF5Exception ex) { 647 log.debug("getDatatype(): H5Dclose(did {}) failure: ", did, ex); 648 } 649 } 650 } 651 } 652 653 if (isExternal) { 654 String pdir = this.getFileFormat().getAbsoluteFile().getParent(); 655 656 if (pdir == null) { 657 pdir = "."; 658 } 659 System.setProperty("user.dir", pdir); 660 log.trace("getDatatype(): External dataset: user.dir={}", pdir); 661 } 662 663 return datatype; 664 } 665 666 /** 667 * Refreshes the dataset before re-read of data. 668 */ 669 @Override 670 public Object refreshData() { 671 inited = false; 672 refresh = true; 673 674 init(); 675 return super.refreshData(); 676 } 677 678 /** 679 * Removes all of the elements from metadata list. 680 * The list should be empty after this call returns. 681 */ 682 @Override 683 public void clear() { 684 super.clear(); 685 objMetadata.clear(); 686 } 687 688 /* 689 * (non-Javadoc) 690 * 691 * @see hdf.object.Dataset#readBytes() 692 */ 693 @Override 694 public byte[] readBytes() throws HDF5Exception { 695 byte[] theData = null; 696 697 if (!isInited()) 698 init(); 699 700 long did = open(); 701 if (did >= 0) { 702 long fspace = HDF5Constants.H5I_INVALID_HID; 703 long mspace = HDF5Constants.H5I_INVALID_HID; 704 long tid = HDF5Constants.H5I_INVALID_HID; 705 706 try { 707 long[] lsize = { 1 }; 708 for (int j = 0; j < selectedDims.length; j++) 709 lsize[0] *= selectedDims[j]; 710 711 fspace = H5.H5Dget_space(did); 712 mspace = H5.H5Screate_simple(rank, selectedDims, null); 713 714 // set the rectangle selection 715 // HDF5 bug: for scalar dataset, H5Sselect_hyperslab gives core dump 716 if (rank * dims[0] > 1) 717 H5.H5Sselect_hyperslab(fspace, HDF5Constants.H5S_SELECT_SET, startDims, selectedStride, selectedDims, null); // set block to 1 718 719 tid = H5.H5Dget_type(did); 720 long size = H5.H5Tget_size(tid) * lsize[0]; 721 log.trace("readBytes(): size = {}", size); 722 723 if (size < Integer.MIN_VALUE || size > Integer.MAX_VALUE) 724 throw new Exception("Invalid int size"); 725 726 theData = new byte[(int)size]; 727 728 log.trace("readBytes(): H5Dread: did={} tid={} fspace={} mspace={}", did, tid, fspace, mspace); 729 H5.H5Dread(did, tid, mspace, fspace, HDF5Constants.H5P_DEFAULT, theData); 730 } 731 catch (Exception ex) { 732 log.debug("readBytes(): failed to read data: ", ex); 733 } 734 finally { 735 try { 736 H5.H5Sclose(fspace); 737 } 738 catch (Exception ex2) { 739 log.debug("readBytes(): H5Sclose(fspace {}) failure: ", fspace, ex2); 740 } 741 try { 742 H5.H5Sclose(mspace); 743 } 744 catch (Exception ex2) { 745 log.debug("readBytes(): H5Sclose(mspace {}) failure: ", mspace, ex2); 746 } 747 try { 748 H5.H5Tclose(tid); 749 } 750 catch (HDF5Exception ex2) { 751 log.debug("readBytes(): H5Tclose(tid {}) failure: ", tid, ex2); 752 } 753 close(did); 754 } 755 } 756 757 return theData; 758 } 759 760 /** 761 * Reads the data from file. 762 * 763 * read() reads the data from file to a memory buffer and returns the memory 764 * buffer. The dataset object does not hold the memory buffer. To store the 765 * memory buffer in the dataset object, one must call getData(). 766 * 767 * By default, the whole dataset is read into memory. Users can also select 768 * a subset to read. Subsetting is done in an implicit way. 769 * 770 * <b>How to Select a Subset</b> 771 * 772 * A selection is specified by three arrays: start, stride and count. 773 * <ol> 774 * <li>start: offset of a selection 775 * <li>stride: determines how many elements to move in each dimension 776 * <li>count: number of elements to select in each dimension 777 * </ol> 778 * getStartDims(), getStride() and getSelectedDims() returns the start, 779 * stride and count arrays respectively. Applications can make a selection 780 * by changing the values of the arrays. 781 * 782 * The following example shows how to make a subset. In the example, the 783 * dataset is a 4-dimensional array of [200][100][50][10], i.e. dims[0]=200; 784 * dims[1]=100; dims[2]=50; dims[3]=10; <br> 785 * We want to select every other data point in dims[1] and dims[2] 786 * 787 * <pre> 788 * int rank = dataset.getRank(); // number of dimensions of the dataset 789 * long[] dims = dataset.getDims(); // the dimension sizes of the dataset 790 * long[] selected = dataset.getSelectedDims(); // the selected size of the 791 * // dataset 792 * long[] start = dataset.getStartDims(); // the offset of the selection 793 * long[] stride = dataset.getStride(); // the stride of the dataset 794 * int[] selectedIndex = dataset.getSelectedIndex(); // the selected 795 * // dimensions for 796 * // display 797 * 798 * // select dim1 and dim2 as 2D data for display, and slice through dim0 799 * selectedIndex[0] = 1; 800 * selectedIndex[1] = 2; 801 * selectedIndex[1] = 0; 802 * 803 * // reset the selection arrays 804 * for (int i = 0; i < rank; i++) { 805 * start[i] = 0; 806 * selected[i] = 1; 807 * stride[i] = 1; 808 * } 809 * 810 * // set stride to 2 on dim1 and dim2 so that every other data point is 811 * // selected. 812 * stride[1] = 2; 813 * stride[2] = 2; 814 * 815 * // set the selection size of dim1 and dim2 816 * selected[1] = dims[1] / stride[1]; 817 * selected[2] = dims[1] / stride[2]; 818 * 819 * // when dataset.getData() is called, the selection above will be used 820 * // since 821 * // the dimension arrays are passed by reference. Changes of these arrays 822 * // outside the dataset object directly change the values of these array 823 * // in the dataset object. 824 * </pre> 825 * 826 * For ScalarDS, the memory data buffer is a one-dimensional array of byte, 827 * short, int, float, double or String type based on the datatype of the 828 * dataset. 829 * 830 * @return the data read from file. 831 * 832 * @see #getData() 833 * @see hdf.object.DataFormat#read() 834 * 835 * @throws Exception 836 * if object can not be read 837 */ 838 @Override 839 public Object read() throws Exception { 840 Object readData = null; 841 842 if (!isInited()) 843 init(); 844 845 try { 846 readData = scalarDatasetCommonIO(H5File.IO_TYPE.READ, null); 847 } 848 catch (Exception ex) { 849 log.debug("read(): failed to read scalar dataset: ", ex); 850 throw new Exception("failed to read scalar dataset: " + ex.getMessage(), ex); 851 } 852 853 return readData; 854 } 855 856 /** 857 * Writes the given data buffer into this dataset in a file. 858 * 859 * @param buf 860 * The buffer that contains the data values. 861 * 862 * @throws Exception 863 * If there is an error at the HDF5 library level. 864 */ 865 @Override 866 public void write(Object buf) throws Exception { 867 if (this.getFileFormat().isReadOnly()) 868 throw new Exception("cannot write to scalar dataset in file opened as read-only"); 869 870 if (!isInited()) 871 init(); 872 873 try { 874 scalarDatasetCommonIO(H5File.IO_TYPE.WRITE, buf); 875 } 876 catch (Exception ex) { 877 log.debug("write(Object): failed to write to scalar dataset: ", ex); 878 throw new Exception("failed to write to scalar dataset: " + ex.getMessage(), ex); 879 } 880 } 881 882 private Object scalarDatasetCommonIO(H5File.IO_TYPE ioType, Object writeBuf) throws Exception { 883 H5Datatype dsDatatype = (H5Datatype) getDatatype(); 884 H5Datatype dsBaseDatatype = (H5Datatype) getDatatype().getDatatypeBase(); 885 boolean BDTisRef = false; 886 if (dsBaseDatatype != null) 887 BDTisRef = dsBaseDatatype.isStdRef(); 888 Object theData = null; 889 890 /* 891 * I/O type-specific pre-initialization. 892 */ 893 if (ioType == H5File.IO_TYPE.WRITE) { 894 if (writeBuf == null) { 895 log.debug("scalarDatasetCommonIO(): writeBuf is null"); 896 throw new Exception("write buffer is null"); 897 } 898 } 899 900 long did = open(); 901 if (did >= 0) { 902 long[] spaceIDs = { HDF5Constants.H5I_INVALID_HID, HDF5Constants.H5I_INVALID_HID }; // spaceIDs[0]=mspace, spaceIDs[1]=fspace 903 904 try { 905 /* 906 * NOTE: this call sets up a hyperslab selection in the file according to the 907 * current selection in the dataset object. 908 */ 909 long totalSelectedSpacePoints = H5Utils.getTotalSelectedSpacePoints(did, dims, startDims, 910 selectedStride, selectedDims, spaceIDs); 911 912 if (ioType == H5File.IO_TYPE.READ) { 913 log.trace("scalarDatasetCommonIO():read ioType isNamed={} isEnum={} isText={} isRefObj={}", dsDatatype.isNamed(), dsDatatype.isEnum(), dsDatatype.isText(), dsDatatype.isRefObj()); 914 if (dsDatatype.isVarStr()) { 915 try { 916 theData = H5Datatype.allocateArray(dsDatatype, (int)totalSelectedSpacePoints); 917 } 918 catch (OutOfMemoryError err) { 919 log.debug("scalarDatasetCommonIO(): Out of memory"); 920 throw new HDF5Exception("Out Of Memory"); 921 } 922 } 923 else if (dsDatatype.isVLEN()) { 924 theData = new ArrayList[(int)totalSelectedSpacePoints]; 925 for (int j = 0; j < (int)totalSelectedSpacePoints; j++) 926 ((ArrayList[])theData)[j] = new ArrayList<byte[]>(); 927 } 928 else if ((originalBuf == null) || dsDatatype.isEnum() || dsDatatype.isText() || dsDatatype.isRefObj() 929 || ((originalBuf != null) && (totalSelectedSpacePoints != nPoints))) { 930 try { 931 theData = H5Datatype.allocateArray(dsDatatype, (int)totalSelectedSpacePoints); 932 } 933 catch (OutOfMemoryError err) { 934 log.debug("scalarDatasetCommonIO(): Out of memory"); 935 throw new HDF5Exception("Out Of Memory"); 936 } 937 } 938 else { 939 // reuse the buffer if the size is the same 940 log.trace("scalarDatasetCommonIO():read ioType reuse the buffer if the size is the same"); 941 theData = originalBuf; 942 } 943 944 if (theData != null) { 945 /* 946 * Actually read the data now that everything has been setup. 947 */ 948 long tid = HDF5Constants.H5I_INVALID_HID; 949 try { 950 log.trace("scalarDatasetCommonIO():read ioType create native"); 951 tid = dsDatatype.createNative(); 952 953 if (dsDatatype.isVarStr()) { 954 log.trace("scalarDatasetCommonIO(): H5Dread_VLStrings did={} tid={} spaceIDs[0]={} spaceIDs[1]={}", 955 did, tid, (spaceIDs[0] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[0], 956 (spaceIDs[1] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[1]); 957 958 H5.H5Dread_VLStrings(did, tid, spaceIDs[0], spaceIDs[1], HDF5Constants.H5P_DEFAULT, 959 (Object[]) theData); 960 } 961 else if (dsDatatype.isVLEN() || (dsDatatype.isArray() && dsDatatype.getDatatypeBase().isVLEN())) { 962 log.trace("scalarDatasetCommonIO(): H5DreadVL did={} tid={} spaceIDs[0]={} spaceIDs[1]={}", 963 did, tid, (spaceIDs[0] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[0], 964 (spaceIDs[1] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[1]); 965 966 H5.H5DreadVL(did, tid, spaceIDs[0], spaceIDs[1], HDF5Constants.H5P_DEFAULT, 967 (Object[]) theData); 968 } 969 else { 970 log.trace("scalarDatasetCommonIO(): H5Dread did={} tid={} spaceIDs[0]={} spaceIDs[1]={}", 971 did, tid, (spaceIDs[0] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[0], 972 (spaceIDs[1] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[1]); 973 974 H5.H5Dread(did, tid, spaceIDs[0], spaceIDs[1], HDF5Constants.H5P_DEFAULT, theData); 975 } 976 } 977 catch (HDF5DataFiltersException exfltr) { 978 log.debug("scalarDatasetCommonIO(): read failure: ", exfltr); 979 throw new Exception("Filter not available exception: " + exfltr.getMessage(), exfltr); 980 } 981 catch (Exception ex) { 982 log.debug("scalarDatasetCommonIO(): read failure: ", ex); 983 throw new Exception(ex.getMessage(), ex); 984 } 985 finally { 986 dsDatatype.close(tid); 987 } 988 989 /* 990 * Perform any necessary data conversions. 991 */ 992 if (dsDatatype.isText() && convertByteToString && (theData instanceof byte[])) { 993 log.trace("scalarDatasetCommonIO(): isText: converting byte array to string array"); 994 theData = byteToString((byte[]) theData, (int) dsDatatype.getDatatypeSize()); 995 } 996 else if (dsDatatype.isFloat() && dsDatatype.getDatatypeSize() == 16) { 997 log.trace("scalarDatasetCommonIO(): isFloat: converting byte array to BigDecimal array"); 998 theData = dsDatatype.byteToBigDecimal(0, (int)totalSelectedSpacePoints, (byte[]) theData); 999 } 1000 else if (dsDatatype.isArray() && dsDatatype.getDatatypeBase().isFloat() && dsDatatype.getDatatypeBase().getDatatypeSize() == 16) { 1001 log.trace("scalarDatasetCommonIO(): isArray and isFloat: converting byte array to BigDecimal array"); 1002 long[] arrayDims = dsDatatype.getArrayDims(); 1003 int asize = (int)totalSelectedSpacePoints; 1004 for (int j = 0; j < arrayDims.length; j++) { 1005 asize *= arrayDims[j]; 1006 } 1007 theData = ((H5Datatype)dsDatatype.getDatatypeBase()).byteToBigDecimal(0, asize, (byte[]) theData); 1008 } 1009 else if (dsDatatype.isRef() && (theData instanceof byte[])) { 1010 log.trace("AttributeCommonIO():read ioType isRef: converting byte array to List of bytes"); 1011 ArrayList<byte[]> theListData = new ArrayList<>((int)totalSelectedSpacePoints); 1012 for (int m = 0; m < (int) totalSelectedSpacePoints; m++) { 1013 byte[] curBytes = new byte[(int)dsDatatype.getDatatypeSize()]; 1014 try { 1015 System.arraycopy(theData, m * (int)dsDatatype.getDatatypeSize(), curBytes, 0, (int)dsDatatype.getDatatypeSize()); 1016 theListData.add(curBytes); 1017 } 1018 catch (Exception err) { 1019 log.trace("AttributeCommonIO(): arraycopy failure: ", err); 1020 } 1021 } 1022 theData = theListData; 1023 } 1024 } 1025 } // H5File.IO_TYPE.READ 1026 else { 1027 /* 1028 * Perform any necessary data conversions before writing the data. 1029 * 1030 * Note that v-len strings do not get converted, regardless of 1031 * conversion request type. 1032 */ 1033 Object tmpData = writeBuf; 1034 try { 1035 // Check if we need to convert integer data 1036 int tsize = (int) dsDatatype.getDatatypeSize(); 1037 String cname = writeBuf.getClass().getName(); 1038 log.trace("scalarDatasetCommonIO(): cname={} of datatype size={}", cname, tsize); 1039 char dname = cname.charAt(cname.lastIndexOf("[") + 1); 1040 boolean doIntConversion = (((tsize == 1) && (dname == 'S')) || ((tsize == 2) && (dname == 'I')) 1041 || ((tsize == 4) && (dname == 'J')) || (dsDatatype.isUnsigned() && unsignedConverted)); 1042 1043 if (doIntConversion) { 1044 log.trace("scalarDatasetCommonIO(): converting integer data to unsigned C-type integers"); 1045 tmpData = convertToUnsignedC(writeBuf, null); 1046 } 1047 else if (dsDatatype.isText() && !dsDatatype.isVarStr() && convertByteToString && !(writeBuf instanceof byte[])) { 1048 log.trace("scalarDatasetCommonIO(): converting string array to byte array"); 1049 tmpData = stringToByte((String[]) writeBuf, tsize); 1050 } 1051 else if (dsDatatype.isEnum() && (Array.get(writeBuf, 0) instanceof String)) { 1052 log.trace("scalarDatasetCommonIO(): converting enum names to values"); 1053 tmpData = dsDatatype.convertEnumNameToValue((String[]) writeBuf); 1054 } 1055 else if (dsDatatype.isFloat() && dsDatatype.getDatatypeSize() == 16) { 1056 log.trace("scalarDatasetCommonIO(): isFloat: converting BigDecimal array to byte array"); 1057 throw new Exception("data conversion failure: cannot write BigDecimal values"); 1058 //tmpData = dsDatatype.bigDecimalToByte(0, (int)totalSelectedSpacePoints, (BigDecimal[]) writeBuf); 1059 } 1060 } 1061 catch (Exception ex) { 1062 log.debug("scalarDatasetCommonIO(): data conversion failure: ", ex); 1063 throw new Exception("data conversion failure: " + ex.getMessage()); 1064 } 1065 1066 /* 1067 * Actually write the data now that everything has been setup. 1068 */ 1069 long tid = HDF5Constants.H5I_INVALID_HID; 1070 try { 1071 tid = dsDatatype.createNative(); 1072 1073 if (dsDatatype.isVarStr()) { 1074 log.trace("scalarDatasetCommonIO(): H5Dwrite_VLStrings did={} tid={} spaceIDs[0]={} spaceIDs[1]={}", 1075 did, tid, (spaceIDs[0] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[0], 1076 (spaceIDs[1] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[1]); 1077 1078 H5.H5Dwrite_VLStrings(did, tid, spaceIDs[0], spaceIDs[1], HDF5Constants.H5P_DEFAULT, (Object[]) tmpData); 1079 } 1080 else if (dsDatatype.isVLEN() || (dsDatatype.isArray() && dsDatatype.getDatatypeBase().isVLEN())) { 1081 log.trace("scalarDatasetCommonIO(): H5DwriteVL did={} tid={} spaceIDs[0]={} spaceIDs[1]={}", 1082 did, tid, (spaceIDs[0] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[0], 1083 (spaceIDs[1] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[1]); 1084 1085 H5.H5DwriteVL(did, tid, spaceIDs[0], spaceIDs[1], HDF5Constants.H5P_DEFAULT, (Object[]) tmpData); 1086 } 1087 else { 1088 log.trace("scalarDatasetCommonIO(): H5Dwrite did={} tid={} spaceIDs[0]={} spaceIDs[1]={}", 1089 did, tid, (spaceIDs[0] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[0], 1090 (spaceIDs[1] == HDF5Constants.H5P_DEFAULT) ? "H5P_DEFAULT" : spaceIDs[1]); 1091 1092 H5.H5Dwrite(did, tid, spaceIDs[0], spaceIDs[1], HDF5Constants.H5P_DEFAULT, tmpData); 1093 } 1094 } 1095 catch (Exception ex) { 1096 log.debug("scalarDatasetCommonIO(): write failure: ", ex); 1097 throw new Exception(ex.getMessage()); 1098 } 1099 finally { 1100 dsDatatype.close(tid); 1101 } 1102 } // H5File.IO_TYPE.WRITE 1103 } 1104 finally { 1105 if (HDF5Constants.H5S_ALL != spaceIDs[0]) { 1106 try { 1107 H5.H5Sclose(spaceIDs[0]); 1108 } 1109 catch (Exception ex) { 1110 log.debug("scalarDatasetCommonIO(): H5Sclose(spaceIDs[0] {}) failure: ", spaceIDs[0], ex); 1111 } 1112 } 1113 1114 if (HDF5Constants.H5S_ALL != spaceIDs[1]) { 1115 try { 1116 H5.H5Sclose(spaceIDs[1]); 1117 } 1118 catch (Exception ex) { 1119 log.debug("scalarDatasetCommonIO(): H5Sclose(spaceIDs[1] {}) failure: ", spaceIDs[1], ex); 1120 } 1121 } 1122 1123 close(did); 1124 } 1125 } 1126 else 1127 log.debug("scalarDatasetCommonIO(): failed to open dataset"); 1128 1129 return theData; 1130 } 1131 1132 /** 1133 * Retrieves the object's metadata, such as attributes, from the file. 1134 * 1135 * Metadata, such as attributes, is stored in a List. 1136 * 1137 * @return the list of metadata objects. 1138 * 1139 * @throws HDF5Exception 1140 * if the metadata can not be retrieved 1141 */ 1142 @Override 1143 public List<Attribute> getMetadata() throws HDF5Exception { 1144 int gmIndexType = 0; 1145 int gmIndexOrder = 0; 1146 1147 try { 1148 gmIndexType = fileFormat.getIndexType(null); 1149 } 1150 catch (Exception ex) { 1151 log.debug("getMetadata(): getIndexType failed: ", ex); 1152 } 1153 try { 1154 gmIndexOrder = fileFormat.getIndexOrder(null); 1155 } 1156 catch (Exception ex) { 1157 log.debug("getMetadata(): getIndexOrder failed: ", ex); 1158 } 1159 return this.getMetadata(gmIndexType, gmIndexOrder); 1160 } 1161 1162 /** 1163 * Retrieves the object's metadata, such as attributes, from the file. 1164 * 1165 * Metadata, such as attributes, is stored in a List. 1166 * 1167 * @param attrPropList 1168 * the list of properties to get 1169 * 1170 * @return the list of metadata objects. 1171 * 1172 * @throws HDF5Exception 1173 * if the metadata can not be retrieved 1174 */ 1175 public List<Attribute> getMetadata(int... attrPropList) throws HDF5Exception { 1176 if (!isInited()) 1177 init(); 1178 1179 try { 1180 this.linkTargetObjName = H5File.getLinkTargetName(this); 1181 } 1182 catch (Exception ex) { 1183 log.debug("getMetadata(): getLinkTargetName failed: ", ex); 1184 } 1185 1186 if (objMetadata.getAttributeList() == null) { 1187 long did = HDF5Constants.H5I_INVALID_HID; 1188 long pcid = HDF5Constants.H5I_INVALID_HID; 1189 long paid = HDF5Constants.H5I_INVALID_HID; 1190 1191 did = open(); 1192 if (did >= 0) { 1193 try { 1194 // get the compression and chunk information 1195 pcid = H5.H5Dget_create_plist(did); 1196 paid = H5.H5Dget_access_plist(did); 1197 long storageSize = H5.H5Dget_storage_size(did); 1198 int nfilt = H5.H5Pget_nfilters(pcid); 1199 int layoutType = H5.H5Pget_layout(pcid); 1200 1201 storageLayout.setLength(0); 1202 compression.setLength(0); 1203 1204 if (layoutType == HDF5Constants.H5D_CHUNKED) { 1205 chunkSize = new long[rank]; 1206 H5.H5Pget_chunk(pcid, rank, chunkSize); 1207 int n = chunkSize.length; 1208 storageLayout.append("CHUNKED: ").append(chunkSize[0]); 1209 for (int i = 1; i < n; i++) 1210 storageLayout.append(" X ").append(chunkSize[i]); 1211 1212 if (nfilt > 0) { 1213 long nelmts = 1; 1214 long uncompSize; 1215 long datumSize = getDatatype().getDatatypeSize(); 1216 1217 if (datumSize < 0) { 1218 long tmptid = HDF5Constants.H5I_INVALID_HID; 1219 try { 1220 tmptid = H5.H5Dget_type(did); 1221 datumSize = H5.H5Tget_size(tmptid); 1222 } 1223 finally { 1224 try { 1225 H5.H5Tclose(tmptid); 1226 } 1227 catch (Exception ex2) { 1228 log.debug("getMetadata(): H5Tclose(tmptid {}) failure: ", tmptid, ex2); 1229 } 1230 } 1231 } 1232 1233 for (int i = 0; i < rank; i++) 1234 nelmts *= dims[i]; 1235 uncompSize = nelmts * datumSize; 1236 1237 /* compression ratio = uncompressed size / compressed size */ 1238 1239 if (storageSize != 0) { 1240 double ratio = (double) uncompSize / (double) storageSize; 1241 DecimalFormat df = new DecimalFormat(); 1242 df.setMinimumFractionDigits(3); 1243 df.setMaximumFractionDigits(3); 1244 compression.append(df.format(ratio)).append(":1"); 1245 } 1246 } 1247 } 1248 else if (layoutType == HDF5Constants.H5D_COMPACT) { 1249 storageLayout.append("COMPACT"); 1250 } 1251 else if (layoutType == HDF5Constants.H5D_CONTIGUOUS) { 1252 storageLayout.append("CONTIGUOUS"); 1253 if (H5.H5Pget_external_count(pcid) > 0) 1254 storageLayout.append(" - EXTERNAL "); 1255 } 1256 else if (layoutType == HDF5Constants.H5D_VIRTUAL) { 1257 storageLayout.append("VIRTUAL - "); 1258 try { 1259 long vmaps = H5.H5Pget_virtual_count(pcid); 1260 try { 1261 int virtView = H5.H5Pget_virtual_view(paid); 1262 long virtGap = H5.H5Pget_virtual_printf_gap(paid); 1263 if (virtView == HDF5Constants.H5D_VDS_FIRST_MISSING) 1264 storageLayout.append("First Missing"); 1265 else 1266 storageLayout.append("Last Available"); 1267 storageLayout.append("\nGAP : ").append(virtGap); 1268 } 1269 catch (Exception err) { 1270 log.debug("getMetadata(): vds error: ", err); 1271 storageLayout.append("ERROR"); 1272 } 1273 storageLayout.append("\nMAPS : ").append(vmaps); 1274 if (vmaps > 0) { 1275 for (long next = 0; next < vmaps; next++) { 1276 try { 1277 H5.H5Pget_virtual_vspace(pcid, next); 1278 H5.H5Pget_virtual_srcspace(pcid, next); 1279 String fname = H5.H5Pget_virtual_filename(pcid, next); 1280 String dsetname = H5.H5Pget_virtual_dsetname(pcid, next); 1281 storageLayout.append("\n").append(fname).append(" : ").append(dsetname); 1282 } 1283 catch (Exception err) { 1284 log.debug("getMetadata(): vds space[{}] error: ", next, err); 1285 storageLayout.append("ERROR"); 1286 } 1287 } 1288 } 1289 } 1290 catch (Exception err) { 1291 log.debug("getMetadata(): vds count error: ", err); 1292 storageLayout.append("ERROR"); 1293 } 1294 } 1295 else { 1296 chunkSize = null; 1297 storageLayout.append("NONE"); 1298 } 1299 1300 int[] flags = { 0, 0 }; 1301 long[] cdNelmts = { 20 }; 1302 int[] cdValues = new int[(int) cdNelmts[0]]; 1303 String[] cdName = { "", "" }; 1304 log.trace("getMetadata(): {} filters in pipeline", nfilt); 1305 int filter = -1; 1306 int[] filterConfig = { 1 }; 1307 1308 filters.setLength(0); 1309 1310 if (nfilt == 0) { 1311 filters.append("NONE"); 1312 } 1313 else { 1314 for (int i = 0, k = 0; i < nfilt; i++) { 1315 log.trace("getMetadata(): filter[{}]", i); 1316 if (i > 0) 1317 filters.append(", "); 1318 if (k > 0) 1319 compression.append(", "); 1320 1321 try { 1322 cdNelmts[0] = 20; 1323 cdValues = new int[(int) cdNelmts[0]]; 1324 cdValues = new int[(int) cdNelmts[0]]; 1325 filter = H5.H5Pget_filter(pcid, i, flags, cdNelmts, cdValues, 120, cdName, filterConfig); 1326 log.trace("getMetadata(): filter[{}] is {} has {} elements ", i, cdName[0], cdNelmts[0]); 1327 for (int j = 0; j < cdNelmts[0]; j++) 1328 log.trace("getMetadata(): filter[{}] element {} = {}", i, j, cdValues[j]); 1329 } 1330 catch (Exception err) { 1331 log.debug("getMetadata(): filter[{}] error: ", i, err); 1332 filters.append("ERROR"); 1333 continue; 1334 } 1335 1336 if (filter == HDF5Constants.H5Z_FILTER_NONE) { 1337 filters.append("NONE"); 1338 } 1339 else if (filter == HDF5Constants.H5Z_FILTER_DEFLATE) { 1340 filters.append("GZIP"); 1341 compression.append(COMPRESSION_GZIP_TXT).append(cdValues[0]); 1342 k++; 1343 } 1344 else if (filter == HDF5Constants.H5Z_FILTER_FLETCHER32) { 1345 filters.append("Error detection filter"); 1346 } 1347 else if (filter == HDF5Constants.H5Z_FILTER_SHUFFLE) { 1348 filters.append("SHUFFLE: Nbytes = ").append(cdValues[0]); 1349 } 1350 else if (filter == HDF5Constants.H5Z_FILTER_NBIT) { 1351 filters.append("NBIT"); 1352 } 1353 else if (filter == HDF5Constants.H5Z_FILTER_SCALEOFFSET) { 1354 filters.append("SCALEOFFSET: MIN BITS = ").append(cdValues[0]); 1355 } 1356 else if (filter == HDF5Constants.H5Z_FILTER_SZIP) { 1357 filters.append("SZIP"); 1358 compression.append("SZIP: Pixels per block = ").append(cdValues[1]); 1359 k++; 1360 int flag = -1; 1361 try { 1362 flag = H5.H5Zget_filter_info(filter); 1363 } 1364 catch (Exception ex) { 1365 log.debug("getMetadata(): H5Zget_filter_info failure: ", ex); 1366 flag = -1; 1367 } 1368 if (flag == HDF5Constants.H5Z_FILTER_CONFIG_DECODE_ENABLED) 1369 compression.append(": H5Z_FILTER_CONFIG_DECODE_ENABLED"); 1370 else if ((flag == HDF5Constants.H5Z_FILTER_CONFIG_ENCODE_ENABLED) 1371 || (flag >= (HDF5Constants.H5Z_FILTER_CONFIG_ENCODE_ENABLED 1372 + HDF5Constants.H5Z_FILTER_CONFIG_DECODE_ENABLED))) 1373 compression.append(": H5Z_FILTER_CONFIG_ENCODE_ENABLED"); 1374 } 1375 else { 1376 filters.append("USERDEFINED ").append(cdName[0]).append("(").append(filter).append("): "); 1377 for (int j = 0; j < cdNelmts[0]; j++) { 1378 if (j > 0) 1379 filters.append(", "); 1380 filters.append(cdValues[j]); 1381 } 1382 log.debug("getMetadata(): filter[{}] is user defined compression", i); 1383 } 1384 } // (int i=0; i<nfilt; i++) 1385 } 1386 1387 if (compression.length() == 0) 1388 compression.append("NONE"); 1389 log.trace("getMetadata(): filter compression={}", compression); 1390 log.trace("getMetadata(): filter information={}", filters); 1391 1392 storage.setLength(0); 1393 storage.append("SIZE: ").append(storageSize); 1394 1395 try { 1396 int[] at = { 0 }; 1397 H5.H5Pget_alloc_time(pcid, at); 1398 storage.append(", allocation time: "); 1399 if (at[0] == HDF5Constants.H5D_ALLOC_TIME_EARLY) 1400 storage.append("Early"); 1401 else if (at[0] == HDF5Constants.H5D_ALLOC_TIME_INCR) 1402 storage.append("Incremental"); 1403 else if (at[0] == HDF5Constants.H5D_ALLOC_TIME_LATE) 1404 storage.append("Late"); 1405 else 1406 storage.append("Default"); 1407 } 1408 catch (Exception ex) { 1409 log.debug("getMetadata(): Storage allocation time:", ex); 1410 } 1411 log.trace("getMetadata(): storage={}", storage); 1412 } 1413 finally { 1414 try { 1415 H5.H5Pclose(paid); 1416 } 1417 catch (Exception ex) { 1418 log.debug("getMetadata(): H5Pclose(paid {}) failure: ", paid, ex); 1419 } 1420 try { 1421 H5.H5Pclose(pcid); 1422 } 1423 catch (Exception ex) { 1424 log.debug("getMetadata(): H5Pclose(pcid {}) failure: ", pcid, ex); 1425 } 1426 close(did); 1427 } 1428 } 1429 } 1430 1431 List<Attribute> attrlist = null; 1432 try { 1433 attrlist = objMetadata.getMetadata(attrPropList); 1434 } 1435 catch (Exception ex) { 1436 log.debug("getMetadata(): getMetadata failed: ", ex); 1437 } 1438 return attrlist; 1439 } 1440 1441 /** 1442 * Writes a specific piece of metadata (such as an attribute) into the file. 1443 * 1444 * If an HDF(4&5) attribute exists in the file, this method updates its 1445 * value. If the attribute does not exist in the file, it creates the 1446 * attribute in the file and attaches it to the object. It will fail to 1447 * write a new attribute to the object where an attribute with the same name 1448 * already exists. To update the value of an existing attribute in the file, 1449 * one needs to get the instance of the attribute by getMetadata(), change 1450 * its values, then use writeMetadata() to write the value. 1451 * 1452 * @param info 1453 * the metadata to write. 1454 * 1455 * @throws Exception 1456 * if the metadata can not be written 1457 */ 1458 @Override 1459 public void writeMetadata(Object info) throws Exception { 1460 try { 1461 objMetadata.writeMetadata(info); 1462 } 1463 catch (Exception ex) { 1464 log.debug("writeMetadata(): Object not an Attribute"); 1465 } 1466 } 1467 1468 /** 1469 * Deletes an existing piece of metadata from this object. 1470 * 1471 * @param info 1472 * the metadata to delete. 1473 * 1474 * @throws HDF5Exception 1475 * if the metadata can not be removed 1476 */ 1477 @Override 1478 public void removeMetadata(Object info) throws HDF5Exception { 1479 try { 1480 objMetadata.removeMetadata(info); 1481 } 1482 catch (Exception ex) { 1483 log.debug("removeMetadata(): Object not an Attribute"); 1484 return; 1485 } 1486 1487 Attribute attr = (Attribute) info; 1488 log.trace("removeMetadata(): {}", attr.getAttributeName()); 1489 long did = open(); 1490 if (did >= 0) { 1491 try { 1492 H5.H5Adelete(did, attr.getAttributeName()); 1493 } 1494 finally { 1495 close(did); 1496 } 1497 } 1498 else { 1499 log.debug("removeMetadata(): failed to open scalar dataset"); 1500 } 1501 } 1502 1503 /** 1504 * Updates an existing piece of metadata attached to this object. 1505 * 1506 * @param info 1507 * the metadata to update. 1508 * 1509 * @throws HDF5Exception 1510 * if the metadata can not be updated 1511 */ 1512 @Override 1513 public void updateMetadata(Object info) throws HDF5Exception { 1514 try { 1515 objMetadata.updateMetadata(info); 1516 } 1517 catch (Exception ex) { 1518 log.debug("updateMetadata(): Object not an Attribute"); 1519 return; 1520 } 1521 } 1522 1523 /* 1524 * (non-Javadoc) 1525 * 1526 * @see hdf.object.HObject#setName(java.lang.String) 1527 */ 1528 @Override 1529 public void setName(String newName) throws Exception { 1530 if (newName == null) 1531 throw new IllegalArgumentException("The new name is NULL"); 1532 1533 H5File.renameObject(this, newName); 1534 super.setName(newName); 1535 } 1536 1537 /** 1538 * Resets selection of dataspace 1539 */ 1540 @Override 1541 protected void resetSelection() { 1542 super.resetSelection(); 1543 1544 if (interlace == INTERLACE_PIXEL) { 1545 // 24-bit TRUE color image 1546 // [height][width][pixel components] 1547 selectedDims[2] = 3; 1548 selectedDims[0] = dims[0]; 1549 selectedDims[1] = dims[1]; 1550 selectedIndex[0] = 0; // index for height 1551 selectedIndex[1] = 1; // index for width 1552 selectedIndex[2] = 2; // index for depth 1553 } 1554 else if (interlace == INTERLACE_PLANE) { 1555 // 24-bit TRUE color image 1556 // [pixel components][height][width] 1557 selectedDims[0] = 3; 1558 selectedDims[1] = dims[1]; 1559 selectedDims[2] = dims[2]; 1560 selectedIndex[0] = 1; // index for height 1561 selectedIndex[1] = 2; // index for width 1562 selectedIndex[2] = 0; // index for depth 1563 } 1564 1565 if ((rank > 1) && (selectedIndex[0] > selectedIndex[1])) 1566 isDefaultImageOrder = false; 1567 else 1568 isDefaultImageOrder = true; 1569 } 1570 1571 /** 1572 * Creates a scalar dataset in a file with/without chunking and compression. 1573 * 1574 * @param name 1575 * the name of the dataset to create. 1576 * @param pgroup 1577 * parent group where the new dataset is created. 1578 * @param type 1579 * the datatype of the dataset. 1580 * @param dims 1581 * the dimension size of the dataset. 1582 * @param maxdims 1583 * the max dimension size of the dataset. maxdims is set to dims if maxdims = null. 1584 * @param chunks 1585 * the chunk size of the dataset. No chunking if chunk = null. 1586 * @param gzip 1587 * GZIP compression level (1 to 9). No compression if gzip<=0. 1588 * @param data 1589 * the array of data values. 1590 * 1591 * @return the new scalar dataset if successful; otherwise returns null. 1592 * 1593 * @throws Exception if there is a failure. 1594 */ 1595 public static Dataset create(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, 1596 long[] chunks, int gzip, Object data) throws Exception { 1597 return create(name, pgroup, type, dims, maxdims, chunks, gzip, null, data); 1598 } 1599 1600 /** 1601 * Creates a scalar dataset in a file with/without chunking and compression. 1602 * 1603 * The following example shows how to create a string dataset using this function. 1604 * 1605 * <pre> 1606 * H5File file = new H5File("test.h5", H5File.CREATE); 1607 * int max_str_len = 120; 1608 * Datatype strType = new H5Datatype(Datatype.CLASS_STRING, max_str_len, Datatype.NATIVE, Datatype.NATIVE); 1609 * int size = 10000; 1610 * long dims[] = { size }; 1611 * long chunks[] = { 1000 }; 1612 * int gzip = 9; 1613 * String strs[] = new String[size]; 1614 * 1615 * for (int i = 0; i < size; i++) 1616 * strs[i] = String.valueOf(i); 1617 * 1618 * file.open(); 1619 * file.createScalarDS("/1D scalar strings", null, strType, dims, null, chunks, gzip, strs); 1620 * 1621 * try { 1622 * file.close(); 1623 * } 1624 * catch (Exception ex) { 1625 * } 1626 * </pre> 1627 * 1628 * @param name 1629 * the name of the dataset to create. 1630 * @param pgroup 1631 * parent group where the new dataset is created. 1632 * @param type 1633 * the datatype of the dataset. 1634 * @param dims 1635 * the dimension size of the dataset. 1636 * @param maxdims 1637 * the max dimension size of the dataset. maxdims is set to dims if maxdims = null. 1638 * @param chunks 1639 * the chunk size of the dataset. No chunking if chunk = null. 1640 * @param gzip 1641 * GZIP compression level (1 to 9). No compression if gzip<=0. 1642 * @param fillValue 1643 * the default data value. 1644 * @param data 1645 * the array of data values. 1646 * 1647 * @return the new scalar dataset if successful; otherwise returns null. 1648 * 1649 * @throws Exception if there is a failure. 1650 */ 1651 public static Dataset create(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, 1652 long[] chunks, int gzip, Object fillValue, Object data) throws Exception { 1653 H5ScalarDS dataset = null; 1654 String fullPath = null; 1655 long did = HDF5Constants.H5I_INVALID_HID; 1656 long plist = HDF5Constants.H5I_INVALID_HID; 1657 long sid = HDF5Constants.H5I_INVALID_HID; 1658 long tid = HDF5Constants.H5I_INVALID_HID; 1659 1660 if ((pgroup == null) || (name == null) || (dims == null) || ((gzip > 0) && (chunks == null))) { 1661 log.debug("create(): one or more parameters are null"); 1662 return null; 1663 } 1664 1665 H5File file = (H5File) pgroup.getFileFormat(); 1666 if (file == null) { 1667 log.debug("create(): parent group FileFormat is null"); 1668 return null; 1669 } 1670 1671 String path = HObject.SEPARATOR; 1672 if (!pgroup.isRoot()) { 1673 path = pgroup.getPath() + pgroup.getName() + HObject.SEPARATOR; 1674 if (name.endsWith("/")) 1675 name = name.substring(0, name.length() - 1); 1676 int idx = name.lastIndexOf('/'); 1677 if (idx >= 0) 1678 name = name.substring(idx + 1); 1679 } 1680 1681 fullPath = path + name; 1682 1683 // setup chunking and compression 1684 boolean isExtentable = false; 1685 if (maxdims != null) { 1686 for (int i = 0; i < maxdims.length; i++) { 1687 if (maxdims[i] == 0) 1688 maxdims[i] = dims[i]; 1689 else if (maxdims[i] < 0) 1690 maxdims[i] = HDF5Constants.H5S_UNLIMITED; 1691 1692 if (maxdims[i] != dims[i]) 1693 isExtentable = true; 1694 } 1695 } 1696 1697 // HDF5 requires you to use chunking in order to define extendible 1698 // datasets. Chunking makes it possible to extend datasets efficiently, 1699 // without having to reorganize storage excessively. Using default size 1700 // of 64x...which has good performance 1701 if ((chunks == null) && isExtentable) { 1702 chunks = new long[dims.length]; 1703 for (int i = 0; i < dims.length; i++) 1704 chunks[i] = Math.min(dims[i], 64); 1705 } 1706 1707 // prepare the dataspace and datatype 1708 int rank = dims.length; 1709 1710 tid = type.createNative(); 1711 if (tid >= 0) { 1712 try { 1713 sid = H5.H5Screate_simple(rank, dims, maxdims); 1714 1715 // figure out creation properties 1716 plist = HDF5Constants.H5P_DEFAULT; 1717 1718 byte[] valFill = null; 1719 try { 1720 valFill = parseFillValue(type, fillValue); 1721 } 1722 catch (Exception ex) { 1723 log.debug("create(): parse fill value: ", ex); 1724 } 1725 log.trace("create(): parseFillValue={}", valFill); 1726 1727 if (chunks != null || valFill != null) { 1728 plist = H5.H5Pcreate(HDF5Constants.H5P_DATASET_CREATE); 1729 1730 if (chunks != null) { 1731 H5.H5Pset_layout(plist, HDF5Constants.H5D_CHUNKED); 1732 H5.H5Pset_chunk(plist, rank, chunks); 1733 1734 // compression requires chunking 1735 if (gzip > 0) { 1736 H5.H5Pset_deflate(plist, gzip); 1737 } 1738 } 1739 1740 if (valFill != null) 1741 H5.H5Pset_fill_value(plist, tid, valFill); 1742 } 1743 1744 long fid = file.getFID(); 1745 1746 log.trace("create(): create dataset fid={}", fid); 1747 did = H5.H5Dcreate(fid, fullPath, tid, sid, HDF5Constants.H5P_DEFAULT, plist, HDF5Constants.H5P_DEFAULT); 1748 log.trace("create(): create dataset did={}", did); 1749 dataset = new H5ScalarDS(file, name, path); 1750 } 1751 finally { 1752 try { 1753 H5.H5Pclose(plist); 1754 } 1755 catch (HDF5Exception ex) { 1756 log.debug("create(): H5Pclose(plist {}) failure: ", plist, ex); 1757 } 1758 try { 1759 H5.H5Sclose(sid); 1760 } 1761 catch (HDF5Exception ex) { 1762 log.debug("create(): H5Sclose(sid {}) failure: ", sid, ex); 1763 } 1764 try { 1765 H5.H5Tclose(tid); 1766 } 1767 catch (HDF5Exception ex) { 1768 log.debug("create(): H5Tclose(tid {}) failure: ", tid, ex); 1769 } 1770 try { 1771 H5.H5Dclose(did); 1772 } 1773 catch (HDF5Exception ex) { 1774 log.debug("create(): H5Dclose(did {}) failure: ", did, ex); 1775 } 1776 } 1777 } 1778 1779 if (dataset != null) { 1780 pgroup.addToMemberList(dataset); 1781 if (data != null) { 1782 dataset.init(); 1783 long[] selected = dataset.getSelectedDims(); 1784 for (int i = 0; i < rank; i++) 1785 selected[i] = dims[i]; 1786 dataset.write(data); 1787 } 1788 } 1789 1790 return dataset; 1791 } 1792 1793 // check _FillValue, valid_min, valid_max, and valid_range 1794 private void checkCFconvention(long oid) throws Exception { 1795 Object avalue = getAttrValue(oid, "_FillValue"); 1796 1797 if (avalue != null) { 1798 int n = Array.getLength(avalue); 1799 for (int i = 0; i < n; i++) 1800 addFilteredImageValue((Number) Array.get(avalue, i)); 1801 } 1802 1803 if (imageDataRange == null || imageDataRange[1] <= imageDataRange[0]) { 1804 double x0 = 0; 1805 double x1 = 0; 1806 avalue = getAttrValue(oid, "valid_range"); 1807 if (avalue != null) { 1808 try { 1809 x0 = Double.parseDouble(java.lang.reflect.Array.get(avalue, 0).toString()); 1810 x1 = Double.parseDouble(java.lang.reflect.Array.get(avalue, 1).toString()); 1811 imageDataRange = new double[2]; 1812 imageDataRange[0] = x0; 1813 imageDataRange[1] = x1; 1814 return; 1815 } 1816 catch (Exception ex) { 1817 log.debug("checkCFconvention(): valid_range: ", ex); 1818 } 1819 } 1820 1821 avalue = getAttrValue(oid, "valid_min"); 1822 if (avalue != null) { 1823 try { 1824 x0 = Double.parseDouble(java.lang.reflect.Array.get(avalue, 0).toString()); 1825 } 1826 catch (Exception ex) { 1827 log.debug("checkCFconvention(): valid_min: ", ex); 1828 } 1829 avalue = getAttrValue(oid, "valid_max"); 1830 if (avalue != null) { 1831 try { 1832 x1 = Double.parseDouble(java.lang.reflect.Array.get(avalue, 0).toString()); 1833 imageDataRange = new double[2]; 1834 imageDataRange[0] = x0; 1835 imageDataRange[1] = x1; 1836 } 1837 catch (Exception ex) { 1838 log.debug("checkCFconvention(): valid_max:", ex); 1839 } 1840 } 1841 } 1842 } // (imageDataRange==null || imageDataRange[1]<=imageDataRange[0]) 1843 } 1844 1845 private Object getAttrValue(long oid, String aname) { 1846 log.trace("getAttrValue(): start: name={}", aname); 1847 1848 long aid = HDF5Constants.H5I_INVALID_HID; 1849 long atid = HDF5Constants.H5I_INVALID_HID; 1850 long asid = HDF5Constants.H5I_INVALID_HID; 1851 Object avalue = null; 1852 1853 try { 1854 // try to find attribute name 1855 if(H5.H5Aexists_by_name(oid, ".", aname, HDF5Constants.H5P_DEFAULT)) 1856 aid = H5.H5Aopen_by_name(oid, ".", aname, HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 1857 } 1858 catch (HDF5LibraryException ex5) { 1859 log.debug("getAttrValue(): Failed to find attribute {} : Expected", aname); 1860 } 1861 catch (Exception ex) { 1862 log.debug("getAttrValue(): try to find attribute {}:", aname, ex); 1863 } 1864 if (aid > 0) { 1865 try { 1866 atid = H5.H5Aget_type(aid); 1867 long tmptid = atid; 1868 atid = H5.H5Tget_native_type(tmptid); 1869 try { 1870 H5.H5Tclose(tmptid); 1871 } 1872 catch (Exception ex) { 1873 log.debug("getAttrValue(): H5Tclose(tmptid {}) failure: ", tmptid, ex); 1874 } 1875 1876 asid = H5.H5Aget_space(aid); 1877 long adims[] = null; 1878 1879 int arank = H5.H5Sget_simple_extent_ndims(asid); 1880 if (arank > 0) { 1881 adims = new long[arank]; 1882 H5.H5Sget_simple_extent_dims(asid, adims, null); 1883 } 1884 log.trace("getAttrValue(): adims={}", adims); 1885 1886 // retrieve the attribute value 1887 long lsize = 1; 1888 if (adims != null) { 1889 for (int j = 0; j < adims.length; j++) { 1890 lsize *= adims[j]; 1891 } 1892 } 1893 log.trace("getAttrValue(): lsize={}", lsize); 1894 1895 if (lsize < Integer.MIN_VALUE || lsize > Integer.MAX_VALUE) throw new Exception("Invalid int size"); 1896 1897 H5Datatype dsDatatype = null; 1898 int nativeClass = H5.H5Tget_class(atid); 1899 if (nativeClass == HDF5Constants.H5T_REFERENCE) 1900 dsDatatype = new H5ReferenceType(getFileFormat(), lsize, atid); 1901 else 1902 dsDatatype = new H5Datatype(getFileFormat(), atid); 1903 1904 try { 1905 avalue = H5Datatype.allocateArray(dsDatatype, (int) lsize); 1906 } 1907 catch (OutOfMemoryError e) { 1908 log.debug("getAttrValue(): out of memory: ", e); 1909 avalue = null; 1910 } 1911 1912 if (avalue != null) { 1913 log.trace("getAttrValue(): read attribute id {} of size={}", atid, lsize); 1914 H5.H5Aread(aid, atid, avalue); 1915 1916 if (dsDatatype.isUnsigned()) { 1917 log.trace("getAttrValue(): id {} is unsigned", atid); 1918 avalue = convertFromUnsignedC(avalue, null); 1919 } 1920 if (dsDatatype.isRef() && (avalue instanceof byte[])) 1921 ((H5ReferenceType)dsDatatype).setData((ArrayList<byte[]>)avalue); 1922 else if (dsDatatype.isRef()) 1923 ((H5ReferenceType)dsDatatype).setData(avalue); 1924 } 1925 } 1926 catch (Exception ex) { 1927 log.debug("getAttrValue(): try to get value for attribute {}: ", aname, ex); 1928 } 1929 finally { 1930 try { 1931 H5.H5Tclose(atid); 1932 } 1933 catch (HDF5Exception ex) { 1934 log.debug("getAttrValue(): H5Tclose(atid {}) failure: ", atid, ex); 1935 } 1936 try { 1937 H5.H5Sclose(asid); 1938 } 1939 catch (HDF5Exception ex) { 1940 log.debug("getAttrValue(): H5Sclose(asid {}) failure: ", asid, ex); 1941 } 1942 try { 1943 H5.H5Aclose(aid); 1944 } 1945 catch (HDF5Exception ex) { 1946 log.debug("getAttrValue(): H5Aclose(aid {}) failure: ", aid, ex); 1947 } 1948 } 1949 } // (aid > 0) 1950 1951 return avalue; 1952 } 1953 1954 private boolean isStringAttributeOf(long objID, String name, String value) { 1955 boolean retValue = false; 1956 long aid = HDF5Constants.H5I_INVALID_HID; 1957 long atid = HDF5Constants.H5I_INVALID_HID; 1958 1959 try { 1960 if (H5.H5Aexists_by_name(objID, ".", name, HDF5Constants.H5P_DEFAULT)) { 1961 aid = H5.H5Aopen_by_name(objID, ".", name, HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 1962 atid = H5.H5Aget_type(aid); 1963 int size = (int)H5.H5Tget_size(atid); 1964 byte[] attrValue = new byte[size]; 1965 H5.H5Aread(aid, atid, attrValue); 1966 String strValue = new String(attrValue).trim(); 1967 retValue = strValue.equalsIgnoreCase(value); 1968 } 1969 } 1970 catch (Exception ex) { 1971 log.debug("isStringAttributeOf(): try to find out interlace mode:", ex); 1972 } 1973 finally { 1974 try { 1975 H5.H5Tclose(atid); 1976 } 1977 catch (HDF5Exception ex) { 1978 log.debug("isStringAttributeOf(): H5Tclose(atid {}) failure: ", atid, ex); 1979 } 1980 try { 1981 H5.H5Aclose(aid); 1982 } 1983 catch (HDF5Exception ex) { 1984 log.debug("isStringAttributeOf(): H5Aclose(aid {}) failure: ", aid, ex); 1985 } 1986 } 1987 1988 return retValue; 1989 } 1990 1991 /* 1992 * (non-Javadoc) 1993 * 1994 * @see hdf.object.Dataset#copy(hdf.object.Group, java.lang.String, long[], java.lang.Object) 1995 */ 1996 @Override 1997 public Dataset copy(Group pgroup, String dstName, long[] dims, Object buff) throws Exception { 1998 // must give a location to copy 1999 if (pgroup == null) { 2000 log.debug("copy(): Parent group is null"); 2001 return null; 2002 } 2003 2004 Dataset dataset = null; 2005 long srcdid = HDF5Constants.H5I_INVALID_HID; 2006 long dstdid = HDF5Constants.H5I_INVALID_HID; 2007 long plist = HDF5Constants.H5I_INVALID_HID; 2008 long tid = HDF5Constants.H5I_INVALID_HID; 2009 long sid = HDF5Constants.H5I_INVALID_HID; 2010 String dname = null; 2011 String path = null; 2012 2013 if (pgroup.isRoot()) 2014 path = HObject.SEPARATOR; 2015 else 2016 path = pgroup.getPath() + pgroup.getName() + HObject.SEPARATOR; 2017 dname = path + dstName; 2018 2019 srcdid = open(); 2020 if (srcdid >= 0) { 2021 try { 2022 tid = H5.H5Dget_type(srcdid); 2023 sid = H5.H5Screate_simple(dims.length, dims, null); 2024 plist = H5.H5Dget_create_plist(srcdid); 2025 2026 long[] chunks = new long[dims.length]; 2027 boolean setChunkFlag = false; 2028 try { 2029 H5.H5Pget_chunk(plist, dims.length, chunks); 2030 for (int i = 0; i < dims.length; i++) { 2031 if (dims[i] < chunks[i]) { 2032 setChunkFlag = true; 2033 if (dims[i] == 1) 2034 chunks[i] = 1; 2035 else 2036 chunks[i] = dims[i] / 2; 2037 } 2038 } 2039 } 2040 catch (Exception ex) { 2041 log.debug("copy(): chunk: ", ex); 2042 } 2043 2044 if (setChunkFlag) 2045 H5.H5Pset_chunk(plist, dims.length, chunks); 2046 2047 try { 2048 dstdid = H5.H5Dcreate(pgroup.getFID(), dname, tid, sid, HDF5Constants.H5P_DEFAULT, plist, 2049 HDF5Constants.H5P_DEFAULT); 2050 } 2051 catch (Exception e) { 2052 log.debug("copy(): H5Dcreate: ", e); 2053 } 2054 finally { 2055 try { 2056 H5.H5Dclose(dstdid); 2057 } 2058 catch (Exception ex2) { 2059 log.debug("copy(): H5Dclose(dstdid {}) failure: ", dstdid, ex2); 2060 } 2061 } 2062 2063 dataset = new H5ScalarDS(pgroup.getFileFormat(), dstName, path); 2064 if (buff != null) { 2065 dataset.init(); 2066 dataset.write(buff); 2067 } 2068 2069 dstdid = dataset.open(); 2070 if (dstdid >= 0) { 2071 try { 2072 H5File.copyAttributes(srcdid, dstdid); 2073 } 2074 finally { 2075 try { 2076 H5.H5Dclose(dstdid); 2077 } 2078 catch (Exception ex) { 2079 log.debug("copy(): H5Dclose(dstdid {}) failure: ", dstdid, ex); 2080 } 2081 } 2082 } 2083 } 2084 finally { 2085 try { 2086 H5.H5Pclose(plist); 2087 } 2088 catch (Exception ex) { 2089 log.debug("copy(): H5Pclose(plist {}) failure: ", plist, ex); 2090 } 2091 try { 2092 H5.H5Sclose(sid); 2093 } 2094 catch (Exception ex) { 2095 log.debug("copy(): H5Sclose(sid {}) failure: ", sid, ex); 2096 } 2097 try { 2098 H5.H5Tclose(tid); 2099 } 2100 catch (Exception ex) { 2101 log.debug("copy(): H5Tclose(tid {}) failure: ", tid, ex); 2102 } 2103 try { 2104 H5.H5Dclose(srcdid); 2105 } 2106 catch (Exception ex) { 2107 log.debug("copy(): H5Dclose(srcdid {}) failure: ", srcdid, ex); 2108 } 2109 } 2110 } 2111 2112 pgroup.addToMemberList(dataset); 2113 2114 if (dataset != null) 2115 ((ScalarDS) dataset).setIsImage(isImage); 2116 2117 return dataset; 2118 } 2119 2120 /** 2121 * Get the number of pallettes for this object. 2122 * 2123 * @return the number of palettes if it has any, 0 otherwise. 2124 */ 2125 public int getNumberOfPalettes() { 2126 return NumberOfPalettes; 2127 } 2128 2129 /* 2130 * (non-Javadoc) 2131 * 2132 * @see hdf.object.ScalarDS#getPalette() 2133 */ 2134 @Override 2135 public byte[][] getPalette() { 2136 log.trace("getPalette(): NumberOfPalettes={}", NumberOfPalettes); 2137 if (NumberOfPalettes > 0) 2138 if (palette == null) 2139 palette = readPalette(0); 2140 2141 return palette; 2142 } 2143 2144 /* 2145 * (non-Javadoc) 2146 * 2147 * @see hdf.object.ScalarDS#getPaletteName(int) 2148 */ 2149 @Override 2150 public String getPaletteName(int idx) { 2151 int count = readNumberOfPalettes(); 2152 long did = HDF5Constants.H5I_INVALID_HID; 2153 long palID = HDF5Constants.H5I_INVALID_HID; 2154 String paletteName = null; 2155 2156 if (count < 1) { 2157 log.debug("getPaletteName(): no palettes are attached"); 2158 return null; 2159 } 2160 2161 byte[][] refBuf = null; 2162 2163 did = open(); 2164 if (did >= 0) { 2165 try { 2166 refBuf = getPaletteRefs(did); 2167 palID = H5.H5Ropen_object(refBuf[idx], HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 2168 paletteName = H5.H5Iget_name(palID); 2169 } 2170 catch (Exception ex) { 2171 ex.printStackTrace(); 2172 } 2173 finally { 2174 close(palID); 2175 for (int i = 0; i < count; i++) 2176 H5.H5Rdestroy(refBuf[i]); 2177 close(did); 2178 } 2179 } 2180 2181 return paletteName; 2182 } 2183 2184 /* 2185 * (non-Javadoc) 2186 * 2187 * @see hdf.object.ScalarDS#readPalette(int) 2188 */ 2189 @Override 2190 public byte[][] readPalette(int idx) { 2191 byte[][] thePalette = null; 2192 int count = readNumberOfPalettes(); 2193 long did = HDF5Constants.H5I_INVALID_HID; 2194 long palID = HDF5Constants.H5I_INVALID_HID; 2195 long tid = HDF5Constants.H5I_INVALID_HID; 2196 log.trace("readPalette(): palette count={}", count); 2197 2198 if (count < 1) { 2199 log.debug("readPalette(): no palettes are attached"); 2200 return null; 2201 } 2202 2203 byte[] p = null; 2204 byte[][] refBuf = null; 2205 2206 did = open(); 2207 if (did >= 0) { 2208 try { 2209 refBuf = getPaletteRefs(did); 2210 palID = H5.H5Ropen_object(refBuf[idx], HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 2211 log.trace("readPalette(): H5Ropen_object: {}", palID); 2212 tid = H5.H5Dget_type(palID); 2213 2214 // support only 3*256 byte palette data 2215 if (H5.H5Dget_storage_size(palID) <= 768) { 2216 p = new byte[3 * 256]; 2217 H5.H5Dread(palID, tid, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL, HDF5Constants.H5P_DEFAULT, p); 2218 } 2219 } 2220 catch (HDF5Exception ex) { 2221 log.debug("readPalette(): failure: ", ex); 2222 p = null; 2223 } 2224 finally { 2225 try { 2226 H5.H5Tclose(tid); 2227 } 2228 catch (HDF5Exception ex2) { 2229 log.debug("readPalette(): H5Tclose(tid {}) failure: ", tid, ex2); 2230 } 2231 close(palID); 2232 for (int i = 0; i < count; i++) 2233 H5.H5Rdestroy(refBuf[i]); 2234 close(did); 2235 } 2236 } 2237 2238 if (p != null) { 2239 thePalette = new byte[3][256]; 2240 for (int i = 0; i < 256; i++) { 2241 thePalette[0][i] = p[i * 3]; 2242 thePalette[1][i] = p[i * 3 + 1]; 2243 thePalette[2][i] = p[i * 3 + 2]; 2244 } 2245 } 2246 2247 return thePalette; 2248 } 2249 2250 private static byte[] parseFillValue(Datatype type, Object fillValue) throws Exception { 2251 byte[] data = null; 2252 2253 if (type == null || fillValue == null) { 2254 log.debug("parseFillValue(): datatype or fill value is null"); 2255 return null; 2256 } 2257 2258 int datatypeClass = type.getDatatypeClass(); 2259 int datatypeSize = (int)type.getDatatypeSize(); 2260 2261 double valDbl = 0; 2262 String valStr = null; 2263 2264 if (fillValue instanceof String) 2265 valStr = (String) fillValue; 2266 else if (fillValue.getClass().isArray()) 2267 valStr = Array.get(fillValue, 0).toString(); 2268 2269 if (!type.isString()) { 2270 try { 2271 valDbl = Double.parseDouble(valStr); 2272 } 2273 catch (NumberFormatException ex) { 2274 log.debug("parseFillValue(): parse error: ", ex); 2275 return null; 2276 } 2277 } 2278 2279 try { 2280 switch (datatypeClass) { 2281 case Datatype.CLASS_INTEGER: 2282 case Datatype.CLASS_ENUM: 2283 case Datatype.CLASS_CHAR: 2284 log.trace("parseFillValue(): class CLASS_INT-ENUM-CHAR"); 2285 if (datatypeSize == 1) 2286 data = new byte[] { (byte) valDbl }; 2287 else if (datatypeSize == 2) 2288 data = HDFNativeData.shortToByte((short) valDbl); 2289 else if (datatypeSize == 8) 2290 data = HDFNativeData.longToByte((long) valDbl); 2291 else 2292 data = HDFNativeData.intToByte((int) valDbl); 2293 break; 2294 case Datatype.CLASS_FLOAT: 2295 log.trace("parseFillValue(): class CLASS_FLOAT"); 2296 if (datatypeSize > 8) 2297 data = valStr.getBytes(); 2298 else if (datatypeSize == 8) 2299 data = HDFNativeData.doubleToByte(valDbl); 2300 else 2301 data = HDFNativeData.floatToByte((float) valDbl); 2302 break; 2303 case Datatype.CLASS_STRING: 2304 log.trace("parseFillValue(): class CLASS_STRING"); 2305 if (valStr != null) 2306 data = valStr.getBytes(); 2307 break; 2308 case Datatype.CLASS_REFERENCE: 2309 log.trace("parseFillValue(): class CLASS_REFERENCE"); 2310 data = HDFNativeData.longToByte((long) valDbl); 2311 break; 2312 default: 2313 log.debug("parseFillValue(): datatypeClass unknown"); 2314 break; 2315 } // (datatypeClass) 2316 } 2317 catch (Exception ex) { 2318 log.debug("parseFillValue(): failure: ", ex); 2319 data = null; 2320 } 2321 2322 return data; 2323 } 2324 2325 /** 2326 * reads references of palettes to count the numberOfPalettes. 2327 * 2328 * @return the number of palettes referenced. 2329 */ 2330 public int readNumberOfPalettes() { 2331 log.trace("readNumberOfPalettes(): isInited={}", isInited()); 2332 if (!isInited()) 2333 init(); // init will be called to get refs 2334 2335 return NumberOfPalettes; 2336 } 2337 2338 /** 2339 * reads references of palettes to calculate the numberOfPalettes. 2340 */ 2341 private int readNumberOfPalette(long did) { 2342 long aid = HDF5Constants.H5I_INVALID_HID; 2343 long sid = HDF5Constants.H5I_INVALID_HID; 2344 long atype = HDF5Constants.H5I_INVALID_HID; 2345 int size = 0; 2346 int rank = 0; 2347 byte[] refbuf = null; 2348 log.trace("readNumberOfPalette(): did={}", did); 2349 2350 try { 2351 if(H5.H5Aexists_by_name(did, ".", "PALETTE", HDF5Constants.H5P_DEFAULT)) { 2352 aid = H5.H5Aopen_by_name(did, ".", "PALETTE", HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 2353 sid = H5.H5Aget_space(aid); 2354 rank = H5.H5Sget_simple_extent_ndims(sid); 2355 size = 1; 2356 if (rank > 0) { 2357 long[] dims = new long[rank]; 2358 H5.H5Sget_simple_extent_dims(sid, dims, null); 2359 log.trace("readNumberOfPalette(): rank={}, dims={}", rank, dims); 2360 for (int i = 0; i < rank; i++) 2361 size *= (int) dims[i]; 2362 } 2363 log.trace("readNumberOfPalette(): size={}", size); 2364 2365 if ((size * HDF5Constants.H5R_REF_BUF_SIZE) < Integer.MIN_VALUE || (size * HDF5Constants.H5R_REF_BUF_SIZE) > Integer.MAX_VALUE) 2366 throw new HDF5Exception("Invalid int size"); 2367 } 2368 } 2369 catch (HDF5Exception ex) { 2370 log.debug("readNumberOfPalette(): Palette attribute search failed: Expected", ex); 2371 refbuf = null; 2372 } 2373 finally { 2374 try { 2375 H5.H5Tclose(atype); 2376 } 2377 catch (HDF5Exception ex2) { 2378 log.debug("readNumberOfPalette(): H5Tclose(atype {}) failure: ", atype, ex2); 2379 } 2380 try { 2381 H5.H5Sclose(sid); 2382 } 2383 catch (HDF5Exception ex2) { 2384 log.debug("readNumberOfPalette(): H5Sclose(sid {}) failure: ", sid, ex2); 2385 } 2386 try { 2387 H5.H5Aclose(aid); 2388 } 2389 catch (HDF5Exception ex2) { 2390 log.debug("readNumberOfPalette(): H5Aclose(aid {}) failure: ", aid, ex2); 2391 } 2392 } 2393 2394 return size; 2395 } 2396 2397 /** 2398 * reads references of palettes into a byte array Each reference requires eight bytes storage. Therefore, the array 2399 * length is 8*numberOfPalettes. 2400 */ 2401 private byte[][] getPaletteRefs(long did) { 2402 long aid = HDF5Constants.H5I_INVALID_HID; 2403 long sid = HDF5Constants.H5I_INVALID_HID; 2404 long atype = HDF5Constants.H5I_INVALID_HID; 2405 int size = 0; 2406 int rank = 0; 2407 byte[][] refBuf = null; 2408 log.trace("getPaletteRefs(): did={}", did); 2409 2410 try { 2411 if(H5.H5Aexists_by_name(did, ".", "PALETTE", HDF5Constants.H5P_DEFAULT)) { 2412 aid = H5.H5Aopen_by_name(did, ".", "PALETTE", HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 2413 sid = H5.H5Aget_space(aid); 2414 rank = H5.H5Sget_simple_extent_ndims(sid); 2415 size = 1; 2416 if (rank > 0) { 2417 long[] dims = new long[rank]; 2418 H5.H5Sget_simple_extent_dims(sid, dims, null); 2419 log.trace("getPaletteRefs(): rank={}, dims={}", rank, dims); 2420 for (int i = 0; i < rank; i++) 2421 size *= (int) dims[i]; 2422 } 2423 log.trace("getPaletteRefs(): size={}", size); 2424 2425 if ((size * HDF5Constants.H5R_REF_BUF_SIZE) < Integer.MIN_VALUE || (size * HDF5Constants.H5R_REF_BUF_SIZE) > Integer.MAX_VALUE) 2426 throw new HDF5Exception("Invalid int size"); 2427 refBuf = new byte[size][HDF5Constants.H5R_REF_BUF_SIZE]; 2428 2429 H5.H5Aread(aid, HDF5Constants.H5T_STD_REF, refBuf); 2430 } 2431 } 2432 catch (HDF5Exception ex) { 2433 log.debug("getPaletteRefs(): Palette attribute search failed: Expected", ex); 2434 refBuf = null; 2435 } 2436 finally { 2437 try { 2438 H5.H5Sclose(sid); 2439 } 2440 catch (HDF5Exception ex2) { 2441 log.debug("getPaletteRefs(): H5Sclose(sid {}) failure: ", sid, ex2); 2442 } 2443 try { 2444 H5.H5Aclose(aid); 2445 } 2446 catch (HDF5Exception ex2) { 2447 log.debug("getPaletteRefs(): H5Aclose(aid {}) failure: ", aid, ex2); 2448 } 2449 } 2450 2451 return refBuf; 2452 } 2453 2454 /** 2455 * H5Dset_extent verifies that the dataset is at least of size size, extending it if necessary. The dimensionality 2456 * of size is the same as that of the dataspace of the dataset being changed. 2457 * 2458 * This function can be applied to the following datasets: 1) Any dataset with unlimited dimensions 2) A dataset 2459 * with fixed dimensions if the current dimension sizes are less than the maximum sizes set with maxdims (see 2460 * H5Screate_simple) 2461 * 2462 * @param newDims the dimension target size 2463 * 2464 * @throws HDF5Exception 2465 * If there is an error at the HDF5 library level. 2466 */ 2467 public void extend(long[] newDims) throws HDF5Exception { 2468 long did = HDF5Constants.H5I_INVALID_HID; 2469 long sid = HDF5Constants.H5I_INVALID_HID; 2470 2471 did = open(); 2472 if (did >= 0) { 2473 try { 2474 H5.H5Dset_extent(did, newDims); 2475 H5.H5Fflush(did, HDF5Constants.H5F_SCOPE_GLOBAL); 2476 sid = H5.H5Dget_space(did); 2477 long[] checkDims = new long[rank]; 2478 H5.H5Sget_simple_extent_dims(sid, checkDims, null); 2479 log.trace("extend(): rank={}, checkDims={}", rank, checkDims); 2480 for (int i = 0; i < rank; i++) { 2481 if (checkDims[i] != newDims[i]) { 2482 log.debug("extend(): error extending dataset"); 2483 throw new HDF5Exception("error extending dataset " + getName()); 2484 } 2485 } 2486 dims = checkDims; 2487 } 2488 catch (Exception e) { 2489 log.debug("extend(): failure: ", e); 2490 throw new HDF5Exception(e.getMessage()); 2491 } 2492 finally { 2493 if (sid > 0) 2494 H5.H5Sclose(sid); 2495 2496 close(did); 2497 } 2498 } 2499 } 2500 2501 /* 2502 * (non-Javadoc) 2503 * 2504 * @see hdf.object.Dataset#isVirtual() 2505 */ 2506 @Override 2507 public boolean isVirtual() { 2508 return isVirtual; 2509 } 2510 2511 /* 2512 * (non-Javadoc) 2513 * 2514 * @see hdf.object.Dataset#getVirtualFilename(int) 2515 */ 2516 @Override 2517 public String getVirtualFilename(int index) { 2518 if(isVirtual) 2519 return virtualNameList.get(index); 2520 else 2521 return null; 2522 } 2523 2524 /* 2525 * (non-Javadoc) 2526 * 2527 * @see hdf.object.Dataset#getVirtualMaps() 2528 */ 2529 @Override 2530 public int getVirtualMaps() { 2531 if(isVirtual) 2532 return virtualNameList.size(); 2533 else 2534 return -1; 2535 } 2536 2537 /* 2538 * (non-Javadoc) 2539 * 2540 * @see hdf.object.Dataset#toString(String delimiter, int maxItems) 2541 */ 2542 @Override 2543 public String toString(String delimiter, int maxItems) { 2544 Object theData = originalBuf; 2545 if (theData == null) { 2546 log.debug("toString: value is null"); 2547 return null; 2548 } 2549 2550 if (theData instanceof List<?>) { 2551 log.trace("toString: value is list"); 2552 return null; 2553 } 2554 2555 Class<? extends Object> valClass = theData.getClass(); 2556 2557 if (!valClass.isArray()) { 2558 log.trace("toString: finish - not array"); 2559 String strValue = theData.toString(); 2560 if (maxItems > 0 && strValue.length() > maxItems) 2561 // truncate the extra characters 2562 strValue = strValue.substring(0, maxItems); 2563 return strValue; 2564 } 2565 2566 // value is an array 2567 StringBuilder sb = new StringBuilder(); 2568 long lsize = 1; 2569 for (int j = 0; j < dims.length; j++) 2570 lsize *= dims[j]; 2571 2572 log.trace("toString: isStdRef={} Array.getLength={}", ((H5Datatype) getDatatype()).isStdRef(), Array.getLength(theData)); 2573 if (((H5Datatype) getDatatype()).isStdRef()) { 2574 String cname = valClass.getName(); 2575 char dname = cname.charAt(cname.lastIndexOf('[') + 1); 2576 log.trace("toString: isStdRef with cname={} dname={}", cname, dname); 2577 for (int i = 0; i < (int)lsize; i++) { 2578 int refIndex = HDF5Constants.H5R_REF_BUF_SIZE * i; 2579 byte[] refarr = new byte[(int) HDF5Constants.H5R_REF_BUF_SIZE]; 2580 System.arraycopy(theData, refIndex, refarr, 0, (int)HDF5Constants.H5R_REF_BUF_SIZE); 2581 String ref_str = ((H5ReferenceType) getDatatype()).getReferenceRegion(refarr, false); 2582 log.trace("toString: ref_str[{}]={}", i, ref_str); 2583 if (i > 0) 2584 sb.append(", "); 2585 sb.append(ref_str); 2586 2587// int n = ref_str.length(); 2588// if (maxItems > 0) { 2589// if (n > maxItems) 2590// break; 2591// else 2592// maxItems -= n; 2593// } 2594 } 2595 return sb.toString(); 2596 } 2597 return super.toString(delimiter, maxItems); 2598 } 2599 2600}