Diff of /HDF5/Dataset.pm [89b140] .. [0ad34b] Maximize Restore

  Switch to unified view

a/HDF5/Dataset.pm b/HDF5/Dataset.pm
...
...
3
use Carp;
3
use Carp;
4
4
5
use strict;
5
use strict;
6
6
7
# Global mapping variables
7
# Global mapping variables
8
our ($H5T_STRING, %PDLtoHDF5internalTypeMapping, %HDF5toPDLfileMapping, %PDLtoHDF5fileMapping);
8
our ($H5T_STRING, $H5T_REFERENCE, %PDLtoHDF5internalTypeMapping, %HDF5toPDLfileMapping, %PDLtoHDF5fileMapping);
9
9
10
=head1 NAME
10
=head1 NAME
11
11
12
PDL::IO::HDF5::Dataset - PDL::IO::HDF5 Helper Object representing HDF5 datasets.
12
PDL::IO::HDF5::Dataset - PDL::IO::HDF5 Helper Object representing HDF5 datasets.
13
13
14
=head1 DESCRIPTION
14
=head1 DESCRIPTION
15
15
16
This is a helper-object used by PDL::IO::HDF5 to interface with HDF5 format's dataset objects.
16
This is a helper-object used by PDL::IO::HDF5 to interface with HDF5 format's dataset objects.
17
Information on the HDF5 Format can be found
17
Information on the HDF5 Format can be found
18
at the NCSA's web site at http://hdf.ncsa.uiuc.edu/ .
18
at the HDF Group's web site at http://www.hdfgroup.org .
19
19
20
=head1 SYNOPSIS
20
=head1 SYNOPSIS
21
21
22
See L<PDL::IO::HDF5>
22
See L<PDL::IO::HDF5>
23
23
...
...
166
166
167
B<Usage:>
167
B<Usage:>
168
168
169
=for usage
169
=for usage
170
170
171
 $dataset->set($pdl);     # Write the array data in the dataset
171
 $dataset->set($pdl, unlimited => 1);     # Write the array data in the dataset
172
173
     Options:
174
     unlimited     If present, the dataset is created with unlimited dimensions.
