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.



654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
# File 'lib/io/netcdf.rb', line 654

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.



682
683
684
# File 'lib/io/netcdf.rb', line 682

def file_id
  @file_id
end

Class Method Details

.convert_attribute_value(value) ⇒ Object



736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
# File 'lib/io/netcdf.rb', line 736

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_INT8(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



820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
# File 'lib/io/netcdf.rb', line 820

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



804
805
806
# File 'lib/io/netcdf.rb', line 804

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

#[]=(name, value) ⇒ Object



808
809
810
# File 'lib/io/netcdf.rb', line 808

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

#check_definition(definition) ⇒ Object



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
730
731
732
733
734
# File 'lib/io/netcdf.rb', line 696

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 "NCFileWriter: 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 "NCFileWriter: 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



812
813
814
# File 'lib/io/netcdf.rb', line 812

def close
  nc_close(@file_id)
end

#define(definition, define_mode: true) ⇒ Object



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
786
787
788
789
790
791
792
793
794
795
796
797
798
# File 'lib/io/netcdf.rb', line 758

def define (definition, define_mode: true)
  definition = normalize_definition(definition)
  check_definition(definition)
  if definition.has_key?("dimensions") and definition["dimensions"].is_a?(Hash)
    definition["dimensions"].each do |name, len|
      dim = Dim.new(self, name, len.to_i, define_mode)
      @dims.push dim
      @name2dim[name] = dim
    end
  else
    warn "NCFileWriter: No dimensions in definition"
  end
  if definition.has_key?("variables") and definition["variables"].is_a?(Hash)
    definition["variables"].each do |name, info|
      var = Var.new(self, name, info, @compression, define_mode)
      @vars.push var
      @name2var[name] = var
    end
  else
    warn "NCFileWriter: No variables in definition"
  end
  if definition.has_key?("attributes") and definition["attributes"].is_a?(Hash)
    @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



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

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

#normalize_definition(definition) ⇒ Object

key of Hash in definition should be String



685
686
687
688
689
690
691
692
693
694
# File 'lib/io/netcdf.rb', line 685

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