Class: NCFileWriter

Inherits:
Object
  • Object
show all
Includes:
NC
Defined in:
lib/io/netcdf.rb,
lib/io/netcdf.rb

Defined Under Namespace

Classes: Dim, Var

Constant Summary collapse

TYPEMAP =
{
  "char" => NC_CHAR,
  "byte" => NC_BYTE,
  "short" => NC_SHORT,
  "int" => NC_INT,
  "float" => NC_FLOAT,
  "double" => NC_DOUBLE,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NC

nc_decode, nc_put_att_simple, nc_put_var_all

Constructor Details

#initialize(file, mode = 0, template: nil, compression: 0) ⇒ NCFileWriter

Returns a new instance of NCFileWriter.



649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
# File 'lib/io/netcdf.rb', line 649

def initialize (file, mode = 0, template: nil, compression: 0)
  @dims     = []
  @name2dim = {}
  @vars     = []
  @name2var = {}
  @compression = compression
  @attributes = nil      
  if template.nil?
    if compression > 0
      @file_id  = nc_create(file, mode|NC_NETCDF4)
    else
      @file_id  = nc_create(file, mode)
    end
  else
    IO.popen("ncgen -o #{file}", "w") { |io|
      io.write(template)
    }
    if compression > 0
      @file_id  = nc_open(file, mode|NC_WRITE|NC_SHARE|NC_NETCDF4)
    else
      @file_id  = nc_open(file, mode|NC_WRITE|NC_SHARE)
    end
    NCFile.open(file) {|nc|
      define nc.definition, define_mode: false
    }
  end
end

Instance Attribute Details

#file_idObject (readonly)

Returns the value of attribute file_id.



677
678
679
# File 'lib/io/netcdf.rb', line 677

def file_id
  @file_id
end

Class Method Details

.convert_attribute_value(value) ⇒ Object



731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
# File 'lib/io/netcdf.rb', line 731

def self.convert_attribute_value (value)
  case value
  when Hash
    type, value = *value.first
    case type
    when "char"
      value = CA_UINT8(value)
    when "byte"
      value = CA_BYTE(value)
    when "short"
      value = CA_SHORT(value)
    when "int"
      value = CA_INT(value)
    when "float"
      value = CA_FLOAT(value)
    when "double"
      value = CA_DOUBLE(value)
    end
  end
  return value
end

.scaled_integer(type, value) ⇒ Object



807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
# File 'lib/io/netcdf.rb', line 807

def self.scaled_integer (type, value)
  min, max = value.min, value.max
  case type
  when :short
    short_max = (0x7fff-1).to_f
    fillvalue = CA_SHORT(0x7fff+1)[0]
    scale_factor = (max - min)/short_max
    add_offset = min + short_max*scale_factor
    packed = ((value - add_offset)/scale_factor).short
  when :int
    int_max = (0x7fffffff-1).to_f
    fillvalue = CA_INT(0x7fffffff+1)[0]
    scale_factor = (max - min)/int_max
    add_offset = min + int_max*scale_factor
    packed = ((value - add_offset)/scale_factor).int
  else
    raise
  end
  packed.attribute["scale_factor"] = scale_factor
  packed.attribute["add_offset"] = add_offset
  if value.has_mask?
    packed[:is_masked] = fillvalue
    packed.attribute["_FillValue"] = fillvalue
  end
  return packed
end

Instance Method Details

#[](name) ⇒ Object



791
792
793
# File 'lib/io/netcdf.rb', line 791

def [] (name)
  return @name2var[name]
end

#[]=(name, value) ⇒ Object



795
796
797
# File 'lib/io/netcdf.rb', line 795

def []= (name, value)
  return @name2var[name].put(value)
end

#check_definition(definition) ⇒ Object



691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
# File 'lib/io/netcdf.rb', line 691

def check_definition (definition)
  if definition.has_key?("dimensions")
    dim_keys = definition["dimensions"].keys
  else
    raise "NetCDF definition shoud have 'dimensions' entry"
  end
  if definition.has_key?("variables")
    definition["variables"].each do |name, var_def|
      unless var_def.has_key?("type")
        warn "NetCDF Variable '#{name}' does not have 'type' entry in definition"
      else
        unless ["char","byte","short","int","float","double"].include?(var_def["type"])
          raise "invalid type of NetCDF Variable '#{name}'"
        end          
      end 
      unless var_def.has_key?("dim") 
        warn "NetCDF Variable '#{name}' does not have 'dim' entry in definition"
      else
        unless var_def["dim"].is_a?(Array)
          raise "'dim' of NetCDF Variable '#{name}' should be an Array"
        else
          var_def["dim"].each do |dim|
            unless dim_keys.include?(dim)
              raise "invalid dimension '#{dim}' for NetCDF Variable '#{name}'"
            end
          end
        end
      end 
      var_def.each do |k, v|
        case v
        when Hash
          if v.size > 1 or not ["byte","short","int","float","double"].include?(v.keys[0])
            raise "invalid specification in attribute '#{k}' for NetCDF Variable '#{name}'"
          end
        end
      end
    end
  end
end

#closeObject



799
800
801
# File 'lib/io/netcdf.rb', line 799

def close
  nc_close(@file_id)
end

#define(definition, define_mode: true) ⇒ Object



753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
# File 'lib/io/netcdf.rb', line 753

def define (definition, define_mode: true)
  definition = normalize_definition(definition)
  check_definition(definition)
  definition["dimensions"].each do |name, len|
    dim = Dim.new(self, name, len.to_i, define_mode)
    @dims.push dim
    @name2dim[name] = dim
  end
  definition["variables"].each do |name, info|
    var = Var.new(self, name, info, @compression, define_mode)
    @vars.push var
    @name2var[name] = var
  end
  if definition.has_key?("attributes")
    @attributes = definition["attributes"]
    if define_mode
      @attributes.each do |name, value|
        value = NCFileWriter.convert_attribute_value(value)
        begin
          nc_put_att(@file_id, NC_GLOBAL, name, value)
        rescue => e
          raise(e.class, e.error_message + " {#{name}: #{value}}")
        end
      end
    end
    @attributes.freeze
  else
    @attributes = {}.freeze
  end
  if define_mode
    nc_enddef(@file_id)
  end
end

#dim(name) ⇒ Object



787
788
789
# File 'lib/io/netcdf.rb', line 787

def dim (name)
  return @name2dim[name]
end

#normalize_definition(definition) ⇒ Object

key of Hash in definition should be String



680
681
682
683
684
685
686
687
688
689
# File 'lib/io/netcdf.rb', line 680

def normalize_definition (definition)
  out = {}
  definition.each do |key, value|
    if value.is_a?(Hash)
      value = normalize_definition(value)
    end
    out[key.to_s] = value
  end
  return out
end