Source: invokespectrum.js

/**
 * @function addSpectrum
 * @description
 * Starting point of drawing spectrum graph
 * @param {String} id - gets the svg id of the graph 
 * @param {Array} peakList - contains the list of data with mz and intensity used to draw lines on the graph 
 * @param {Array} envelopeList - contains the list of data with actual mass, mz and intensity used to draw circles on graph
 * @param {float} monoMZ - Value to which tha graph as to point on click of mz value used to zoom the grpah to that location
 * @param {Array} ionData - contains the list of data with mass and acid name
 * @param {object} graphFeatures - contains all the features needed for drawing the graphs
 */
addSpectrum = function(id,peakList,envelopeList,monoMZ, ionData, graphFeatures){
	let specParameters = compSpectrumParameters(peakList, envelopeList, monoMZ);
	specParameters.graphFeatures = graphFeatures;
	let peakData = {};
	peakData.peak_list = peakList ;
	if(envelopeList != null)
	{
		peakData.envelope_list = sortEnvelopes(envelopeList) ;
	}
	id = "#"+id;
	if(ionData == null)
	{
		specParameters.graphFeatures.showIons = false ;
	}
	else{
		ionData = groupBy(ionData,'ion');
	}
	specParameters.padding = graphFeatures.padding;
	specParameters.specWidth = graphFeatures.specWidth;
	specParameters.specHeight = graphFeatures.specHeight;
	specParameters.svgHeight = graphFeatures.svgHeight;
	specParameters.padding.head = graphFeatures.padding.head;
	let spectrumGraph = new SpectrumGraph(id,specParameters,peakData,ionData);
	return spectrumGraph;
}
 /**
  * Function to set spectrum perameters based on the data
  * @param {Array} peakList - contains the list of data with mz and intensity used to draw lines on the graph 
  * @param {Array} envelopeList - contains the list of data with actual mass, mz and intensity used to draw circles on graph
  * @param {float} monoMZ - Value to which tha graph as to point on click of mz value used to zoom the grpah to that location
  */
 function compSpectrumParameters(peakList, envelopeList, monoMZ){
	 console.log("peakList : ",peakList);
	let ratio = 1; 
	let specParameters = new SpectrumParameters();
	// Sort by mz
	peakList.sort(function(x,y){
		return x.mz - y.mz;
	});
	let listSize = peakList.length;
	let minMzData = peakList[0].mz;
	let maxMzData = peakList[listSize-1].mz;
	// Sort by intensity
	peakList.sort(function(x,y){
		return x.intensity - y.intensity;
	});

	let maxEnvelope = -1;
	let minEnvelope = 1000000000; // A random onstant high value
	if(envelopeList != null)
	{
		ratio = 1.000684;
		envelopeList.forEach(function(element){
			element.env_peaks.forEach(function(e){
				if (e.intensity > maxEnvelope){
					maxEnvelope = e.intensity;
				}
				else if (e.intensity < minEnvelope){
					minEnvelope = e.intensity;
				}
			})
		})
	}
	let maxIntensity = peakList[listSize-1].intensity;
	let minIntensity = peakList[0].intensity;
	let currminMz = minMzData ;
	let currmaxMz = maxMzData ;
	let currentMaxIntensity;
	if (maxIntensity > maxEnvelope) {
		currentMaxIntensity = maxIntensity;
	}
	else {
		currentMaxIntensity = maxEnvelope;
	}

	if(monoMZ != null)
	{
		//  Initializing with 1% of total intensity. If there exists no peaks in the 
		//  current range the intensity can't be 0 or nothing which will produce an 
		//  error in arithmatic calculations
		currentMaxIntensity = 0.01 * currentMaxIntensity ;
		monoMZ = monoMZ * ratio;
		currminMz = monoMZ - specParameters.onClickMassAdjacentRange ;
		currmaxMz = monoMZ + specParameters.onClickMassAdjacentRange ;
		for(let i = 0; i<listSize ; i++)
		{
			if(peakList[i].mz > currminMz && peakList[i].mz < currmaxMz)
			{
				if(peakList[i].intensity > currentMaxIntensity)
				{
					currentMaxIntensity = peakList[i].intensity;
				}
			}
		}
	}

	//  for specParameters, going to pass whichever value between peak max and envelope max that is bigger
	if (maxIntensity < maxEnvelope){
		maxIntensity = maxEnvelope;
	}
	if (minIntensity > minEnvelope){
		minIntensity = minEnvelope;
	}
	specParameters.initScale(currminMz,currmaxMz,maxIntensity,minIntensity,minMzData,maxMzData,currentMaxIntensity);

	// Code must be included to get top 200 intensities at any given time
	peakList.sort(function(x,y){
		return d3.descending(x.intensity, y.intensity);
	});
	return specParameters;
 }

/**
 * Sorting envelopes based on intensity to show top 200 envelops with high intensitites
 * @param {Array} envelopeList - contains the list of data with actual mass, mz and intensity used to draw circles on graph
 */
function sortEnvelopes(envelopeList)
{
	envelopeList.forEach(function(envelope){
		// ...env_peak converts arguments into list as sort function is not allowed on arguments
		envelope.env_peaks.forEach(function(...env_peak){
			env_peak.sort(function(x,y){
				return d3.descending(x.intensity, y.intensity);
			})
		})
	})
	envelopeList.sort(function(x,y){
	 	return d3.descending(x.env_peaks[0].intensity, y.env_peaks[0].intensity);
	})
	return envelopeList ;
}

/**
 * Function returns a map list with key and value
 * @param {list} listData - contains list of data
 * @param {string} keyValue - contains keyword based on which new group is created
 */
function groupBy(listData,keyValue){
	const map = new Map();
    listData.forEach((element)=>{
        const key = element[keyValue];
        const collection = map.get(key);
        if(!collection) map.set(key,[element]);
        else collection.push(element);
    });
    return map;
}