NT-MDT data: JavaScript parsing library

A native file format of NT-MDT scientific software. Usually contains any of:

Some examples of mdt files can be downloaded at:

Application

["Nova", "Image Analysis", "NanoEducator", "Gwyddion", "Callisto"]

File extension

mdt

KS implementation details

License: GPL-3.0-or-later

This page hosts a formal specification of NT-MDT data using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All parsing code for JavaScript generated by Kaitai Struct depends on the JavaScript runtime library. You have to install it before you can parse data.

The JavaScript runtime library is available at npm:

npm install kaitai-struct

Code

See the usage examples in the JavaScript notes.

Parse structure from an ArrayBuffer:

var arrayBuffer = ...;
var data = new NtMdt(new KaitaiStream(arrayBuffer));

After that, one can get various attributes from the structure by accessing fields or properties like:

data.size // => File size (w/o header)

JavaScript source code to parse NT-MDT data

NtMdt.js

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['exports', 'kaitai-struct/KaitaiStream'], factory);
  } else if (typeof exports === 'object' && exports !== null && typeof exports.nodeType !== 'number') {
    factory(exports, require('kaitai-struct/KaitaiStream'));
  } else {
    factory(root.NtMdt || (root.NtMdt = {}), root.KaitaiStream);
  }
})(typeof self !== 'undefined' ? self : this, function (NtMdt_, KaitaiStream) {
/**
 * A native file format of NT-MDT scientific software. Usually contains
 * any of:
 * 
 * * [Scanning probe](https://en.wikipedia.org/wiki/Scanning_probe_microscopy) microscopy scans and spectra
 * * [Raman spectra](https://en.wikipedia.org/wiki/Raman_spectroscopy)
 * * results of their analysis
 * 
 * Some examples of mdt files can be downloaded at:
 * 
 * * <https://www.ntmdt-si.ru/resources/scan-gallery>
 * * <http://callistosoft.narod.ru/Resources/Mdt.zip>
 * @see {@link https://svn.code.sf.net/p/gwyddion/code/trunk/gwyddion/modules/file/nt-mdt.c|Source}
 */

var NtMdt = (function() {
  NtMdt.AdcMode = Object.freeze({
    HEIGHT: 0,
    DFL: 1,
    LATERAL_F: 2,
    BIAS_V: 3,
    CURRENT: 4,
    FB_OUT: 5,
    MAG: 6,
    MAG_SIN: 7,
    MAG_COS: 8,
    RMS: 9,
    CALC_MAG: 10,
    PHASE1: 11,
    PHASE2: 12,
    CALC_PHASE: 13,
    EX1: 14,
    EX2: 15,
    HV_X: 16,
    HV_Y: 17,
    SNAP_BACK: 18,
    FALSE: 255,

    0: "HEIGHT",
    1: "DFL",
    2: "LATERAL_F",
    3: "BIAS_V",
    4: "CURRENT",
    5: "FB_OUT",
    6: "MAG",
    7: "MAG_SIN",
    8: "MAG_COS",
    9: "RMS",
    10: "CALC_MAG",
    11: "PHASE1",
    12: "PHASE2",
    13: "CALC_PHASE",
    14: "EX1",
    15: "EX2",
    16: "HV_X",
    17: "HV_Y",
    18: "SNAP_BACK",
    255: "FALSE",
  });

  NtMdt.Consts = Object.freeze({
    FRAME_MODE_SIZE: 8,
    FRAME_HEADER_SIZE: 22,
    AXIS_SCALES_SIZE: 30,
    FILE_HEADER_SIZE: 32,
    SPECTRO_VARS_MIN_SIZE: 38,
    SCAN_VARS_MIN_SIZE: 77,

    8: "FRAME_MODE_SIZE",
    22: "FRAME_HEADER_SIZE",
    30: "AXIS_SCALES_SIZE",
    32: "FILE_HEADER_SIZE",
    38: "SPECTRO_VARS_MIN_SIZE",
    77: "SCAN_VARS_MIN_SIZE",
  });

  NtMdt.DataType = Object.freeze({
    FLOATFIX: -65544,
    FLOAT80: -16138,
    FLOAT64: -13320,
    FLOAT48: -9990,
    FLOAT32: -5892,
    INT64: -8,
    INT32: -4,
    INT16: -2,
    INT8: -1,
    UNKNOWN0: 0,
    UINT8: 1,
    UINT16: 2,
    UINT32: 4,
    UINT64: 8,

    "-65544": "FLOATFIX",
    "-16138": "FLOAT80",
    "-13320": "FLOAT64",
    "-9990": "FLOAT48",
    "-5892": "FLOAT32",
    "-8": "INT64",
    "-4": "INT32",
    "-2": "INT16",
    "-1": "INT8",
    0: "UNKNOWN0",
    1: "UINT8",
    2: "UINT16",
    4: "UINT32",
    8: "UINT64",
  });

  NtMdt.SpmMode = Object.freeze({
    CONSTANT_FORCE: 0,
    CONTACT_CONSTANT_HEIGHT: 1,
    CONTACT_ERROR: 2,
    LATERAL_FORCE: 3,
    FORCE_MODULATION: 4,
    SPREADING_RESISTANCE_IMAGING: 5,
    SEMICONTACT_TOPOGRAPHY: 6,
    SEMICONTACT_ERROR: 7,
    PHASE_CONTRAST: 8,
    AC_MAGNETIC_FORCE: 9,
    DC_MAGNETIC_FORCE: 10,
    ELECTROSTATIC_FORCE: 11,
    CAPACITANCE_CONTRAST: 12,
    KELVIN_PROBE: 13,
    CONSTANT_CURRENT: 14,
    BARRIER_HEIGHT: 15,
    CONSTANT_HEIGHT: 16,
    AFAM: 17,
    CONTACT_EFM: 18,
    SHEAR_FORCE_TOPOGRAPHY: 19,
    SFOM: 20,
    CONTACT_CAPACITANCE: 21,
    SNOM_TRANSMISSION: 22,
    SNOM_REFLECTION: 23,
    SNOM_ALL: 24,
    SNOM: 25,

    0: "CONSTANT_FORCE",
    1: "CONTACT_CONSTANT_HEIGHT",
    2: "CONTACT_ERROR",
    3: "LATERAL_FORCE",
    4: "FORCE_MODULATION",
    5: "SPREADING_RESISTANCE_IMAGING",
    6: "SEMICONTACT_TOPOGRAPHY",
    7: "SEMICONTACT_ERROR",
    8: "PHASE_CONTRAST",
    9: "AC_MAGNETIC_FORCE",
    10: "DC_MAGNETIC_FORCE",
    11: "ELECTROSTATIC_FORCE",
    12: "CAPACITANCE_CONTRAST",
    13: "KELVIN_PROBE",
    14: "CONSTANT_CURRENT",
    15: "BARRIER_HEIGHT",
    16: "CONSTANT_HEIGHT",
    17: "AFAM",
    18: "CONTACT_EFM",
    19: "SHEAR_FORCE_TOPOGRAPHY",
    20: "SFOM",
    21: "CONTACT_CAPACITANCE",
    22: "SNOM_TRANSMISSION",
    23: "SNOM_REFLECTION",
    24: "SNOM_ALL",
    25: "SNOM",
  });

  NtMdt.SpmTechnique = Object.freeze({
    CONTACT_MODE: 0,
    SEMICONTACT_MODE: 1,
    TUNNEL_CURRENT: 2,
    SNOM: 3,

    0: "CONTACT_MODE",
    1: "SEMICONTACT_MODE",
    2: "TUNNEL_CURRENT",
    3: "SNOM",
  });

  NtMdt.Unit = Object.freeze({
    RAMAN_SHIFT: -10,
    RESERVED0: -9,
    RESERVED1: -8,
    RESERVED2: -7,
    RESERVED3: -6,
    METER: -5,
    CENTI_METER: -4,
    MILLI_METER: -3,
    MICRO_METER: -2,
    NANO_METER: -1,
    ANGSTROM: 0,
    NANO_AMPERE: 1,
    VOLT: 2,
    NONE: 3,
    KILO_HERTZ: 4,
    DEGREES: 5,
    PERCENT: 6,
    CELSIUS_DEGREE: 7,
    VOLT_HIGH: 8,
    SECOND: 9,
    MILLI_SECOND: 10,
    MICRO_SECOND: 11,
    NANO_SECOND: 12,
    COUNTS: 13,
    PIXELS: 14,
    RESERVED_SFOM0: 15,
    RESERVED_SFOM1: 16,
    RESERVED_SFOM2: 17,
    RESERVED_SFOM3: 18,
    RESERVED_SFOM4: 19,
    AMPERE2: 20,
    MILLI_AMPERE: 21,
    MICRO_AMPERE: 22,
    NANO_AMPERE2: 23,
    PICO_AMPERE: 24,
    VOLT2: 25,
    MILLI_VOLT: 26,
    MICRO_VOLT: 27,
    NANO_VOLT: 28,
    PICO_VOLT: 29,
    NEWTON: 30,
    MILLI_NEWTON: 31,
    MICRO_NEWTON: 32,
    NANO_NEWTON: 33,
    PICO_NEWTON: 34,
    RESERVED_DOS0: 35,
    RESERVED_DOS1: 36,
    RESERVED_DOS2: 37,
    RESERVED_DOS3: 38,
    RESERVED_DOS4: 39,

    "-10": "RAMAN_SHIFT",
    "-9": "RESERVED0",
    "-8": "RESERVED1",
    "-7": "RESERVED2",
    "-6": "RESERVED3",
    "-5": "METER",
    "-4": "CENTI_METER",
    "-3": "MILLI_METER",
    "-2": "MICRO_METER",
    "-1": "NANO_METER",
    0: "ANGSTROM",
    1: "NANO_AMPERE",
    2: "VOLT",
    3: "NONE",
    4: "KILO_HERTZ",
    5: "DEGREES",
    6: "PERCENT",
    7: "CELSIUS_DEGREE",
    8: "VOLT_HIGH",
    9: "SECOND",
    10: "MILLI_SECOND",
    11: "MICRO_SECOND",
    12: "NANO_SECOND",
    13: "COUNTS",
    14: "PIXELS",
    15: "RESERVED_SFOM0",
    16: "RESERVED_SFOM1",
    17: "RESERVED_SFOM2",
    18: "RESERVED_SFOM3",
    19: "RESERVED_SFOM4",
    20: "AMPERE2",
    21: "MILLI_AMPERE",
    22: "MICRO_AMPERE",
    23: "NANO_AMPERE2",
    24: "PICO_AMPERE",
    25: "VOLT2",
    26: "MILLI_VOLT",
    27: "MICRO_VOLT",
    28: "NANO_VOLT",
    29: "PICO_VOLT",
    30: "NEWTON",
    31: "MILLI_NEWTON",
    32: "MICRO_NEWTON",
    33: "NANO_NEWTON",
    34: "PICO_NEWTON",
    35: "RESERVED_DOS0",
    36: "RESERVED_DOS1",
    37: "RESERVED_DOS2",
    38: "RESERVED_DOS3",
    39: "RESERVED_DOS4",
  });

  NtMdt.XmlParamType = Object.freeze({
    NONE: 0,
    LASER_WAVELENGTH: 1,
    UNITS: 2,
    DATA_ARRAY: 255,

    0: "NONE",
    1: "LASER_WAVELENGTH",
    2: "UNITS",
    255: "DATA_ARRAY",
  });

  NtMdt.XmlScanLocation = Object.freeze({
    HLT: 0,
    HLB: 1,
    HRT: 2,
    HRB: 3,
    VLT: 4,
    VLB: 5,
    VRT: 6,
    VRB: 7,

    0: "HLT",
    1: "HLB",
    2: "HRT",
    3: "HRB",
    4: "VLT",
    5: "VLB",
    6: "VRT",
    7: "VRB",
  });

  function NtMdt(_io, _parent, _root) {
    this._io = _io;
    this._parent = _parent;
    this._root = _root || this;

    this._read();
  }
  NtMdt.prototype._read = function() {
    this.signature = this._io.readBytes(4);
    if (!((KaitaiStream.byteArrayCompare(this.signature, new Uint8Array([1, 176, 147, 255])) == 0))) {
      throw new KaitaiStream.ValidationNotEqualError(new Uint8Array([1, 176, 147, 255]), this.signature, this._io, "/seq/0");
    }
    this.size = this._io.readU4le();
    this.reserved0 = this._io.readBytes(4);
    this.lastFrame = this._io.readU2le();
    this.reserved1 = this._io.readBytes(18);
    this.wrondDoc = this._io.readBytes(1);
    this._raw_frames = this._io.readBytes(this.size);
    var _io__raw_frames = new KaitaiStream(this._raw_frames);
    this.frames = new Framez(_io__raw_frames, this, this._root);
  }

  var Frame = NtMdt.Frame = (function() {
    Frame.FrameType = Object.freeze({
      SCANNED: 0,
      SPECTROSCOPY: 1,
      TEXT: 3,
      OLD_MDA: 105,
      MDA: 106,
      PALETTE: 107,
      CURVES_NEW: 190,
      CURVES: 201,

      0: "SCANNED",
      1: "SPECTROSCOPY",
      3: "TEXT",
      105: "OLD_MDA",
      106: "MDA",
      107: "PALETTE",
      190: "CURVES_NEW",
      201: "CURVES",
    });

    function Frame(_io, _parent, _root) {
      this._io = _io;
      this._parent = _parent;
      this._root = _root;

      this._read();
    }
    Frame.prototype._read = function() {
      this.size = this._io.readU4le();
      this._raw_main = this._io.readBytes(this.size - 4);
      var _io__raw_main = new KaitaiStream(this._raw_main);
      this.main = new FrameMain(_io__raw_main, this, this._root);
    }

    var AxisScale = Frame.AxisScale = (function() {
      function AxisScale(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      AxisScale.prototype._read = function() {
        this.offset = this._io.readF4le();
        this.step = this._io.readF4le();
        this.unit = this._io.readS2le();
      }

      /**
       * x_scale->offset = gwy_get_gfloat_le(&p);# r0 (physical units)
       */

      /**
       * x_scale->step = gwy_get_gfloat_le(&p); r (physical units) x_scale->step = fabs(x_scale->step); if (!x_scale->step) {
       *   g_warning("x_scale.step == 0, changing to 1");
       *   x_scale->step = 1.0;
       * }
       */

      /**
       * U
       */

      return AxisScale;
    })();

    var DateTime = Frame.DateTime = (function() {
      function DateTime(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      DateTime.prototype._read = function() {
        this.date = new Date(this._io, this, this._root);
        this.time = new Time(this._io, this, this._root);
      }

      var Date = DateTime.Date = (function() {
        function Date(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Date.prototype._read = function() {
          this.year = this._io.readU2le();
          this.month = this._io.readU2le();
          this.day = this._io.readU2le();
        }

        /**
         * h_yea
         */

        /**
         * h_mon
         */

        /**
         * h_day
         */

        return Date;
      })();

      var Time = DateTime.Time = (function() {
        function Time(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Time.prototype._read = function() {
          this.hour = this._io.readU2le();
          this.min = this._io.readU2le();
          this.sec = this._io.readU2le();
        }

        /**
         * h_h
         */

        /**
         * h_m
         */

        /**
         * h_s
         */

        return Time;
      })();

      return DateTime;
    })();

    var Dots = Frame.Dots = (function() {
      function Dots(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      Dots.prototype._read = function() {
        this.fmNdots = this._io.readU2le();
        if (this.fmNdots > 0) {
          this.coordHeader = new DotsHeader(this._io, this, this._root);
        }
        this.coordinates = [];
        for (var i = 0; i < this.fmNdots; i++) {
          this.coordinates.push(new DotsData(this._io, this, this._root));
        }
        this.data = [];
        for (var i = 0; i < this.fmNdots; i++) {
          this.data.push(new DataLinez(this._io, this, this._root, i));
        }
      }

      var DataLinez = Dots.DataLinez = (function() {
        function DataLinez(_io, _parent, _root, index) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;
          this.index = index;

          this._read();
        }
        DataLinez.prototype._read = function() {
          this.forward = [];
          for (var i = 0; i < this._parent.coordinates[this.index].forwardSize; i++) {
            this.forward.push(this._io.readS2le());
          }
          this.backward = [];
          for (var i = 0; i < this._parent.coordinates[this.index].backwardSize; i++) {
            this.backward.push(this._io.readS2le());
          }
        }

        return DataLinez;
      })();

      var DotsData = Dots.DotsData = (function() {
        function DotsData(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        DotsData.prototype._read = function() {
          this.coordX = this._io.readF4le();
          this.coordY = this._io.readF4le();
          this.forwardSize = this._io.readS4le();
          this.backwardSize = this._io.readS4le();
        }

        return DotsData;
      })();

      var DotsHeader = Dots.DotsHeader = (function() {
        function DotsHeader(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        DotsHeader.prototype._read = function() {
          this.headerSize = this._io.readS4le();
          this._raw_header = this._io.readBytes(this.headerSize);
          var _io__raw_header = new KaitaiStream(this._raw_header);
          this.header = new Header(_io__raw_header, this, this._root);
        }

        var Header = DotsHeader.Header = (function() {
          function Header(_io, _parent, _root) {
            this._io = _io;
            this._parent = _parent;
            this._root = _root;

            this._read();
          }
          Header.prototype._read = function() {
            this.coordSize = this._io.readS4le();
            this.version = this._io.readS4le();
            this.xyunits = this._io.readS2le();
          }

          return Header;
        })();

        return DotsHeader;
      })();

      return Dots;
    })();

    var FdCurvesNew = Frame.FdCurvesNew = (function() {
      function FdCurvesNew(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      FdCurvesNew.prototype._read = function() {
        this.blockCount = this._io.readU4le();
        this.blocksHeaders = [];
        for (var i = 0; i < this.blockCount; i++) {
          this.blocksHeaders.push(new BlockDescr(this._io, this, this._root));
        }
        this.blocksNames = [];
        for (var i = 0; i < this.blockCount; i++) {
          this.blocksNames.push(KaitaiStream.bytesToStr(this._io.readBytes(this.blocksHeaders[i].nameLen), "UTF-8"));
        }
        this.blocksData = [];
        for (var i = 0; i < this.blockCount; i++) {
          this.blocksData.push(this._io.readBytes(this.blocksHeaders[i].len));
        }
      }

      var BlockDescr = FdCurvesNew.BlockDescr = (function() {
        function BlockDescr(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        BlockDescr.prototype._read = function() {
          this.nameLen = this._io.readU4le();
          this.len = this._io.readU4le();
        }

        return BlockDescr;
      })();

      return FdCurvesNew;
    })();

    var FdMetaData = Frame.FdMetaData = (function() {
      function FdMetaData(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      FdMetaData.prototype._read = function() {
        this.headSize = this._io.readU4le();
        this.totLen = this._io.readU4le();
        this.guids = [];
        for (var i = 0; i < 2; i++) {
          this.guids.push(new Uuid(this._io, this, this._root));
        }
        this.frameStatus = this._io.readBytes(4);
        this.nameSize = this._io.readU4le();
        this.commSize = this._io.readU4le();
        this.viewInfoSize = this._io.readU4le();
        this.specSize = this._io.readU4le();
        this.sourceInfoSize = this._io.readU4le();
        this.varSize = this._io.readU4le();
        this.dataOffset = this._io.readU4le();
        this.dataSize = this._io.readU4le();
        this.title = KaitaiStream.bytesToStr(this._io.readBytes(this.nameSize), "UTF-8");
        this.xml = KaitaiStream.bytesToStr(this._io.readBytes(this.commSize), "UTF-8");
        this.structLen = this._io.readU4le();
        this.arraySize = this._io.readU8le();
        this.cellSize = this._io.readU4le();
        this.nDimensions = this._io.readU4le();
        this.nMesurands = this._io.readU4le();
        this.dimensions = [];
        for (var i = 0; i < this.nDimensions; i++) {
          this.dimensions.push(new Calibration(this._io, this, this._root));
        }
        this.mesurands = [];
        for (var i = 0; i < this.nMesurands; i++) {
          this.mesurands.push(new Calibration(this._io, this, this._root));
        }
      }

      var Calibration = FdMetaData.Calibration = (function() {
        function Calibration(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Calibration.prototype._read = function() {
          this.lenTot = this._io.readU4le();
          this.lenStruct = this._io.readU4le();
          this.lenName = this._io.readU4le();
          this.lenComment = this._io.readU4le();
          this.lenUnit = this._io.readU4le();
          this.siUnit = this._io.readU8le();
          this.accuracy = this._io.readF8le();
          this.functionIdAndDimensions = this._io.readU8le();
          this.bias = this._io.readF8le();
          this.scale = this._io.readF8le();
          this.minIndex = this._io.readU8le();
          this.maxIndex = this._io.readU8le();
          this.dataType = this._io.readS4le();
          this.lenAuthor = this._io.readU4le();
          this.name = KaitaiStream.bytesToStr(this._io.readBytes(this.lenName), "UTF-8");
          this.comment = KaitaiStream.bytesToStr(this._io.readBytes(this.lenComment), "UTF-8");
          this.unit = KaitaiStream.bytesToStr(this._io.readBytes(this.lenUnit), "UTF-8");
          this.author = KaitaiStream.bytesToStr(this._io.readBytes(this.lenAuthor), "UTF-8");
        }
        Object.defineProperty(Calibration.prototype, 'count', {
          get: function() {
            if (this._m_count !== undefined)
              return this._m_count;
            this._m_count = (this.maxIndex - this.minIndex) + 1;
            return this._m_count;
          }
        });

        return Calibration;
      })();

      var Image = FdMetaData.Image = (function() {
        function Image(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Image.prototype._read = function() {
          this.image = [];
          var i = 0;
          while (!this._io.isEof()) {
            this.image.push(new Vec(this._io, this, this._root));
            i++;
          }
        }

        var Vec = Image.Vec = (function() {
          function Vec(_io, _parent, _root) {
            this._io = _io;
            this._parent = _parent;
            this._root = _root;

            this._read();
          }
          Vec.prototype._read = function() {
            this.items = [];
            for (var i = 0; i < this._parent._parent.nMesurands; i++) {
              switch (this._parent._parent.mesurands[i].dataType) {
              case NtMdt.DataType.FLOAT32:
                this.items.push(this._io.readF4le());
                break;
              case NtMdt.DataType.FLOAT64:
                this.items.push(this._io.readF8le());
                break;
              case NtMdt.DataType.INT16:
                this.items.push(this._io.readS2le());
                break;
              case NtMdt.DataType.INT32:
                this.items.push(this._io.readS4le());
                break;
              case NtMdt.DataType.INT64:
                this.items.push(this._io.readS8le());
                break;
              case NtMdt.DataType.INT8:
                this.items.push(this._io.readS1());
                break;
              case NtMdt.DataType.UINT16:
                this.items.push(this._io.readU2le());
                break;
              case NtMdt.DataType.UINT32:
                this.items.push(this._io.readU4le());
                break;
              case NtMdt.DataType.UINT64:
                this.items.push(this._io.readU8le());
                break;
              case NtMdt.DataType.UINT8:
                this.items.push(this._io.readU1());
                break;
              }
            }
          }

          return Vec;
        })();

        return Image;
      })();
      Object.defineProperty(FdMetaData.prototype, 'image', {
        get: function() {
          if (this._m_image !== undefined)
            return this._m_image;
          var _pos = this._io.pos;
          this._io.seek(this.dataOffset);
          this._raw__m_image = this._io.readBytes(this.dataSize);
          var _io__raw__m_image = new KaitaiStream(this._raw__m_image);
          this._m_image = new Image(_io__raw__m_image, this, this._root);
          this._io.seek(_pos);
          return this._m_image;
        }
      });

      return FdMetaData;
    })();

    var FdScanned = Frame.FdScanned = (function() {
      FdScanned.InputSignal = Object.freeze({
        EXTENSION_SLOT: 0,
        BIAS_V: 1,
        GROUND: 2,

        0: "EXTENSION_SLOT",
        1: "BIAS_V",
        2: "GROUND",
      });

      FdScanned.LiftMode = Object.freeze({
        STEP: 0,
        FINE: 1,
        SLOPE: 2,

        0: "STEP",
        1: "FINE",
        2: "SLOPE",
      });

      FdScanned.Mode = Object.freeze({
        STM: 0,
        AFM: 1,
        UNKNOWN2: 2,
        UNKNOWN3: 3,
        UNKNOWN4: 4,

        0: "STM",
        1: "AFM",
        2: "UNKNOWN2",
        3: "UNKNOWN3",
        4: "UNKNOWN4",
      });

      function FdScanned(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      FdScanned.prototype._read = function() {
        this._raw_vars = this._io.readBytes(this._parent.varSize);
        var _io__raw_vars = new KaitaiStream(this._raw_vars);
        this.vars = new Vars(_io__raw_vars, this, this._root);
        if (false) {
          this.origFormat = this._io.readU4le();
        }
        if (false) {
          this.tune = this._io.readU4le();
        }
        if (false) {
          this.feedbackGain = this._io.readF8le();
        }
        if (false) {
          this.dacScale = this._io.readS4le();
        }
        if (false) {
          this.overscan = this._io.readS4le();
        }
        this.fmMode = this._io.readU2le();
        this.fmXres = this._io.readU2le();
        this.fmYres = this._io.readU2le();
        this.dots = new Dots(this._io, this, this._root);
        this.image = [];
        for (var i = 0; i < this.fmXres * this.fmYres; i++) {
          this.image.push(this._io.readS2le());
        }
        this.title = new Title(this._io, this, this._root);
        this.xml = new Xml(this._io, this, this._root);
      }

      var Dot = FdScanned.Dot = (function() {
        function Dot(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Dot.prototype._read = function() {
          this.x = this._io.readS2le();
          this.y = this._io.readS2le();
        }

        return Dot;
      })();

      var ScanDir = FdScanned.ScanDir = (function() {
        function ScanDir(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        ScanDir.prototype._read = function() {
          this.unkn = this._io.readBitsIntBe(4);
          this.doublePass = this._io.readBitsIntBe(1) != 0;
          this.bottom = this._io.readBitsIntBe(1) != 0;
          this.left = this._io.readBitsIntBe(1) != 0;
          this.horizontal = this._io.readBitsIntBe(1) != 0;
        }

        /**
         * Bottom - 1 Top - 0
         */

        /**
         * Left - 1 Right - 0
         */

        /**
         * Horizontal - 1 Vertical - 0
         */

        return ScanDir;
      })();

      var Vars = FdScanned.Vars = (function() {
        function Vars(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Vars.prototype._read = function() {
          this.xScale = new AxisScale(this._io, this, this._root);
          this.yScale = new AxisScale(this._io, this, this._root);
          this.zScale = new AxisScale(this._io, this, this._root);
          this.channelIndex = this._io.readU1();
          this.mode = this._io.readU1();
          this.xres = this._io.readU2le();
          this.yres = this._io.readU2le();
          this.ndacq = this._io.readU2le();
          this.stepLength = this._io.readF4le();
          this.adt = this._io.readU2le();
          this.adcGainAmpLog10 = this._io.readU1();
          this.adcIndex = this._io.readU1();
          this.inputSignalOrVersion = this._io.readU1();
          this.substrPlaneOrderOrPassNum = this._io.readU1();
          this.scanDir = new ScanDir(this._io, this, this._root);
          this.powerOf2 = this._io.readU1();
          this.velocity = this._io.readF4le();
          this.setpoint = this._io.readF4le();
          this.biasVoltage = this._io.readF4le();
          this.draw = this._io.readU1();
          this.reserved = this._io.readU1();
          this.xoff = this._io.readS4le();
          this.yoff = this._io.readS4le();
          this.nlCorr = this._io.readU1();
        }

        /**
         * s_mode
         */

        /**
         * s_dev
         */

        /**
         * s_nx
         */

        /**
         * s_ny
         */

        /**
         * Step (DAC)
         */

        /**
         * s_rs in Angstrom's (Angstrom*gwy_get_gfloat_le(&p))
         */

        /**
         * s_adt
         */

        /**
         * s_adc_a
         */

        /**
         * ADC index
         */

        /**
         * MDTInputSignal smp_in; s_smp_in (for signal) s_8xx (for version)
         */

        /**
         * s_spl or z_03
         */

        /**
         * s_xy TODO: interpretation
         */

        /**
         * s_2n (bool)
         */

        /**
         * s_vel (Angstrom/second)
         */

        /**
         * s_i0
         */

        /**
         * s_ut
         */

        /**
         * s_draw (bool)
         */

        /**
         * s_x00 (in DAC quants)
         */

        /**
         * s_y00 (in DAC quants)
         */

        /**
         * s_cor (bool)
         */

        return Vars;
      })();

      /**
       * s_oem
       */

      /**
       * z_tune
       */

      /**
       * s_fbg
       */

      /**
       * s_s
       */

      /**
       * s_xov (in %)
       */

      /**
       * m_mode
       */

      /**
       * m_nx
       */

      /**
       * m_ny
       */

      return FdScanned;
    })();

    var FdSpectroscopy = Frame.FdSpectroscopy = (function() {
      function FdSpectroscopy(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      FdSpectroscopy.prototype._read = function() {
        this._raw_vars = this._io.readBytes(this._parent.varSize);
        var _io__raw_vars = new KaitaiStream(this._raw_vars);
        this.vars = new Vars(_io__raw_vars, this, this._root);
        this.fmMode = this._io.readU2le();
        this.fmXres = this._io.readU2le();
        this.fmYres = this._io.readU2le();
        this.dots = new Dots(this._io, this, this._root);
        this.data = [];
        for (var i = 0; i < this.fmXres * this.fmYres; i++) {
          this.data.push(this._io.readS2le());
        }
        this.title = new Title(this._io, this, this._root);
        this.xml = new Xml(this._io, this, this._root);
      }

      var Vars = FdSpectroscopy.Vars = (function() {
        function Vars(_io, _parent, _root) {
          this._io = _io;
          this._parent = _parent;
          this._root = _root;

          this._read();
        }
        Vars.prototype._read = function() {
          this.xScale = new AxisScale(this._io, this, this._root);
          this.yScale = new AxisScale(this._io, this, this._root);
          this.zScale = new AxisScale(this._io, this, this._root);
          this.spMode = this._io.readU2le();
          this.spFilter = this._io.readU2le();
          this.uBegin = this._io.readF4le();
          this.uEnd = this._io.readF4le();
          this.zUp = this._io.readS2le();
          this.zDown = this._io.readS2le();
          this.spAveraging = this._io.readU2le();
          this.spRepeat = this._io.readU1();
          this.spBack = this._io.readU1();
          this.sp4nx = this._io.readS2le();
          this.spOsc = this._io.readU1();
          this.spN4 = this._io.readU1();
          this.sp4x0 = this._io.readF4le();
          this.sp4xr = this._io.readF4le();
          this.sp4u = this._io.readS2le();
          this.sp4i = this._io.readS2le();
          this.spNx = this._io.readS2le();
        }

        return Vars;
      })();

      return FdSpectroscopy;
    })();

    var FrameMain = Frame.FrameMain = (function() {
      function FrameMain(_io, _parent, _root) {
        this._io = _io;
        this._parent = _parent;
        this._root = _root;

        this._read();
      }
      FrameMain.prototype._read = function() {
        this.type = this._io.readU2le();
        this.version = new Version(this._io, this, this._root);
        this.dateTime = new DateTime(this._io, this, this._root);
        this.varSize = this._io.readU2le();
        switch (this.type) {
        case NtMdt.Frame.FrameType.CURVES:
          this._raw_frameData = this._io.readBytesFull();
          var _io__raw_frameData = new KaitaiStream(this._raw_frameData);
          this.frameData = new FdSpectroscopy(_io__raw_frameData, this, this._root);
          break;
        case NtMdt.Frame.FrameType.CURVES_NEW:
          this._raw_frameData = this._io.readBytesFull();
          var _io__raw_frameData = new KaitaiStream(this._raw_frameData);
          this.frameData = new FdCurvesNew(_io__raw_frameData, this, this._root);
          break;
        case NtMdt.Frame.FrameType.MDA:
          this._raw_frameData = this._io.readBytesFull();
          var _io__raw_frameData = new KaitaiStream(this._raw_frameData);
          this.frameData = new FdMetaData(_io__raw_frameData, this, this._root);
          break;
        case NtMdt.Frame.FrameType.SCANNED:
          this._raw_frameData = this._io.readBytesFull();
          var _io__raw_frameData = new KaitaiStream(this._raw_frameData);
          this.frameData = new FdScanned(_io__raw_frameData, this, this._root);
          break;
        case NtMdt.Frame.FrameType.SPECTROSCOPY:
          this._raw_frameData = this._io.readBytesFull();
          var _io__raw_frameData = new KaitaiStream(this._raw_frameData);
          this.frameData = new FdSpectroscopy(_io__raw_frameData, this, this._root);
          break;
        default:
          this.frameData = this._io.readBytesFull();
          break;
        }
      }

      /**
       * h_what
       */

      /**
       * h_am, v6 and older only
       */

      /**
       * 
       */

      return FrameMain;
    })();

    /**
     * h_sz
     */

    return Frame;
  })();

  var Framez = NtMdt.Framez = (function() {
    function Framez(_io, _parent, _root) {
      this._io = _io;
      this._parent = _parent;
      this._root = _root;

      this._read();
    }
    Framez.prototype._read = function() {
      this.frames = [];
      for (var i = 0; i < this._root.lastFrame + 1; i++) {
        this.frames.push(new Frame(this._io, this, this._root));
      }
    }

    return Framez;
  })();

  var Title = NtMdt.Title = (function() {
    function Title(_io, _parent, _root) {
      this._io = _io;
      this._parent = _parent;
      this._root = _root;

      this._read();
    }
    Title.prototype._read = function() {
      this.titleLen = this._io.readU4le();
      this.title = KaitaiStream.bytesToStr(this._io.readBytes(this.titleLen), "windows-1251");
    }

    return Title;
  })();

  var Uuid = NtMdt.Uuid = (function() {
    function Uuid(_io, _parent, _root) {
      this._io = _io;
      this._parent = _parent;
      this._root = _root;

      this._read();
    }
    Uuid.prototype._read = function() {
      this.data = [];
      for (var i = 0; i < 16; i++) {
        this.data.push(this._io.readU1());
      }
    }

    return Uuid;
  })();

  var Version = NtMdt.Version = (function() {
    function Version(_io, _parent, _root) {
      this._io = _io;
      this._parent = _parent;
      this._root = _root;

      this._read();
    }
    Version.prototype._read = function() {
      this.minor = this._io.readU1();
      this.major = this._io.readU1();
    }

    return Version;
  })();

  var Xml = NtMdt.Xml = (function() {
    function Xml(_io, _parent, _root) {
      this._io = _io;
      this._parent = _parent;
      this._root = _root;

      this._read();
    }
    Xml.prototype._read = function() {
      this.xmlLen = this._io.readU4le();
      this.xml = KaitaiStream.bytesToStr(this._io.readBytes(this.xmlLen), "UTF-16LE");
    }

    return Xml;
  })();

  /**
   * File size (w/o header)
   */

  /**
   * documentation specifies 32 bytes long header, but zeroth frame starts at 33th byte in reality
   */

  return NtMdt;
})();
NtMdt_.NtMdt = NtMdt;
});