# All files / node_modules/netcdfjs/src index.js

13.95% Statements 6/43
0% Branches 0/8
0% Functions 0/16
13.95% Lines 6/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176

    18x

    18x
    18x
    18x
    18x

    18x
     'use strict';

    const { IOBuffer } = require('iobuffer');

    const utils = require('./utils');
    const data = require('./data');
    const readHeader = require('./header');
    const toString = require('./toString');

    /**
     * Reads a NetCDF v3.x file
     * https://www.unidata.ucar.edu/software/netcdf/docs/file_format_specifications.html
     * @param {ArrayBuffer} data - ArrayBuffer or any Typed Array (including Node.js' Buffer from v4) with the data
     * @constructor
     */
    class NetCDFReader {
      constructor(data) {
        const buffer = new IOBuffer(data);
        buffer.setBigEndian();

        // Validate that it's a NetCDF file
        utils.notNetcdf(buffer.readChars(3) !== 'CDF', 'should start with CDF');

        // Check the NetCDF format
        const version = buffer.readByte();
        utils.notNetcdf(version > 2, 'unknown version');

        // Read the header
        this.header = readHeader(buffer, version);
        this.buffer = buffer;
      }

      /**
       * @return {string} - Version for the NetCDF format
       */
      get version() {
        if (this.header.version === 1) {
          return 'classic format';
        } else {
          return '64-bit offset format';
        }
      }

      /**
       * @return {object} - Metadata for the record dimension
       *  * `length`: Number of elements in the record dimension
       *  * `id`: Id number in the list of dimensions for the record dimension
       *  * `name`: String with the name of the record dimension
       *  * `recordStep`: Number with the record variables step size
       */
      get recordDimension() {
        return this.header.recordDimension;
      }

      /**
       * @return {Array<object>} - List of dimensions with:
       *  * `name`: String with the name of the dimension
       *  * `size`: Number with the size of the dimension
       */
      get dimensions() {
        return this.header.dimensions;
      }

      /**
       * @return {Array<object>} - List of global attributes with:
       *  * `name`: String with the name of the attribute
       *  * `type`: String with the type of the attribute
       *  * `value`: A number or string with the value of the attribute
       */
      get globalAttributes() {
        return this.header.globalAttributes;
      }

      /**
       * Returns the value of an attribute
       * @param {string} attributeName
       * @return {string} Value of the attributeName or null
       */
      getAttribute(attributeName) {
        const attribute = this.globalAttributes.find(
          (val) => val.name === attributeName
        );
    I    if (attribute) return attribute.value;
        return null;
      }

      /**
       * Returns the value of a variable as a string
       * @param {string} variableName
       * @return {string} Value of the variable as a string or null
       */
      getDataVariableAsString(variableName) {
        const variable = this.getDataVariable(variableName);
    I    if (variable) return variable.join('');
        return null;
      }

      /**
       * @return {Array<object>} - List of variables with:
       *  * `name`: String with the name of the variable
       *  * `dimensions`: Array with the dimension IDs of the variable
       *  * `attributes`: Array with the attributes of the variable
       *  * `type`: String with the type of the variable
       *  * `size`: Number with the size of the variable
       *  * `offset`: Number with the offset where of the variable begins
       *  * `record`: True if is a record variable, false otherwise
       */
      get variables() {
        return this.header.variables;
      }

      toString() {
        return toString.call(this);
      }

      /**
       * Retrieves the data for a given variable
       * @param {string|object} variableName - Name of the variable to search or variable object
       * @return {Array} - List with the variable values
       */
      getDataVariable(variableName) {
        let variable;
        if (typeof variableName === 'string') {
          // search the variable
          variable = this.header.variables.find(function (val) {
            return val.name === variableName;
          });
        } else {
          variable = variableName;
        }

        // throws if variable not found
        utils.notNetcdf(
          variable === undefined,
          `variable not found: ${variableName}`
        );

        // go to the offset position
        this.buffer.seek(variable.offset);

        if (variable.record) {
          // record variable case
          return data.record(this.buffer, variable, this.header.recordDimension);
        } else {
          // non-record variable case
          return data.nonRecord(this.buffer, variable);
        }
      }

      /**
       * Check if a dataVariable exists
       * @param {string} variableName - Name of the variable to find
       * @return {boolean}
       */
      dataVariableExists(variableName) {
        const variable = this.header.variables.find(function (val) {
          return val.name === variableName;
        });
        return variable !== undefined;
      }

      /**
       * Check if an attribute exists
       * @param {string} attributeName - Name of the attribute to find
       * @return {boolean}
       */
      attributeExists(attributeName) {
        const attribute = this.globalAttributes.find(
          (val) => val.name === attributeName
        );
        return attribute !== undefined;
      }
    }

    module.exports = NetCDFReader;