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 files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 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.h4; 016 017import java.util.List; 018import java.util.Vector; 019 020import hdf.hdflib.HDFChunkInfo; 021import hdf.hdflib.HDFCompInfo; 022import hdf.hdflib.HDFConstants; 023import hdf.hdflib.HDFDeflateCompInfo; 024import hdf.hdflib.HDFException; 025import hdf.hdflib.HDFJPEGCompInfo; 026import hdf.hdflib.HDFLibrary; 027import hdf.hdflib.HDFNBITCompInfo; 028import hdf.hdflib.HDFSKPHUFFCompInfo; 029import hdf.hdflib.HDFSZIPCompInfo; 030import hdf.object.Attribute; 031import hdf.object.Dataset; 032import hdf.object.Datatype; 033import hdf.object.FileFormat; 034import hdf.object.Group; 035import hdf.object.HObject; 036import hdf.object.ScalarDS; 037 038/** 039 * H4SDS describes HDF4 Scientific Data Sets (SDS) and operations performed on 040 * the SDS. A SDS is a group of data structures used to store and describe 041 * multidimensional arrays of scientific data. 042 * <p> 043 * The data contained in an SDS array has a data type associated with it. The 044 * standard data types supported by the SD interface include 32- and 64-bit 045 * floating-point numbers, 8-, 16- and 32-bit signed integers, 8-, 16- and 046 * 32-bit unsigned integers, and 8-bit characters. 047 * <p> 048 * <b>How to Select a Subset</b> 049 * <p> 050 * Dataset defines APIs for reading, writing and subsetting a dataset. No function 051 * is defined to select a subset of a data array. The selection is done in an implicit 052 * way. Function calls to dimension information such as getSelectedDims() return an array 053 * of dimension values, which is a reference to the array in the dataset object. 054 * Changes of the array outside the dataset object directly change the values of 055 * the array in the dataset object. It is like pointers in C. 056 * <p> 057 * 058 * The following is an example of how to make a subset. In the example, the dataset 059 * is a 4-dimension with size of [200][100][50][10], i.e. 060 * dims[0]=200; dims[1]=100; dims[2]=50; dims[3]=10; <br> 061 * We want to select every other data point in dims[1] and dims[2] 062 * <pre> 063 int rank = dataset.getRank(); // number of dimensions of the dataset 064 long[] dims = dataset.getDims(); // the dimension sizes of the dataset 065 long[] selected = dataset.getSelectedDims(); // the selected size of the dataet 066 long[] start = dataset.getStartDims(); // the offset of the selection 067 long[] stride = dataset.getStride(); // the stride of the dataset 068 int[] selectedIndex = dataset.getSelectedIndex(); // the selected dimensions for display 069 070 // select dim1 and dim2 as 2D data for display,and slice through dim0 071 selectedIndex[0] = 1; 072 selectedIndex[1] = 2; 073 selectedIndex[1] = 0; 074 075 // reset the selection arrays 076 for (int i=0; i<rank; i++) { 077 start[i] = 0; 078 selected[i] = 1; 079 stride[i] = 1; 080 } 081 082 // set stride to 2 on dim1 and dim2 so that every other data point is selected. 083 stride[1] = 2; 084 stride[2] = 2; 085 086 // set the selection size of dim1 and dim2 087 selected[1] = dims[1]/stride[1]; 088 selected[2] = dims[1]/stride[2]; 089 090 // when dataset.read() is called, the slection above will be used since 091 // the dimension arrays is passed by reference. Changes of these arrays 092 // outside the dataset object directly change the values of these array 093 // in the dataset object. 094 095 * </pre> 096 * 097 * <p> 098 * @version 1.1 9/4/2007 099 * @author Peter X. Cao 100 */ 101public class H4SDS extends ScalarDS 102{ 103 private static final long serialVersionUID = 2557157923292438696L; 104 105 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4SDS.class); 106 107 /** tag for netCDF datasets. 108 * HDF4 library supports netCDF version 2.3.2. It only supports SDS APIs. 109 */ 110 // magic number for netCDF: "C(67) D(68) F(70) '\001'" 111 public static final int DFTAG_NDG_NETCDF = 67687001; 112 113 /** 114 * The list of attributes of this data object. Members of the list are 115 * instance of Attribute. 116 */ 117 @SuppressWarnings("rawtypes") 118 private List attributeList; 119 120 /** 121 * The SDS interface identifier obtained from SDstart(filename, access) 122 */ 123 private long sdid; 124 125 /** the datatype identifier */ 126 private long datatypeID = -1; 127 128 private int nAttributes = -1; 129 130 131 public H4SDS(FileFormat theFile, String name, String path) 132 { 133 this(theFile, name, path, null); 134 } 135 136 /** 137 * Creates an H4SDS object with specific name and path. 138 * 139 * @param theFile the HDF file. 140 * @param name the name of this H4SDS. 141 * @param path the full path of this H4SDS. 142 * @param oid the unique identifier of this data object. 143 */ 144 @SuppressWarnings("deprecation") 145 public H4SDS( 146 FileFormat theFile, 147 String name, 148 String path, 149 long[] oid) 150 { 151 super (theFile, name, path, oid); 152 unsignedConverted = false; 153 sdid = ((H4File)getFileFormat()).getSDAccessID(); 154 } 155 156 /* 157 * (non-Javadoc) 158 * @see hdf.object.DataFormat#hasAttribute() 159 */ 160 @Override 161 public boolean hasAttribute () 162 { 163 if (nAttributes < 0) { 164 sdid = ((H4File)getFileFormat()).getSDAccessID(); 165 166 long id = open(); 167 168 if (id >= 0) { 169 try { // retireve attributes of the dataset 170 String[] objName = {""}; 171 int[] sdInfo = {0, 0, 0}; 172 int[] tmpDim = new int[HDFConstants.MAX_VAR_DIMS]; 173 HDFLibrary.SDgetinfo(id, objName, tmpDim, sdInfo); 174 nAttributes = sdInfo[2]; 175 } 176 catch (Exception ex) { 177 log.debug("hasAttribute(): failure: ", ex); 178 nAttributes=0; 179 } 180 181 log.trace("hasAttribute(): nAttributes={}", nAttributes); 182 183 close(id); 184 } 185 } 186 187 return (nAttributes>0); 188 } 189 190 // ***** need to implement from ScalarDS ***** 191 @Override 192 public byte[][] readPalette(int idx) { return null;} 193 194 // ***** need to implement from ScalarDS ***** 195 @Override 196 public byte[] getPaletteRefs() { return null;} 197 198 // implementing Dataset 199 @Override 200 public Datatype getDatatype() 201 { 202 if (datatype == null) 203 { 204 datatype = new H4Datatype(datatypeID); 205 } 206 207 return datatype; 208 } 209 210 // To do: Implementing Dataset 211 @Override 212 public Dataset copy(Group pgroup, String dname, long[] dims, Object buff) 213 throws Exception 214 { 215 log.trace("copy(): start: parentGroup={} datasetName={}", pgroup, dname); 216 217 Dataset dataset = null; 218 long srcdid=-1, dstdid=-1, tid=-1; 219 int size=1, theRank=2; 220 String path=null; 221 int[] count=null, start=null; 222 223 if (pgroup == null) { 224 log.debug("copy(): Parent group is null"); 225 log.trace("copy(): finish"); 226 return null; 227 } 228 229 if (dname == null) { 230 dname = getName(); 231 } 232 233 if (pgroup.isRoot()) { 234 path = HObject.separator; 235 } 236 else { 237 path = pgroup.getPath()+pgroup.getName()+HObject.separator; 238 } 239 log.trace("copy(): path={}", path); 240 241 srcdid = open(); 242 if (srcdid < 0) { 243 log.debug("copy(): Invalid source SDID"); 244 log.trace("copy(): finish"); 245 return null; 246 } 247 248 if (dims == null) { 249 if (!isInited()) 250 init(); 251 252 theRank = getRank(); 253 254 dims = getDims(); 255 } 256 else { 257 theRank = dims.length; 258 } 259 260 start = new int[theRank]; 261 count = new int[theRank]; 262 for (int i=0; i<theRank; i++) { 263 start[i] = 0; 264 count[i] = (int)dims[i]; 265 size *= count[i]; 266 } 267 log.trace("copy(): theRank={} with size={}", theRank, size); 268 269 // create the new dataset and attach it to the parent group 270 tid = datatypeID; 271 dstdid = HDFLibrary.SDcreate( 272 ((H4File)pgroup.getFileFormat()).getSDAccessID(), 273 dname, tid, theRank, count); 274 if (dstdid < 0) { 275 log.debug("copy(): Invalid dest SDID"); 276 log.trace("copy(): finish"); 277 return null; 278 } 279 280 int ref = HDFLibrary.SDidtoref(dstdid); 281 if (!pgroup.isRoot()) { 282 long vgid = pgroup.open(); 283 HDFLibrary.Vaddtagref(vgid, HDFConstants.DFTAG_NDG, ref); 284 pgroup.close(vgid); 285 } 286 287 // copy attributes from one object to the new object 288 log.trace("copy(): copy attributes"); 289 copyAttribute(srcdid, dstdid); 290 291 // read data from the source dataset 292 log.trace("copy(): read data from the source dataset"); 293 if (buff == null) { 294 buff = new byte[size * HDFLibrary.DFKNTsize(tid)]; 295 HDFLibrary.SDreaddata(srcdid, start, null, count, buff); 296 } 297 298 // write the data into the destination dataset 299 log.trace("copy(): write the data into the destination dataset"); 300 HDFLibrary.SDwritedata(dstdid, start, null, count, buff); 301 302 long[] oid = {HDFConstants.DFTAG_NDG, ref}; 303 dataset = new H4SDS(pgroup.getFileFormat(), dname, path, oid); 304 305 pgroup.addToMemberList(dataset); 306 307 close(srcdid); 308 309 try { 310 HDFLibrary.SDendaccess(dstdid); 311 } 312 catch (HDFException ex) { 313 log.debug("copy(): SDendaccess failure: ", ex); 314 } 315 316 log.trace("copy(): finish"); 317 return dataset; 318 } 319 320 // Implementing Dataset 321 @Override 322 public byte[] readBytes() throws HDFException 323 { 324 log.trace("readBytes(): start"); 325 326 byte[] theData = null; 327 328 if (!isInited()) 329 init(); 330 331 long id = open(); 332 if (id < 0) { 333 log.debug("readBytes(): Invalid SDID"); 334 log.trace("readBytes(): finish"); 335 return null; 336 } 337 338 int datasize = 1; 339 int[] select = new int[rank]; 340 int[] start = new int[rank]; 341 for (int i=0; i<rank; i++) { 342 datasize *= (int)selectedDims[i]; 343 select[i] = (int)selectedDims[i]; 344 start[i] = (int)startDims[i]; 345 } 346 347 int[] stride = null; 348 if (selectedStride != null) { 349 stride = new int[rank]; 350 for (int i=0; i<rank; i++) { 351 stride[i] = (int)selectedStride[i]; 352 } 353 } 354 355 try { 356 int size = HDFLibrary.DFKNTsize(datatypeID)*datasize; 357 theData = new byte[size]; 358 HDFLibrary.SDreaddata(id, start, stride, select, theData); 359 } 360 catch (Exception ex) { 361 log.debug("readBytes(): failure: ", ex); 362 } 363 finally { 364 close(id); 365 } 366 367 log.trace("readBytes(): finish"); 368 return theData; 369 } 370 371 // Implementing DataFormat 372 @Override 373 public Object read() throws HDFException, OutOfMemoryError 374 { 375 log.trace("read(): start"); 376 377 Object theData = null; 378 379 if (!isInited()) 380 init(); 381 382 long id = open(); 383 if (id < 0) { 384 log.debug("read(): Invalid SDID"); 385 log.trace("read(): finish"); 386 return null; 387 } 388 389 int datasize = 1; 390 int[] select = new int[rank]; 391 int[] start = new int[rank]; 392 for (int i=0; i<rank; i++) { 393 datasize *= (int)selectedDims[i]; 394 select[i] = (int)selectedDims[i]; 395 start[i] = (int)startDims[i]; 396 } 397 398 int[] stride = null; 399 if (selectedStride != null) { 400 stride = new int[rank]; 401 for (int i=0; i<rank; i++) { 402 stride[i] = (int)selectedStride[i]; 403 } 404 } 405 406 try { 407 theData = H4Datatype.allocateArray(datatypeID, datasize); 408 409 if (theData != null) { 410 // assume external data files are located in the same directory as the main file. 411 HDFLibrary.HXsetdir(getFileFormat().getParent()); 412 413 HDFLibrary.SDreaddata(id, start, stride, select, theData); 414 415 if (isText) { 416 theData = byteToString((byte[])theData, select[0]); 417 } 418 } 419 } 420 catch (Exception ex) { 421 log.debug("read(): failure: ", ex); 422 } 423 finally { 424 close(id); 425 } 426 427 if (fillValue==null && isImageDisplay) { 428 try { 429 getMetadata(); 430 } // need to set fillValue for images 431 catch (Exception ex) { 432 log.debug("read(): getMetadata failure: ", ex); 433 } 434 } 435 436 if ((rank > 1) && (selectedIndex[0] > selectedIndex[1])) 437 isDefaultImageOrder = false; 438 else 439 isDefaultImageOrder = true; 440 441 log.trace("read(): isDefaultImageOrder={}", isDefaultImageOrder); 442 log.trace("read(): finish"); 443 return theData; 444 } 445 446 // Implementing DataFormat 447 @SuppressWarnings("deprecation") 448 @Override 449 public void write(Object buf) throws HDFException 450 { 451 log.trace("write(): start"); 452 453 if (buf == null) { 454 log.debug("write(): Object is null"); 455 log.trace("write(): finish"); 456 return; 457 } 458 459 long id = open(); 460 if (id < 0) { 461 log.debug("write(): Invalid SDID"); 462 log.trace("write(): finish"); 463 return; 464 } 465 466 int[] select = new int[rank]; 467 int[] start = new int[rank]; 468 for (int i=0; i<rank; i++) { 469 select[i] = (int)selectedDims[i]; 470 start[i] = (int)startDims[i]; 471 } 472 473 int[] stride = null; 474 if (selectedStride != null) { 475 stride = new int[rank]; 476 for (int i=0; i<rank; i++) { 477 stride[i] = (int)selectedStride[i]; 478 } 479 } 480 481 Object tmpData = buf; 482 try { 483 if (getDatatype().isUnsigned() && unsignedConverted) { 484 tmpData = convertToUnsignedC(buf); 485 } 486 // assume external data files are located in the same directory as the main file. 487 HDFLibrary.HXsetdir(getFileFormat().getParent()); 488 489 HDFLibrary.SDwritedata(id, start, stride, select, tmpData); 490 //} catch (Exception ex) {ex.printStackTrace(); 491 } 492 catch (Exception ex) { 493 log.debug("write(): failure: ", ex); 494 } 495 finally { 496 tmpData = null; 497 close(id); 498 } 499 500 log.trace("write(): finish"); 501 } 502 503 // Implementing DataFormat 504 @Override 505 @SuppressWarnings({"rawtypes", "unchecked"}) 506 public List getMetadata() throws HDFException 507 { 508 log.trace("getMetadata(): start"); 509 510 if (attributeList != null) { 511 log.trace("getMetdata(): attributeList != null"); 512 log.trace("getMetadata(): finish"); 513 return attributeList; 514 } 515 516 long id = open(); 517 String[] objName = {""}; 518 int[] sdInfo = {0, 0, 0}; 519 try { 520 // retrieve attributes of the dataset 521 int[] tmpDim = new int[HDFConstants.MAX_VAR_DIMS]; 522 HDFLibrary.SDgetinfo(id, objName, tmpDim, sdInfo); 523 int n = sdInfo[2]; 524 525 if ((attributeList == null) && (n>0)) { 526 attributeList = new Vector(n, 5); 527 } 528 529 boolean b = false; 530 String[] attrName = new String[1]; 531 int[] attrInfo = {0, 0}; 532 for (int i=0; i<n; i++) { 533 attrName[0] = ""; 534 try { 535 b = HDFLibrary.SDattrinfo(id, i, attrName, attrInfo); 536 // mask off the litend bit 537 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 538 } 539 catch (HDFException ex) { 540 log.debug("getMetadata(): attribute[{}] SDattrinfo failure: ", i, ex); 541 b = false; 542 } 543 544 if (!b) { 545 continue; 546 } 547 548 long[] attrDims = {attrInfo[1]}; 549 Attribute attr = new Attribute(this, attrName[0], new H4Datatype(attrInfo[0]), attrDims); 550 attributeList.add(attr); 551 552 Object buf = null; 553 try { 554 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 555 } 556 catch (OutOfMemoryError e) { 557 log.debug("getMetadata(): out of memory: ", e); 558 buf = null; 559 } 560 561 try { 562 HDFLibrary.SDreadattr(id, i, buf); 563 } 564 catch (HDFException ex) { 565 log.debug("getMetadata(): attribute[{}] SDreadattr failure: ", i, ex); 566 buf = null; 567 } 568 569 if (buf != null) { 570 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) || 571 (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) { 572 buf = Dataset.byteToString((byte[])buf, attrInfo[1]); 573 } 574 else if (attrName[0].equalsIgnoreCase("fillValue") || 575 attrName[0].equalsIgnoreCase("_fillValue")) { 576 fillValue = buf; 577 } 578 579 attr.setData(buf); 580 } 581 582 } // for (int i=0; i<n; i++) 583 584 // retrieve attribute of dimension 585 // BUG !! HDFLibrary.SDgetdimstrs(dimID, argv, 80) does not return anything 586 /* 587 for (int i=0; i< rank; i++) { 588 int dimID = HDFLibrary.SDgetdimid(id, i); 589 String[] argv = {" ", " ", " "}; 590 HDFLibrary.SDgetdimstrs(dimID, argv, 80); 591 } 592 */ 593 } 594 catch (Exception ex) { 595 log.debug("getMetadata(): failure: ", ex); 596 } 597 finally { 598 close(id); 599 } 600 601 log.trace("getMetadata(): finish"); 602 return attributeList; 603 } 604 605 // To do: implementing DataFormat 606 @Override 607 @SuppressWarnings({"rawtypes", "unchecked"}) 608 public void writeMetadata(Object info) throws Exception 609 { 610 log.trace("writeMetadata(): start"); 611 612 // only attribute metadata is supported. 613 if (!(info instanceof Attribute)) { 614 log.debug("writeMetadata(): Object not an Attribute"); 615 log.trace("writeMetadata(): finish"); 616 return; 617 } 618 619 try { 620 getFileFormat().writeAttribute(this, (Attribute)info, true); 621 622 if (attributeList == null) { 623 attributeList = new Vector(); 624 } 625 626 attributeList.add(info); 627 nAttributes = attributeList.size(); 628 } 629 catch (Exception ex) { 630 log.trace("writeMetadata(): failure: ", ex); 631 } 632 633 log.trace("writeMetadata(): finish"); 634 } 635 636 // To do: implementing DataFormat 637 @Override 638 public void removeMetadata(Object info) throws HDFException { 639 log.trace("removeMetadata(): disabled"); 640 } 641 642 // implementing DataFormat 643 @Override 644 public void updateMetadata(Object info) throws Exception { 645 log.trace("updateMetadata(): disabled"); 646 } 647 648 // Implementing HObject 649 @Override 650 public long open() 651 { 652 log.trace("open(): start"); 653 654 long id=-1; 655 656 try { 657 int index = 0; 658 int tag = (int)oid[0]; 659 660 log.trace("open(): tag={}", tag); 661 if (tag == H4SDS.DFTAG_NDG_NETCDF) { 662 index = (int)oid[1]; //HDFLibrary.SDidtoref(id) fails for netCDF 663 } 664 else { 665 index = HDFLibrary.SDreftoindex(sdid, (int)oid[1]); 666 } 667 668 id = HDFLibrary.SDselect(sdid,index); 669 } 670 catch (HDFException ex) { 671 log.debug("open(): failure: ", ex); 672 id = -1; 673 } 674 675 log.trace("open(): finish"); 676 return id; 677 } 678 679 // Implementing HObject 680 @Override 681 public void close(long id) 682 { 683 try { HDFLibrary.SDendaccess(id); } 684 catch (HDFException ex) { log.debug("close(): failure: ", ex); } 685 } 686 687 /** 688 * Initializes the H4SDS such as dimension size of this dataset. 689 */ 690 @SuppressWarnings("deprecation") 691 @Override 692 public void init() 693 { 694 log.trace("init(): start"); 695 696 if (inited) { 697 log.trace("init(): Already initialized"); 698 log.trace("init(): finish"); 699 return; // already called. Initialize only once 700 } 701 702 long id = open(); 703 String[] objName = {""}; 704 String[] dimName = {""}; 705 int[] dimInfo = {0, 0, 0}; 706 int[] sdInfo = {0, 0, 0}; 707 boolean isUnlimited = false; 708 709 int[] idims = new int[HDFConstants.MAX_VAR_DIMS]; 710 try { 711 HDFLibrary.SDgetinfo(id, objName, idims, sdInfo); 712 // mask off the litend bit 713 sdInfo[1] = sdInfo[1] & (~HDFConstants.DFNT_LITEND); 714 nAttributes = sdInfo[2]; 715 rank = sdInfo[0]; 716 717 if (rank <= 0) { 718 rank = 1; 719 idims[0] = 1; 720 } 721 722 isUnlimited = HDFLibrary.SDisrecord(id); 723 log.trace("init(): isUnlimited={}", isUnlimited); 724 725 datatypeID = sdInfo[1]; 726 isText = ((datatypeID == HDFConstants.DFNT_CHAR) || (datatypeID == HDFConstants.DFNT_UCHAR8)); 727 728 // get the dimension names 729 try { 730 dimNames = new String[rank]; 731 for (int i=0; i<rank; i++) { 732 long dimid = HDFLibrary.SDgetdimid(id, i); 733 HDFLibrary.SDdiminfo(dimid, dimName, dimInfo); 734 dimNames[i] = dimName[0]; 735 } 736 } 737 catch (Exception ex) { 738 log.debug("init(): get the dimension names: ", ex); 739 } 740 741 // get compression information 742 try { 743 HDFCompInfo compInfo = new HDFCompInfo(); 744 745 HDFLibrary.SDgetcompinfo(id, compInfo); 746 if (compInfo.ctype == HDFConstants.COMP_CODE_DEFLATE) { 747 HDFDeflateCompInfo comp = new HDFDeflateCompInfo(); 748 HDFLibrary.SDgetcompinfo(id, comp); 749 compression = "GZIP(level="+comp.level+")"; 750 } 751 else if (compInfo.ctype == HDFConstants.COMP_CODE_SZIP) { 752 HDFSZIPCompInfo comp = new HDFSZIPCompInfo(); 753 HDFLibrary.SDgetcompinfo(id, comp); 754 compression = "SZIP(bits_per_pixel="+comp.bits_per_pixel+",options_mask="+comp.options_mask+ 755 ",pixels="+comp.pixels+",pixels_per_block="+comp.pixels_per_block+ 756 ",pixels_per_scanline="+comp.pixels_per_scanline+")"; 757 } 758 else if (compInfo.ctype == HDFConstants.COMP_CODE_JPEG) { 759 HDFJPEGCompInfo comp = new HDFJPEGCompInfo(); 760 HDFLibrary.SDgetcompinfo(id, comp); 761 compression = "JPEG(quality="+comp.quality+",options_mask="+ 762 ",force_baseline="+comp.force_baseline+")"; 763 } 764 else if (compInfo.ctype == HDFConstants.COMP_CODE_SKPHUFF) { 765 HDFSKPHUFFCompInfo comp = new HDFSKPHUFFCompInfo(); 766 HDFLibrary.SDgetcompinfo(id, comp); 767 compression = "SKPHUFF(skp_size="+comp.skp_size+")"; 768 } 769 else if (compInfo.ctype == HDFConstants.COMP_CODE_RLE) { 770 compression = "RLE"; 771 } 772 else if (compInfo.ctype == HDFConstants.COMP_CODE_NBIT) { 773 HDFNBITCompInfo comp = new HDFNBITCompInfo(); 774 HDFLibrary.SDgetcompinfo(id, comp); 775 compression = "NBIT(nt="+comp.nt+",bit_len="+comp.bit_len+",ctype="+comp.ctype+ 776 ",fill_one="+comp.fill_one+",sign_ext="+comp.sign_ext+ 777 ",start_bit="+comp.start_bit+")"; 778 } 779 } 780 catch (Exception ex) { 781 log.debug("init(): get compression information failure: ", ex); 782 } 783 784 // get chunk information 785 try { 786 HDFChunkInfo chunkInfo = new HDFChunkInfo(); 787 int[] cflag = {HDFConstants.HDF_NONE}; 788 789 try { 790 HDFLibrary.SDgetchunkinfo(id, chunkInfo, cflag); 791 } 792 catch (Throwable ex) { 793 ex.printStackTrace(); 794 } 795 796 if (cflag[0] == HDFConstants.HDF_NONE) { 797 chunkSize = null; 798 storage_layout = "NONE"; 799 } 800 else { 801 chunkSize = new long[rank]; 802 for (int i=0; i<rank; i++) { 803 chunkSize[i] = chunkInfo.chunk_lengths[i]; 804 } 805 storage_layout = "CHUNKED: " + String.valueOf(chunkSize[0]); 806 for (int i = 1; i < rank; i++) { 807 storage_layout += " X " + chunkSize[i]; 808 } 809 } 810 } 811 catch (Exception ex) { 812 log.debug("init(): get chunk information failure: ", ex); 813 } 814 815 inited = true; 816 } 817 catch (HDFException ex) { 818 log.debug("init(): failure: ", ex); 819 } 820 finally { 821 close(id); 822 } 823 824 dims = new long[rank]; 825 maxDims = new long[rank]; 826 startDims = new long[rank]; 827 selectedDims = new long[rank]; 828 829 for (int i=0; i<rank; i++) { 830 startDims[i] = 0; 831 selectedDims[i] = 1; 832 dims[i] = maxDims[i] = idims[i]; 833 } 834 835 if (isUnlimited) 836 maxDims[0] = -1; 837 838 selectedIndex[0] = 0; 839 selectedIndex[1] = 1; 840 selectedIndex[2] = 2; 841 842 // select only two dimension a time, 843 if (rank == 1) { 844 selectedDims[0] = dims[0]; 845 } 846 847 if (rank > 1) { 848 selectedDims[0] = dims[0]; 849 if (isText) { 850 selectedDims[1] = 1; 851 } 852 else { 853 selectedDims[1] = dims[1]; 854 } 855 } 856 857 log.trace("init(): finish"); 858 } 859 860 // Implementing ScalarDS 861 @Override 862 public byte[][] getPalette() 863 { 864 return palette; 865 } 866 867 /** 868 * Creates a new dataset. 869 * 870 * @param name the name of the dataset to create. 871 * @param pgroup the parent group of the new dataset. 872 * @param type the datatype of the dataset. 873 * @param dims the dimension size of the dataset. 874 * @param maxdims the max dimension size of the dataset. 875 * @param chunks the chunk size of the dataset. 876 * @param gzip the level of the gzip compression. 877 * @param fillValue the default value. 878 * @param data the array of data values. 879 * 880 * @return the new dataset if successful. Otherwise returns null. 881 * 882 * @throws Exception if the dataset can not be created 883 */ 884 public static H4SDS create( 885 String name, 886 Group pgroup, 887 Datatype type, 888 long[] dims, 889 long[] maxdims, 890 long[] chunks, 891 int gzip, 892 Object fillValue, 893 Object data) throws Exception 894 { 895 log.trace("create(): start"); 896 897 H4SDS dataset = null; 898 if ((pgroup == null) || 899 (name == null)|| 900 (dims == null)) { 901 log.trace("create(): Parent group, name or dims is null"); 902 log.trace("create(): finish"); 903 return null; 904 } 905 906 H4File file = (H4File)pgroup.getFileFormat(); 907 908 if (file == null) { 909 log.trace("create(): Parent group FileFormat is null"); 910 log.trace("create(): finish"); 911 return null; 912 } 913 914 String path = HObject.separator; 915 if (!pgroup.isRoot()) { 916 path = pgroup.getPath()+pgroup.getName()+HObject.separator; 917 } 918 // prepare the dataspace 919 // int tsize = 1; 920 int rank = dims.length; 921 int idims[] = new int[rank]; 922 int start[] = new int [rank]; 923 for (int i=0; i<rank; i++) { 924 idims[i] = (int)dims[i]; 925 start[i] = 0; 926 // tsize *= idims[i]; 927 } 928 929 // only the first element of the SDcreate parameter dim_sizes (i.e., 930 // the dimension of the lowest rank or the slowest-changing dimension) 931 // can be assigned the value SD_UNLIMITED (or 0) to make the first 932 // dimension unlimited. 933 if ((maxdims != null) && (maxdims[0]<=0)) { 934 idims[0] = 0; // set to unlimited dimension. 935 } 936 937 int ichunks[] = null; 938 if (chunks != null) { 939 ichunks = new int[rank]; 940 for (int i=0; i<rank; i++) { 941 ichunks[i] = (int)chunks[i]; 942 } 943 } 944 945 // unlimted cannot be used with chunking or compression for HDF 4.2.6 or earlier. 946 if (idims[0] == 0 && (ichunks != null || gzip>0)) { 947 log.debug("create(): Unlimited cannot be used with chunking or compression"); 948 log.trace("create(): finish"); 949 throw new HDFException("Unlimited cannot be used with chunking or compression"); 950 } 951 952 long sdid = (file).getSDAccessID(); 953 long sdsid = -1; 954 long vgid = -1; 955 long tid = type.createNative(); 956 957 if(tid >= 0) { 958 try { 959 sdsid = HDFLibrary.SDcreate(sdid, name, tid, rank, idims); 960 // set fill value to zero. 961 int vsize = HDFLibrary.DFKNTsize(tid); 962 byte[] fill = new byte[vsize]; 963 for (int i=0; i<vsize; i++) { 964 fill[i] = 0; 965 } 966 HDFLibrary.SDsetfillvalue(sdsid, fill); 967 968 // when we create a new dataset with unlimited dimension, 969 // we have to write some data into the dataset or otherwise 970 // the current dataset has zero dimensin size. 971 972 // comment out the following lines because SDwritedata fails when 973 // try to write data into a zero dimension array. 05/25/05 974 // don't know why the code was first put here ???? 975 /** 976 if (idims[0] == 0 && data == null) 977 { 978 idims[0] = (int)dims[0]; 979 data = new byte[tsize*vsize]; 980 } 981 */ 982 983 } 984 catch (Exception ex) { 985 log.debug("create(): failure: ", ex); 986 log.trace("create(): finish"); 987 throw (ex); 988 } 989 } 990 991 if (sdsid < 0) { 992 log.debug("create(): Dataset creation failed"); 993 log.trace("create(): finish"); 994 throw (new HDFException("Unable to create the new dataset.")); 995 } 996 997 HDFDeflateCompInfo compInfo = null; 998 if (gzip > 0) { 999 // set compression 1000 compInfo = new HDFDeflateCompInfo(); 1001 compInfo.level = gzip; 1002 if (chunks == null) 1003 HDFLibrary.SDsetcompress(sdsid, HDFConstants.COMP_CODE_DEFLATE, compInfo); 1004 } 1005 1006 if (chunks != null) { 1007 // set chunk 1008 HDFChunkInfo chunkInfo = new HDFChunkInfo(ichunks); 1009 int flag = HDFConstants.HDF_CHUNK; 1010 1011 if (gzip > 0) { 1012 flag = HDFConstants.HDF_CHUNK | HDFConstants.HDF_COMP; 1013 chunkInfo = new HDFChunkInfo(ichunks, HDFConstants.COMP_CODE_DEFLATE, compInfo); 1014 } 1015 1016 try { 1017 HDFLibrary.SDsetchunk (sdsid, chunkInfo, flag); 1018 } 1019 catch (Throwable err) { 1020 log.debug("create(): SDsetchunk failure: ", err); 1021 err.printStackTrace(); 1022 log.trace("create(): finish"); 1023 throw new HDFException("SDsetchunk failed."); 1024 } 1025 } 1026 1027 if ((sdsid > 0) && (data != null)) { 1028 HDFLibrary.SDwritedata(sdsid, start, null, idims, data); 1029 } 1030 1031 int ref = HDFLibrary.SDidtoref(sdsid); 1032 1033 if (!pgroup.isRoot()) { 1034 // add the dataset to the parent group 1035 vgid = pgroup.open(); 1036 if (vgid < 0) 1037 { 1038 if (sdsid > 0) { 1039 HDFLibrary.SDendaccess(sdsid); 1040 } 1041 log.debug("create(): Invalid Parent Group ID"); 1042 log.trace("create(): finish"); 1043 throw (new HDFException("Unable to open the parent group.")); 1044 } 1045 1046 HDFLibrary.Vaddtagref(vgid, HDFConstants.DFTAG_NDG, ref); 1047 1048 pgroup.close(vgid); 1049 } 1050 1051 try { 1052 if (sdsid > 0) { 1053 HDFLibrary.SDendaccess(sdsid); 1054 } 1055 } 1056 catch (Exception ex) { 1057 log.debug("create(): SDendaccess failure: ", ex); 1058 } 1059 1060 long[] oid = {HDFConstants.DFTAG_NDG, ref}; 1061 dataset = new H4SDS(file, name, path, oid); 1062 1063 if (dataset != null) { 1064 pgroup.addToMemberList(dataset); 1065 } 1066 1067 log.trace("create(): finish"); 1068 return dataset; 1069 } 1070 1071 public static H4SDS create( 1072 String name, 1073 Group pgroup, 1074 Datatype type, 1075 long[] dims, 1076 long[] maxdims, 1077 long[] chunks, 1078 int gzip, 1079 Object data) throws Exception 1080 { 1081 return create(name, pgroup, type, dims, maxdims, chunks, gzip, null, data); 1082 } 1083 1084 /** 1085 * copy attributes from one SDS to another SDS 1086 */ 1087 private void copyAttribute(long srcdid, long dstdid) 1088 { 1089 log.trace("copyAttribute(): start: srcdid={} dstdid={}", srcdid, dstdid); 1090 try { 1091 String[] objName = {""}; 1092 int[] sdInfo = {0, 0, 0}; 1093 int[] tmpDim = new int[HDFConstants.MAX_VAR_DIMS]; 1094 HDFLibrary.SDgetinfo(srcdid, objName, tmpDim, sdInfo); 1095 int numberOfAttributes = sdInfo[2]; 1096 log.trace("copyAttribute(): numberOfAttributes={}", numberOfAttributes); 1097 1098 boolean b = false; 1099 String[] attrName = new String[1]; 1100 int[] attrInfo = {0, 0}; 1101 for (int i=0; i<numberOfAttributes; i++) { 1102 attrName[0] = ""; 1103 try { 1104 b = HDFLibrary.SDattrinfo(srcdid, i, attrName, attrInfo); 1105 } 1106 catch (HDFException ex) { 1107 log.debug("copyAttribute(): attribute[{}] SDattrinfo failure: ", i, ex); 1108 b = false; 1109 } 1110 1111 if (!b) { 1112 continue; 1113 } 1114 1115 // read attribute data from source dataset 1116 byte[] attrBuff = new byte[attrInfo[1] * HDFLibrary.DFKNTsize(attrInfo[0])]; 1117 try { 1118 HDFLibrary.SDreadattr(srcdid, i, attrBuff); 1119 } 1120 catch (HDFException ex) { 1121 log.debug("copyAttribute(): attribute[{}] SDreadattr failure: ", i, ex); 1122 attrBuff = null; 1123 } 1124 1125 if (attrBuff == null) { 1126 log.debug("copyAttribute(): attrBuff[{}] is null", i); 1127 log.trace("copyAttribute(): continue"); 1128 continue; 1129 } 1130 1131 // attach attribute to the destination dataset 1132 HDFLibrary.SDsetattr(dstdid, attrName[0], attrInfo[0], attrInfo[1], attrBuff); 1133 } // for (int i=0; i<numberOfAttributes; i++) 1134 } 1135 catch (Exception ex) { 1136 log.debug("copyAttribute(): failure: ", ex); 1137 } 1138 1139 log.trace("copyAttribute(): finish"); 1140 } 1141 1142 //Implementing DataFormat 1143 @SuppressWarnings("rawtypes") 1144 public List getMetadata(int... attrPropList) throws Exception { 1145 throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported"); 1146 } 1147}