Cluster

function
Cluster(data, display, meta)

Option name Type Description
data Object

Data used to create the cluster. See example below

display Object

Display options passed to SVPath

meta Object

User-defined key:value pairs to add to the Cluster.

Clusters are made up of a group of Peaks. Typically a cluster for an NMR spectrum would correspond to a multiplet of peaks.

data = {
  peaks: [
    { center: 2.22, amplitude: 0.6, width: 0.005 },
    { center: 2.34, amplitude: 0.6, width: 0.005 }
  ]
}

// The data may also contain upper_bound and lower attributes.
// The bounds can shown on the Viewer when a cluster is selected,
// if the SVSelection.show_bounds is true.

data = {
  peaks: [...],
  lower_bound: 2.0,
  upper_bound: 2.4
}

Cluster inherits methods and properties from SVPath.

function Cluster(data, display, meta) {
  var self = this;
  data = data || { };
  display_defaults = { visible: false };
  display = JSV.merge(display_defaults, data.display, display);
  meta = JSV.merge(data.meta, meta);
  JSV.SVPath.call(this, display, meta);

  this._peaks = new JSV.SVSet();

  this._atoms = new JSV.SVSet();

  this.lower_bound = JSV.number(data.lower_bound);
  this.upper_bound = JSV.number(data.upper_bound);
  this.weight = JSV.number(data.weight);
  this.protons = JSV.number(data.protons);

  if (data.peaks) {
    data.peaks.forEach(function(peak_data) {
      self.add_peak(new JSV.Peak(peak_data))
    });
  }

}
JSV.inherits(Cluster, JSV.SVPath);

Cluster.prototype.toString = function() { return 'Cluster'; }

add_peak

method
Cluster.add_peak(peak)

Option name Type Description
peak Peak

Peak to add

Add a Peak to the cluster

Cluster.prototype.add_peak = function(peak) {
  this._peaks.push(peak);
  this.multiplet_type = undefined;
  peak._cluster = this;
}

update

method
Cluster.update()

Reorder all the peaks in the Cluster by their center property.

Cluster.prototype.update = function() {
  this._peaks.order_by('center');
}

peaks

method
Cluster.peaks(term)

Option name Type Description
term Integer,String,Array

See SVSet.get for details.

Returns an SVSet of peaks or a single Peak from the Cluster.

Cluster.prototype.peaks = function(term) {
  return this._peaks.get(term);
}

compound

method
Cluster.compound()

Returns the parent Compound.

Cluster.prototype.compound = function() {
  return this._compound;
}

spectrum

method
Cluster.spectrum()

Returns the parent Spectrum.

Cluster.prototype.spectrum = function() {
  return this.compound().spectrum();
}

center

method
Cluster.center()

Return the center of the cluster: an average of center value for all the peaks in the cluster.

Cluster.prototype.center = function() {
  var center;
  if (this.peaks().present()) {
    center = d3.mean(this.peaks(), function(p) { return p.center });
  }
  return center;
}

atoms

method
Cluster.atoms(term)

Option name Type Description
term Integer,String,Array

See SVSet.get for details.

Returns an SVSet of atoms or a single Atom from the Cluster.

Cluster.prototype.atoms = function(term) {
  return this._atoms.get(term);
}


// http://pubs.acs.org/paragonplus/submission/acs_nmr_guidelines.pdf
// http://www.chem.uci.edu/~jsnowick/groupweb/files/MultipletGuideV4.pdf
Cluster.prototype.determine_multiplet_type = function() {
  var self = this;
  var peaks = self.peaks();
  var type = 'm';
  if (peaks.length == 1) {
    type = 's';
  } else if (peaks.length == 2) {
    type = 'd';
  } else if (peaks.length == 3) {
    type = 't';
  } else if (peaks.length == 4) {
    if (double_of_doublets(peaks)) {
      type = 'dd';
    } else {
    type = 'q';
    }
  } else if (peaks.length == 5) {
    type = 'quint';
  } else if (peaks.length == 6) {
    if (triplet_of_doublets(peaks)) {
      type = 'td';
    } else {
    type = 'dt';
    }
  }
  return type
}

// All the peaks should be close to the same height
var double_of_doublets = function(peaks) {
  var within = 0.1; // amount all heights must be within of the max height
  var heights = peaks.map(function(p) { return p.amplitude });
  var max_height = d3.max(heights);
  var range_min = max_height * (1 - within);
  var range_max = max_height * (1 + within);
  return heights.every(function(h) { return  h >= range_min && h <= range_max })
}

// The middle 2 peaks should be higher than all the other peaks
var triplet_of_doublets = function(peaks) {
  var heights = peaks.map(function(p) { return p.amplitude });
  var middle_height = d3.min(heights.slice(2,3));
  var check_heights = heights.slice(0,1).concat(heights.slice(4,5));
  return check_heights.every(function(h) { return  h <= middle_height })
}

// Return the json required to create the multiplet nmrml
Cluster.prototype.nmrml_multiplet_json = function() {
  var json;
  switch (this.multiplet_type) {
    case 's':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000194', _name: 'singlet feature'};
      break;
    case 'd':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000184', _name: 'doublet feature'};
      break;
    case 't':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000185', _name: 'triplet feature'};
      break;
    case 'q':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000186', _name: 'quatruplet feature'};
      break;
    case 'dd':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000192', _name: 'doublet of doublets feature'};
      break;
    case 'quint':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000195', _name: 'quintet feature'};
      break;
    case 'dt':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000196', _name: 'doublet of triplets feature'};
      break;
    case 'td':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1000197', _name: 'triplet of doublets feature'};
      break;
    case 'm':
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1400305', _name: 'multiplet feature'};
      break;
    default:
      json = {_cvRef: 'NMRCV', _accession: 'NMR:1400305', _name: 'multiplet feature'};
  }
  return json
}
/////////////////////////////////////////////////////////////////////////////
// Cluster Properties (setters/getters)
/////////////////////////////////////////////////////////////////////////////
Object.defineProperties(Cluster.prototype, {
  'multiplet_type': {
    get: function() {
      if (!this._multiplet_type) {
        this._multiplet_type = this.determine_multiplet_type();
      }
      return this._multiplet_type
    },
    set: function(type) {
      this._multiplet_type = type;
    }
  },
  'atom_refs': {
    get: function() {
      if (this.atoms().length > 0) {
        return this.atoms().map(function(a) { return a.id });
      } else {
        return this._atom_refs || []
      }
    },
    set: function(refs) {
      this._atom_refs = refs;
    }
  }
});

JSV.Cluster = Cluster;

})(JSpectraViewer);