172
175
173
=cut
176
=cut
174
177
175
178
176
#############################################################################
179
#############################################################################
...
...
203
206
204
sub set{
207
sub set{
205
208
206
    my $self = shift;
209
    my $self = shift;
207
210
208
  my ($pdl) = @_;
211
  my $pdl = shift;
209
212
213
  my %options = @_
214
      if ( scalar(@_) >= 1 );
210
215
211
    my $parent = $self->{parent};
216
    my $parent = $self->{parent};
212
    my $groupID = $parent->IDget;
217
    my $groupID = $parent->IDget;
213
    my $datasetID = $self->{ID};
218
    my $datasetID = $self->{ID};
214
    my $name = $self->{name};
219
    my $name = $self->{name};
...
...
251
256
252
257
253
    
258
    
254
    
259
    
255
        my $dims = PDL::IO::HDF5::packList(@dims);
260
        my $dims = PDL::IO::HDF5::packList(@dims);
256
          
261
262
  my $udims = $dims;
263
  if ( exists($options{'unlimited'}) ) {
264
      my $udim = pack ("L*", (PDL::IO::HDF5::H5S_UNLIMITED()));
265
      my $rank = scalar(@dims)*2;
266
      $udims = $udim x $rank;
257
    
267
    }
258
    my $dataspaceID = PDL::IO::HDF5::H5Screate_simple(scalar(@dims), $dims , $dims);
268
    my $dataspaceID = PDL::IO::HDF5::H5Screate_simple(scalar(@dims), $dims , $udims);
259
        if( $dataspaceID < 0 ){
269
        if( $dataspaceID < 0 ){
260
        carp("Can't Open Dataspace in ".__PACKAGE__.":set\n");
270
        carp("Can't Open Dataspace in ".__PACKAGE__.":set\n");
261
        return undef;
271
        return undef;
262
    }
272
    }
263
273
264
    if( $datasetID == 0){  # Dataset not created yet
274
    if( $datasetID == 0){  # Dataset not created yet
265
  
275
276
      my $propertiesID;
277
      if ( exists($options{'unlimited'}) ) {
278
      $propertiesID = PDL::IO::HDF5::H5Pcreate(PDL::IO::HDF5::H5P_DATASET_CREATE());
279
      if( $propertiesID < 0 ){
280
          carp("Can't Open Properties in ".__PACKAGE__.":set\n");
281
          return undef;
282
      }       
283
      if ( PDL::IO::HDF5::H5Pset_chunk($propertiesID,scalar(@dims),$dims) < 0 ) {
284
          carp("Error setting chunk size in ".__PACKAGE__.":set\n");
285
          return undef;
286
      }   
287
      # /* Create the dataset. */
288
      $datasetID = PDL::IO::HDF5::H5Dcreate($groupID, $name, $hdf5Filetype, $dataspaceID, 
289
                            $propertiesID);
290
      } else {
266
           # /* Create the dataset. */
291
           # /* Create the dataset. */
267
        $datasetID = PDL::IO::HDF5::H5Dcreate($groupID, $name, $hdf5Filetype, $dataspaceID, 
292
        $datasetID = PDL::IO::HDF5::H5Dcreate($groupID, $name, $hdf5Filetype, $dataspaceID, 
268
                PDL::IO::HDF5::H5P_DEFAULT());
293
                            PDL::IO::HDF5::H5P_DEFAULT());
294
      }
269
      if( $datasetID < 0){
295
        if( $datasetID < 0){
270
         carp("Can't Create Dataspace in ".__PACKAGE__.":set\n");
296
        carp("Can't Create Dataspace in ".__PACKAGE__.":set\n");
271
         return undef;
297
        return undef;
272
      }
298
      }
273
      $self->{ID} = $datasetID;
299
        $self->{ID} = $datasetID;
300
301
      if ( exists($options{'unlimited'}) ) {
302
      if ( PDL::IO::HDF5::H5Pclose($propertiesID) < 0 ) {
303
          carp("Error closing properties in ".__PACKAGE__.":set\n");
304
          return undef;
305
      }
306
      }
274
    }
307
    }
275
308
276
    # Write the actual data:
309
    # Write the actual data:
277
        my $data = ${$pdl->get_dataref};
310
        my $data = ${$pdl->get_dataref};
278
    
311
    
312
  if( PDL::IO::HDF5::H5Dextend($datasetID,$dims) < 0 ){ 
313
      carp("Error extending dataset in ".__PACKAGE__.":set\n");
314
      return undef;
315
  }
279
316
280
    if( PDL::IO::HDF5::H5Dwrite($datasetID, $internalhdf5_type, PDL::IO::HDF5::H5S_ALL(), PDL::IO::HDF5::H5S_ALL(), PDL::IO::HDF5::H5P_DEFAULT(),
317
    if( PDL::IO::HDF5::H5Dwrite($datasetID, $internalhdf5_type, PDL::IO::HDF5::H5S_ALL(), PDL::IO::HDF5::H5S_ALL(), PDL::IO::HDF5::H5P_DEFAULT(),
281
        $data) < 0 ){ 
318
        $data) < 0 ){ 
282
319
283
        carp("Error Writing to dataset in ".__PACKAGE__.":set\n");
320
        carp("Error Writing to dataset in ".__PACKAGE__.":set\n");
...
...
357
 PDL::IO::HDF5::H5T_IEEE_F64LE()=>  $PDL::Types::PDL_D
394
 PDL::IO::HDF5::H5T_IEEE_F64LE()=>  $PDL::Types::PDL_D
358
395
359
For HDF5 File types not in this table, this method will attempt to
396
For HDF5 File types not in this table, this method will attempt to
360
map it to the default PDL type PDL_D.
397
map it to the default PDL type PDL_D.
361
398
399
If the dataset being read is a scalar reference, the referenced dataset region will be read instead.
400
362
B<Note:>
401
B<Note:>
363
402
 
364
Character arrays are returned as the special L<PDL::Char> fixed-length string type. For fixed-length
403
Character arrays are returned as the special L<PDL::Char> fixed-length string type. For fixed-length
365
HDF5 string arrays, this is a direct mapping to the PDL::Char datatype. For HDF5 variable-length string
404
HDF5 string arrays, this is a direct mapping to the PDL::Char datatype. For HDF5 variable-length string
366
arrays, the data is converted to a fixed-length character array, with a string size equal to the maximum
405
arrays, the data is converted to a fixed-length character array, with a string size equal to the maximum
367
size of all the strings in the array.
406
size of all the strings in the array.
368
407
...
...
393
     PDL::IO::HDF5::H5T_IEEE_F32LE()    =>  $PDL::Types::PDL_F,
432
     PDL::IO::HDF5::H5T_IEEE_F32LE()    =>  $PDL::Types::PDL_F,
394
     PDL::IO::HDF5::H5T_IEEE_F64BE()    =>  $PDL::Types::PDL_D,
433
     PDL::IO::HDF5::H5T_IEEE_F64BE()    =>  $PDL::Types::PDL_D,
395
     PDL::IO::HDF5::H5T_IEEE_F64LE()    =>  $PDL::Types::PDL_D
434
     PDL::IO::HDF5::H5T_IEEE_F64LE()    =>  $PDL::Types::PDL_D
396
);
435
);
397
436
398
$H5T_STRING = PDL::IO::HDF5::H5T_STRING();  #HDF5 string type
437
$H5T_STRING    = PDL::IO::HDF5::H5T_STRING   (); #HDF5 string type
438
$H5T_REFERENCE = PDL::IO::HDF5::H5T_REFERENCE(); #HDF5 reference type
399
439
400
sub get{
440
sub get{
401
441
402
    my $self = shift;
442
    my $self = shift;
403
    my $start = shift;
443
    my $start = shift;
404
    my $end = shift;
444
    my $end = shift;
405
    my $stride = shift;
445
    my $stride = shift;
406
446
407
    my $pdl;
447
    my $pdl;
408
448
409
    my $rc; # H5 library call return code
449
     my $rc; # H5 library call return code
410
450
411
    my $parent = $self->{parent};
451
    my $parent = $self->{parent};
412
    my $groupID = $parent->IDget;
452
    my $groupID = $parent->IDget;
413
    my $datasetID = $self->{ID};
453
    my $datasetID = $self->{ID};
414
    my $name = $self->{name};
454
    my $name = $self->{name};
...
...
418
                    #  the file)
458
                    #  the file)
419
459
420
    my $ReturnType = 'PDL';         # Default object returned is PDL. If strings are store, then this will
460
    my $ReturnType = 'PDL';         # Default object returned is PDL. If strings are store, then this will
421
                    # return PDL::Char
461
                    # return PDL::Char
422
462
463
  my $isReference = 0;            # Indicates if dataset is a reference
464
  my $datasetReference;           # Data set reference
465
  my $referencedDatasetID;        # ID of referenced dataset
466
423
    # Get the HDF5 file datatype;
467
    # Get the HDF5 file datatype;
424
        my $HDF5type = PDL::IO::HDF5::H5Dget_type($datasetID );
468
        my $HDF5type = PDL::IO::HDF5::H5Dget_type($datasetID );
425
    unless( $HDF5type >= 0 ){
469
    unless( $HDF5type >= 0 ){
426
        carp "Error Calling ".__PACKAGE__."::get: Can't get HDF5 Dataset type.\n";
470
        carp "Error Calling ".__PACKAGE__."::get: Can't get HDF5 Dataset type.\n";
427
        return undef;
471
        return undef;
428
    }
472
    }
429
473
430
    # Check for string type:
474
    # Check for string type:
431
    my $varLenString = 0; # Flag = 1 if reading variable-length string array
475
     my $varLenString = 0; # Flag = 1 if reading variable-length string array
432
    if( PDL::IO::HDF5::H5Tget_class($HDF5type ) == $H5T_STRING ){  # String type
476
    if( PDL::IO::HDF5::H5Tget_class($HDF5type ) == $H5T_STRING ){  # String type
433
477
434
            # Check for variable length string"
478
            # Check for variable length string"
435
            if( ! PDL::IO::HDF5::H5Tis_variable_str($HDF5type ) ){
479
            if( ! PDL::IO::HDF5::H5Tis_variable_str($HDF5type ) ){
436
                    # Not a variable length string
480
                    # Not a variable length string
...
...
454
498
455
        $PDLtype = $PDL::Types::PDL_B; 
499
        $PDLtype = $PDL::Types::PDL_B; 
456
        $ReturnType = 'PDL::Char';   # For strings, we return a PDL::Char
500
        $ReturnType = 'PDL::Char';   # For strings, we return a PDL::Char
457
501
458
    }
502
    }
503
  elsif ( PDL::IO::HDF5::H5Tget_class($HDF5type) == $H5T_REFERENCE ) { # Reference type
504
505
      # Flag that dataset is a reference
506
      $isReference = 1;
507
508
      # Check that the reference dataset is a single element
509
      my $dataspaceID = PDL::IO::HDF5::H5Dget_space($datasetID);
510
      my $Ndims = PDL::IO::HDF5::H5Sget_simple_extent_ndims($dataspaceID);
511
      if( $Ndims != 0 ){
512
          carp("Can't handle non-scalar references ".__PACKAGE__.":get\n");
513
          carp("Can't close Dataspace in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Sclose($dataspaceID) < 0);
514
          return undef;
515
      }      
516
517
            # Read the reference
518
      my $howBig =  PDL::IO::HDF5::H5Tget_size(PDL::IO::HDF5::H5T_STD_REF_DSETREG());
519
      $datasetReference = ' ' x $howBig;
520
      $rc = PDL::IO::HDF5::H5Dread($datasetID, PDL::IO::HDF5::H5T_STD_REF_DSETREG(), PDL::IO::HDF5::H5S_ALL(),
521
                   PDL::IO::HDF5::H5S_ALL(), 
522
                   PDL::IO::HDF5::H5P_DEFAULT(),
523
                   $datasetReference);
524
      # Dereference the reference
525
      $referencedDatasetID = PDL::IO::HDF5::H5Rdereference($datasetID,PDL::IO::HDF5::H5R_DATASET_REGION(),$datasetReference);
526
527
      # Get the data type of the dereferenced object
528
      $HDF5type = PDL::IO::HDF5::H5Dget_type($referencedDatasetID);
529
      
530
      # Map the HDF5 file datatype to a PDL datatype
531
      $PDLtype = $PDL::Types::PDL_D; # Default type is double
532
533
      my $defaultType;
534
      foreach $defaultType( keys %HDF5toPDLfileMapping){
535
      if( PDL::IO::HDF5::H5Tequal($defaultType,$HDF5type) > 0){
536
          $PDLtype = $HDF5toPDLfileMapping{$defaultType};
537
          last;
538
      }
539
      }
540
      
541
      
542
      # Get the HDF5 internal datatype that corresponds to the PDL type
543
      unless( defined($PDLtoHDF5internalTypeMapping{$PDLtype}) ){
544
      carp "Error Calling ".__PACKAGE__."::set: Can't map PDL type to HDF5 datatype\n";
545
      return undef;
546
      }
547
      $internalhdf5_type = $PDLtoHDF5internalTypeMapping{$PDLtype};
548
549
  }
459
    else{  # Normal Numeric Type
550
    else{  # Normal Numeric Type
460
        # Map the HDF5 file datatype to a PDL datatype
551
        # Map the HDF5 file datatype to a PDL datatype
461
        $PDLtype = $PDL::Types::PDL_D; # Default type is double
552
        $PDLtype = $PDL::Types::PDL_D; # Default type is double
462
        
553
        
463
        my $defaultType;
554
        my $defaultType;
...
...
475
            return undef;
566
            return undef;
476
        }
567
        }
477
        $internalhdf5_type = $PDLtoHDF5internalTypeMapping{$PDLtype};
568
        $internalhdf5_type = $PDLtoHDF5internalTypeMapping{$PDLtype};
478
    }
569
    }
479
570
571
  my $dataspaceID;
572
  if ( $isReference == 1 ) {
573
      # Get the dataspace from the reference
574
      $dataspaceID = PDL::IO::HDF5::H5Rget_region($datasetID,PDL::IO::HDF5::H5R_DATASET_REGION(),$datasetReference);      
575
      # Now reset the dataset ID to that of the referenced dataset for all further use
576
      $datasetID = $referencedDatasetID;
577
  } else {
578
      # Get the dataspace from the dataset itself
480
    my $dataspaceID = PDL::IO::HDF5::H5Dget_space($datasetID);
579
        $dataspaceID = PDL::IO::HDF5::H5Dget_space($datasetID);
580
  }
481
    if( $dataspaceID < 0 ){
581
    if( $dataspaceID < 0 ){
482
        carp("Can't Open Dataspace in ".__PACKAGE__.":get\n");
582
        carp("Can't Open Dataspace in ".__PACKAGE__.":get\n");
483
        carp("Can't close Datatype in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
583
        carp("Can't close Datatype in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
484
        return undef;
584
        return undef;
485
    }
585
    }
...
...
495
    }
595
    }
496
596
497
597
498
    my @dims = ( 0..($Ndims-1)); 
598
    my @dims = ( 0..($Ndims-1)); 
499
    my ($mem_space,$file_space);
599
    my ($mem_space,$file_space);
600
  if ( $isReference == 1) {
601
      my @startAt = ( 0..($Ndims-1)); 
602
      my @endAt = ( 0..($Ndims-1)); 
603
      my $startAt = PDL::IO::HDF5::packList(@startAt);
604
      my $endAt = PDL::IO::HDF5::packList(@endAt);
605
      
606
      my $rc = PDL::IO::HDF5::H5Sget_select_bounds($dataspaceID, $startAt, $endAt );
607
      
608
      if( $rc < 0 ){
609
      carp("Error getting number of dims in dataspace in ".__PACKAGE__.":get\n");
610
      carp("Can't close Datatype in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
611
      carp("Can't close DataSpace in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Sclose($dataspaceID) < 0);
612
      return undef;
613
      }
614
      
615
      @startAt = PDL::IO::HDF5::unpackList($startAt);
616
      @endAt   = PDL::IO::HDF5::unpackList($endAt);
617
      for(my $i=0;$i<=$#dims;++$i) {
618
      $dims[$i] = $endAt[$i]-$startAt[$i]+1;
619
      }
620
      if (not defined $start) {
621
      $start  = PDL->zeros($Ndims);
622
      $end    = PDL->zeros($Ndims);
623
      $start .= PDL->pdl(@startAt);
624
      $end   .= PDL->pdl(@endAt);
625
      } else {
626
      $start += PDL->pdl(@startAt);
627
      $end   += PDL->pdl(@startAt);
628
      }
629
  }
630
500
    if (not defined $start) {
631
    if (not defined $start) {
501
        # Initialize Dims structure:
632
        # Initialize Dims structure:
502
        my $dims = PDL::IO::HDF5::packList(@dims);
633
        my $dims = PDL::IO::HDF5::packList(@dims);
503
        my $dims2 = PDL::IO::HDF5::packList(@dims);
634
        my $dims2 = PDL::IO::HDF5::packList(@dims);
504
        
635
        
...
...
553
        }
684
        }
554
        my $mem_dims = PDL::IO::HDF5::packList(@dims);
685
        my $mem_dims = PDL::IO::HDF5::packList(@dims);
555
        my $stride2 = PDL::IO::HDF5::packList(reverse($stride->list));
686
        my $stride2 = PDL::IO::HDF5::packList(reverse($stride->list));
556
        my $block=PDL::Core::ones($Ndims);
687
        my $block=PDL::Core::ones($Ndims);
557
        my $block2 = PDL::IO::HDF5::packList(reverse($block->list));
688
        my $block2 = PDL::IO::HDF5::packList(reverse($block->list));
558
689
      
559
        # Slice the data
690
        # Slice the data
560
        $file_space = PDL::IO::HDF5::H5Dget_space($datasetID);
691
        $file_space = PDL::IO::HDF5::H5Dget_space($datasetID);
561
        $rc=PDL::IO::HDF5::H5Sselect_hyperslab($file_space, 0, 
692
        $rc=PDL::IO::HDF5::H5Sselect_hyperslab($file_space, 0, 
562
             $start2, $stride2, $length2, $block2);
693
                         $start2, $stride2, $length2, $block2);
563
694
      
564
  
695
      
565
        if( $rc < 0 ){
696
        if( $rc < 0 ){
566
        carp("Error slicing data from file in ".__PACKAGE__.":get\n");
697
        carp("Error slicing data from file in ".__PACKAGE__.":get\n");
567
        carp("Can't close Datatype in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
698
        carp("Can't close Datatype in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
568
        carp("Can't close DataSpace in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Sclose($dataspaceID) < 0);
699
        carp("Can't close DataSpace in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Sclose($dataspaceID) < 0);
569
        return undef;
700
        return undef;
570
        }
701
        }
571
        
702
        
572
        $mem_space = PDL::IO::HDF5::H5Screate_simple($Ndims, $mem_dims, 
703
        $mem_space = PDL::IO::HDF5::H5Screate_simple($Ndims, $mem_dims, 
573
                                $mem_dims);
704
                             $mem_dims);
574
705
      
575
    }
706
    }
576
707
577
        # Create initial PDL null array with the proper datatype    
708
        # Create initial PDL null array with the proper datatype    
578
    $pdl = $ReturnType->null;
709
    $pdl = $ReturnType->null;
579
    $pdl->set_datatype($PDLtype);
710
    $pdl->set_datatype($PDLtype);
...
...
582
    my $datatypeSize; # Size of one element of data stored
713
    my $datatypeSize; # Size of one element of data stored
583
    if( defined( $stringSize )){  # Fixed-Length String types
714
    if( defined( $stringSize )){  # Fixed-Length String types
584
        
715
        
585
        @pdldims = ($stringSize,reverse(@dims)); # HDF5 stores columns/rows in reverse order than pdl,
716
        @pdldims = ($stringSize,reverse(@dims)); # HDF5 stores columns/rows in reverse order than pdl,
586
        #  1st PDL dim is the string length (for PDL::Char)
717
        #  1st PDL dim is the string length (for PDL::Char)
587
      
718
588
        $datatypeSize = PDL::howbig($pdl->get_datatype);
719
        $datatypeSize = PDL::howbig($pdl->get_datatype);
589
    }
720
    }
590
    elsif( $varLenString ){ # Variable-length String
721
    elsif( $varLenString ){ # Variable-length String
591
          # (Variable length string arrays will be converted to fixed-length strings later)
722
          # (Variable length string arrays will be converted to fixed-length strings later)
592
        @pdldims = (reverse(@dims));        # HDF5 stores columns/rows in reverse order than pdl
723
        @pdldims = (reverse(@dims));        # HDF5 stores columns/rows in reverse order than pdl
...
...
596
        $datatypeSize = PDL::IO::HDF5::bufPtrSize();
727
        $datatypeSize = PDL::IO::HDF5::bufPtrSize();
597
    }
728
    }
598
    else{ # Normal Numeric types
729
    else{ # Normal Numeric types
599
          # (Variable length string arrays will be converted to fixed-length strings later)
730
          # (Variable length string arrays will be converted to fixed-length strings later)
600
        @pdldims = (reverse(@dims));        # HDF5 stores columns/rows in reverse order than pdl
731
        @pdldims = (reverse(@dims));        # HDF5 stores columns/rows in reverse order than pdl
601
      
732
602
        $datatypeSize = PDL::howbig($pdl->get_datatype);
733
        $datatypeSize = PDL::howbig($pdl->get_datatype);
603
    }
734
    }
735
  
736
  $pdl->setdims(\@pdldims);
604
    
737
    
605
    my $nelems = 1;
738
    my $nelems = 1;
606
    foreach (@pdldims){ $nelems *= $_; }; # calculate the number of elements
739
    foreach (@pdldims){ $nelems *= $_; }; # calculate the number of elements
607
    
740
    
608
    my $datasize = $nelems * $datatypeSize;
741
    my $datasize = $nelems * $datatypeSize;
...
...
1026
1159
1027
    my @attrValues; #return array
1160
    my @attrValues; #return array
1028
    
1161
    
1029
    my $typeID; # id used for attribute
1162
    my $typeID; # id used for attribute
1030
    my $dataspaceID; # id used for the attribute dataspace
1163
    my $dataspaceID; # id used for the attribute dataspace
1031
  
1164
1032
    my $attrID;
1165
    my $attrID;
1166
  my $stringSize;
1167
  my $Ndims;
1033
    foreach $attrName( @attrs){
1168
    foreach $attrName( @attrs){
1034
      
1169
      undef($stringSize);     
1035
        $attrValue = undef;
1170
        $attrValue = undef;
1036
      
1171
1037
        # Open the Attribute
1172
        # Open the Attribute
1038
        $attrID = PDL::IO::HDF5::H5Aopen_name($datasetID, $attrName );
1173
        $attrID = PDL::IO::HDF5::H5Aopen_name($datasetID, $attrName );
1039
        unless( $attrID >= 0){
1174
        unless( $attrID >= 0){
1040
            carp "Error Calling ".__PACKAGE__."::attrget: Can't open HDF5 Attribute name '$attrName'.\n";
1175
            carp "Error Calling ".__PACKAGE__."::attrget: Can't open HDF5 Attribute name '$attrName'.\n";
1041
            next;
1176
            next;
...
...
1057
            next;
1192
            next;
1058
        }
1193
        }
1059
1194
1060
1195
1061
        # Get the number of dims:
1196
        # Get the number of dims:
1062
        my $Ndims = PDL::IO::HDF5::H5Sget_simple_extent_ndims($dataspaceID);
1197
        $Ndims = PDL::IO::HDF5::H5Sget_simple_extent_ndims($dataspaceID);
1063
1198
1064
        unless( $Ndims >= 0){
1199
        unless( $Ndims >= 0){
1065
            if( $Ndims < 0 ){
1200
            if( $Ndims < 0 ){
1066
                carp("Warning: Can't Get Number of Dims in Attribute name '$attrName' Dataspace in ".__PACKAGE__.":get\n");
1201
                carp("Warning: Can't Get Number of Dims in Attribute name '$attrName' Dataspace in ".__PACKAGE__.":get\n");
1067
            }
1202
            }
...
...
1075
1210
1076
        my $HDF5type;
1211
        my $HDF5type;
1077
        
1212
        
1078
        if ($Ndims == 0) {
1213
        if ($Ndims == 0) {
1079
            # If it is a scalar we do this
1214
            # If it is a scalar we do this
1080
1081
        # Get the HDF5 dataset datatype;
1215
        # Get the HDF5 dataset datatype;
1082
            $HDF5type = PDL::IO::HDF5::H5Aget_type($attrID );
1216
            $HDF5type = PDL::IO::HDF5::H5Aget_type($attrID );
1083
1217
1084
        unless( $HDF5type >= 0 ){
1218
        unless( $HDF5type >= 0 ){
1085
            carp "Error Calling ".__PACKAGE__."::attrGet: Can't get HDF5 Dataset type in Attribute name '$attrName'.\n";
1219
            carp "Error Calling ".__PACKAGE__."::attrGet: Can't get HDF5 Dataset type in Attribute name '$attrName'.\n";
...
...
1097
            carp("Can't close Attribute in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Aclose($attrID) < 0);
1231
            carp("Can't close Attribute in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Aclose($attrID) < 0);
1098
            next;
1232
            next;
1099
        }
1233
        }
1100
        
1234
        
1101
        #init attr value to the length of the type
1235
        #init attr value to the length of the type
1102
        $attrValue = ' ' x ($size);
1236
        my $data = ' ' x ($size);
1237
          my $PDLtype;
1238
          my $ReturnType;
1239
          my $internalhdf5_type;
1240
      if( PDL::IO::HDF5::H5Tget_class($HDF5type ) == PDL::IO::HDF5::H5T_STRING() ){  # String type
1241
          $PDLtype = $PDL::Types::PDL_B; 
1242
          $internalhdf5_type =  $HDF5type; # internal storage the same as the file storage.
1243
          $ReturnType = 'PDL::Char';   # For strings, we return a PDL::Char
1244
          $stringSize = PDL::IO::HDF5::H5Tget_size($HDF5type);
1245
          unless( $stringSize >= 0 ){
1246
          carp "Error Calling ".__PACKAGE__."::attrGet: Can't get HDF5 String Datatype Size.\n";
1247
          carp("Can't close Datatype in ".__PACKAGE__.":get\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
1248
          return undef;
1249
          }
1103
        
1250
        }
1251
      else{  # Normal Numeric Type
1252
          # Map the HDF5 file datatype to a PDL datatype
1253
          $PDLtype = $PDL::Types::PDL_D; # Default type is double
1254
          $ReturnType = 'PDL';
1255
1256
          my $defaultType;
1257
          foreach $defaultType( keys %HDF5toPDLfileMapping){
1258
          if( PDL::IO::HDF5::H5Tequal($defaultType,$HDF5type) > 0){
1259
              $PDLtype = $HDF5toPDLfileMapping{$defaultType};
1260
              last;
1261
          }
1262
          }
1263
          
1264
          # Get the HDF5 internal datatype that corresponds to the PDL type
1265
          unless( defined($PDLtoHDF5internalTypeMapping{$PDLtype}) ){
1266
          carp "Error Calling ".__PACKAGE__."::attrGet: Can't map PDL type to HDF5 datatype\n";
1267
          return undef;
1268
          }
1269
          $internalhdf5_type = $PDLtoHDF5internalTypeMapping{$PDLtype};
1270
      }
1271
1104
        if( PDL::IO::HDF5::H5Aread($attrID, $HDF5type, $attrValue) < 0 ){
1272
        if( PDL::IO::HDF5::H5Aread($attrID, $internalhdf5_type, $data) < 0 ){
1105
            carp "Error Calling ".__PACKAGE__."::attrGet: Can't read Attribute Value for Attribute name '$attrName'.\n";
1273
            carp "Error Calling ".__PACKAGE__."::attrGet: Can't read Attribute Value for Attribute name '$attrName'.\n";
1106
            carp("Can't close Datatype in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
1274
            carp("Can't close Datatype in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Tclose($HDF5type) < 0);
1107
            carp("Can't close DataSpace in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Sclose($dataspaceID) < 0);
1275
            carp("Can't close DataSpace in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Sclose($dataspaceID) < 0);
1108
            carp("Can't close Attribute in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Aclose($attrID) < 0);
1276
            carp("Can't close Attribute in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Aclose($attrID) < 0);
1109
            next;
1277
            next;
1110
        }           
1278
        }           
1279
      $attrValue = $ReturnType->null;
1280
      $attrValue->set_datatype($PDLtype);
1281
          my @pdldims;
1282
          if( defined( $stringSize )){  # String types
1283
          @pdldims = ( $stringSize );
1284
          } else {        
1285
          @pdldims = ( 1 );
1286
          }
1287
          $attrValue->setdims(\@pdldims);
1288
      # Update the PDL data with the data read from the file
1289
      ${$attrValue->get_dataref()} = $data;
1290
      $attrValue->upd_data();
1291
      
1111
            # End of scalar option
1292
            # End of scalar option
1112
        } else {
1293
        } else {
1113
            # This is a PDL
1294
            # This is a PDL
1114
            # Get the HDF5 dataset datatype;
1295
            # Get the HDF5 dataset datatype;
1115
            $HDF5type = PDL::IO::HDF5::H5Aget_type($attrID );
1296
            $HDF5type = PDL::IO::HDF5::H5Aget_type($attrID );
...
...
1158
                                # Create variable-length type for reading from the file
1339
                                # Create variable-length type for reading from the file
1159
                                $internalhdf5_type = PDL::IO::HDF5::H5Tcopy(PDL::IO::HDF5::H5T_C_S1() );
1340
                                $internalhdf5_type = PDL::IO::HDF5::H5Tcopy(PDL::IO::HDF5::H5T_C_S1() );
1160
                                PDL::IO::HDF5::H5Tset_size( $internalhdf5_type, PDL::IO::HDF5::H5T_VARIABLE() );
1341
                                PDL::IO::HDF5::H5Tset_size( $internalhdf5_type, PDL::IO::HDF5::H5T_VARIABLE() );
1161
        
1342
        
1162
                        }
1343
                        }
1163
                        
1344
          
1164
            $PDLtype = $PDL::Types::PDL_B; 
1345
            $PDLtype = $PDL::Types::PDL_B; 
1346
          $internalhdf5_type =  $HDF5type; # internal storage the same as the file storage.
1165
            $typeID=$HDF5type;
1347
            $typeID=$HDF5type;
1166
            $ReturnType = 'PDL::Char';   # For strings, we return a PDL::Char
1348
            $ReturnType = 'PDL::Char';   # For strings, we return a PDL::Char
1167
            
1349
            
1168
            }
1350
            }
1169
            else{  # Normal Numeric Type
1351
            else{  # Normal Numeric Type
...
...
1210
            @dims = PDL::IO::HDF5::unpackList($dims); # get the dim sizes from the binary structure
1392
            @dims = PDL::IO::HDF5::unpackList($dims); # get the dim sizes from the binary structure
1211
            
1393
            
1212
            # Create initial PDL null array with the proper datatype    
1394
            # Create initial PDL null array with the proper datatype    
1213
            $attrValue = $ReturnType->null;
1395
            $attrValue = $ReturnType->null;
1214
            $attrValue->set_datatype($PDLtype);
1396
            $attrValue->set_datatype($PDLtype);
1215
          
1216
            my @pdldims;  # dims of the PDL
1397
            my @pdldims;  # dims of the PDL
1217
            my $datatypeSize; # Size of one element of data stored
1398
            my $datatypeSize; # Size of one element of data stored
1218
            if( defined( $stringSize )){ # Fixed-Length String types
1399
            if( defined( $stringSize )){  # Fixed-Length String types
1219
        
1400
        
1220
            @pdldims = ($stringSize,reverse(@dims)); # HDF5 stores columns/rows in reverse order than pdl,
1401
            @pdldims = ($stringSize,reverse(@dims)); # HDF5 stores columns/rows in reverse order than pdl,
1221
            #  1st PDL dim is the string length (for PDL::Char)
1402
            #  1st PDL dim is the string length (for PDL::Char)
1222
1403
1223
            $datatypeSize = PDL::howbig($attrValue->get_datatype);
1404
            $datatypeSize = PDL::howbig($attrValue->get_datatype);
...
...
1235
1416
1236
                        $datatypeSize = PDL::howbig($attrValue->get_datatype);
1417
                        $datatypeSize = PDL::howbig($attrValue->get_datatype);
1237
1418
1238
            }
1419
            }
1239
            
1420
            
1421
          $attrValue->setdims(\@pdldims);
1240
            
1422
            
1241
            my $nelems = 1;
1423
            my $nelems = 1;
1242
            foreach (@pdldims){ $nelems *= $_; }; # calculate the number of elements
1424
            foreach (@pdldims){ $nelems *= $_; }; # calculate the number of elements
1243
1425
1244
            my $datasize = $nelems * $datatypeSize;
1426
            my $datasize = $nelems * $datatypeSize;
...
...
1307
        carp("Can't close Attribute in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Aclose($attrID) < 0);
1489
        carp("Can't close Attribute in ".__PACKAGE__.":attrGet\n") if( PDL::IO::HDF5::H5Aclose($attrID) < 0);
1308
1490
1309
1491
1310
    }
1492
    }
1311
    continue{
1493
    continue{
1312
      
1494
      if ( $Ndims == 0 ) {
1495
                if (defined($stringSize)) {
1496
                    push @attrValues, $attrValue->atstr(0);
1497
                } else {
1498
                    push @attrValues, $attrValue->index(0);
1499
                }
1500
            } else {
1313
      push @attrValues, $attrValue;
1501
                push @attrValues, $attrValue;
1502
            }
1314
    }
1503
    }
1315
1504
1316
    return @attrValues;
1505
    return @attrValues;
1317
1506
1318
}
1507
}