Giter Club home page Giter Club logo

nmrium's Introduction

NMRium

React component to display and process nuclear magnetic resonance (NMR) spectra.

Zakodium logo

Maintained by Zakodium

NPM version build status npm download DOI

Use it

Visit https://www.nmrium.org for examples of usage.

Use as a library in a React project

Install the package

npm install nmrium

OpenChemLib version

This module makes use of openchemlib/full.
If you use OpenChemLib somewhere else in your project, make sure to also import from openchemlib/full to avoid having multiple OCL versions in your bundle.

Use the component

import NMRium from 'nmrium';

function MyComponent() {
  return <NMRium />;
}

Development and testing

See General information for NMRium development.

There is an automatic build on each commit. You can test the latest build from main at:

https://dev.nmrium.org/

Want to play ? You can do some 1D NMR exercises ;)

https://www.nmrium.org/teaching#?toc=https://cheminfo.github.io/nmr-dataset2/toc.json

Also you can do some 2D NMR exercises ;)

https://www.nmrium.org/teaching#?toc=https://cheminfo.github.io/nmr-dataset1/data/2d.json

https://dev.nmrium.org?sampleURL=https%3A//cheminfo.github.io/nmr-dataset1/data/2d.json

You can do some 1D NMR tests/ exams ;)

https://dev.nmrium.org?sampleURL=https%3A//cheminfo.github.io/nmr-dataset2/exam.json

If you have jcamps accessible from an URL and that your server allow cross-origin you can directly open your file in the demo application:

https://dev.nmrium.org?sampleURL=https%3A//cheminfo.github.io/nmr-dataset2/100-86-7/1h.dx

Link loading the default samples test cases

https://dev.nmrium.org/?sampleURL=samples.json

You can debug Data and onDataChange callback ;)

https://dev.nmrium.org/#/test

Install and test locally

git clone https://github.com/cheminfo/nmrium.git
cd nmrium
npm i
npm start

Funding

Zakodium sàrl
Initiative zur Verbesserung der NMR-Datenqualität (IDNMR)
NFDI4Chem Chemistry Consortium in the NFDI
Universidad del Valle / Cali, Colombia
This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No 957189. The project is part of BATTERY 2030+, the large-scale European research initiative for inventing the sustainable batteries of the future.

License

MIT

nmrium's People

Contributors

cheminfo-bot avatar dependabot[bot] avatar djeanner avatar evaziegler avatar hamed-musallam avatar jliermann avatar jobo322 avatar josoriom avatar jwist avatar lpatiny avatar nes-cgn avatar sebastien-ahkrin avatar stropitek avatar targos avatar tpoisseau avatar wadjih-bencheikh18 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nmrium's Issues

Data1DManager and method names

I would like we rename the method and internal array so that we explicitely now what is the content:

  • dataObjects -> data1D
  • pushObject -> pushDatum1D

Create React components for annotations

First annotations could be a peak label

One way is to draw a vertical line that is just on top of the peak with the value next to it like:

image

Would be nice that this value can optionaly be edited

Scroll and vertical scale

Currently the vertical scroll seems limited and it looks like you continue to scroll but the spectrum does not scale. And after scrolling down look like you first need to reduce to a limit before the spectrum is scaled down.

Please remove the limitation. You may scroll up / down as much as you want.

consider the possibility of tilted Jres spectra (Hz/ppm)

I propose that you make it possible to display:

  1. tilted J-res spectra. These spectra will have a chemical shift scale in the horizontal direction and a scale in Hz in F1. (typically 50 Hz in F1). Compared to a 1D spectrum, the multiplets would be tilted vertically (F1 projection: pure shift spectrum). I can provide examples. These spectra would be obtained by tilting J-res spectra or re-organizing DIAG spectra.
  2. multiple quantum spectra. Usually Hz in F1. This would allow to work with 2D inadequate spectra. In general, the multiple quantum have scales in F1 are Hz, and vary with double the scale in F2.
    Conclusion, generally, it would be nice to have ppm or Hz in both dimensions as default unit for 2D spectra. It means that the Larmor frequencies should be specified in F1 and F2 to interconvert.
    In these two cases, what the projection would be may be different than for simple COSY; HSQC; HMBC.

Check the buttons

This button could for now be selected by default 👍

image

The functionalities of the 2 buttons are currently inverted

Use predefined colors for spectra

In order to generate distinct colors you may be interested in the library:

https://gka.github.io/chroma.js/

But it seems that based on the literature it is not so easy to select distinctable colors. The best apparently is to use an hardcoded list:

https://jsfiddle.net/jalbertbowdenii/7h1uw4yu/

Boynton's list of 11 colors that are almost never confused (9 without the black and white)

or

Kelly's 22 colors of maximum contrast (20 without the black and white).

I think you may reuse this last palette and make a module in case there are more than 20 spectra.

3 kind of buttons

In the toolbar we have at least 3 kind of buttons:

  • radio buttons: only on of them may be selected in the group and all of them can not be deselected at the same time. There should be a default at the beginning
  • push button: an immediate action is done, like full zoom out
  • checkbox button: it is on or off. An example that could be implemented is to show either real part of the spectrum or imaginary

Display FID

If it is a FID (see 13C FID example):

  • the axis value should be inverted (starts at 0 on the left side)
  • the unit should be changed: time [s]

Add new button for peak picking

Add a new button that allows to track the spectrum by place an annotation with the value of it. The goal is that there is a call back on mouse / click

Consider option/possibility to show only one or multiple parts of the spectrum

In some cases, the calling function may ask to display only certain regions of the spectrum. On case could be :
-show one section of the spectrum. For example to show the relevant coupling structure of a signal when rolling over the corresponding hydrogen on the structure) - this will be like zooming.
-Show multiple regions. For example 4.2-4.05 and 3.86-3.75 and 2.1-1.9 each with a small space beteeen the parts. This may be desirable when displaying a signal for which a parameter is optimized (say a coupling constants), but the same coupling influences also another region of the spectrum which should be shown as well. When working on one part of a coupling network of a compound, only one part of the spectrum is interesting - it would be nice to show only that part. It could be the part that is being optimizing a parameter by best fit of a simulated spectrum with the experimental one.

If you agree with this option, you probably want to implement it early in he programming process... the selection would be itotope specific and propagate to the 2D spectra opened simulateneously with the same isotope.

Do you want a picture to examplify 1D or 1D&2D ?

code is broken when useReducer

this what i get when useReducer and split the code insted of useState..

Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().
and all of things is broken.

@targos
can you give me what is the reason.

Speed and SVG in 1D

NMR spectra may have a lot of points (like 500k) and it is difficult to display them as a SVG.

Nevertheless it does not make sense to display all the points on a screen that can at best display 8000 points.

I will go by default to 2 or 3 points per pixels but in case of printing we will need to be able to generate a spectrum at a higher resolution

Here is an example of algorithm:
https://github.com/NPellet/jsGraph/blob/25186af1b97c8482ac7f377a51ddd12206d8efdd/src/util/waveform.js#L835-L948

We need to make a hypothesis about the monotonicity of the data. We will decide that the data object {x:[], y:[]} is monotonous and x is increasing ! Like that we will not have to make any check laster !!!

When trying to display data:

  • if data is null or undefined we can blank the screen
  • if data is an object, it has to contain 2 properties and both should be an array: x and y
  • we need to check if the x values are increasing otherwise we throw

interpolate spectrum to determine top of a picked peaks

When spectra have relatively low resolution (which the the standard in the processing of spectra (in particular 2d, but also 1D), it is a good idea to interpolate the spectrum near the point of selection to get the true top. When the user clicks near a top, the value picked could be interpolated (x and y coordinates).
Example: for a peak over this bit of spectrum : x: 1 2 3 4 5 6 y: 1 2 5 4 1.8 1
The "naive" top of the peak when selecting the point at x=4 would be (3,5), but it would be even better to interpolate to find it at (3.31,5.8).
In NMR the prefered interpolation is the trigonometric interpolation ifft/zero filling/fft, but this may take too a bit of time (except if already done before picking the peak). A more serious problem may be if the baseline is terrible, the interpolation may not work. (also over part of a spectrum it is tricky... because peaks should no be truncated... not sure how few it has to be taken to be safe) Another reasonable manner is to use other interpolator such as spline (need only a few points). The advantage is that it would be more robust (for other type of spectra if this is to be used for jcamp in general instead of only NMR). The ideal would be to use trigonometric interpolation, check that it makes sense by comparing with the spline and return just one...
Make sure you consider picking minima (either when the signals is negative) or when the spectroscopy for which peaks go down.

Improve code in getDomain

https://github.com/cheminfo/nmr-displayer/blob/1d1a5ebf0c0ba034f92aa6a22989f1a8106e1c8d/src/component/spectrum-chart.jsx#L72-L81

If you want to extract a property from an array of object please replace

let xArray = [];
let yArray = [];
for (let d of data) {
      xArray = xArray.concat(d['x']);
      yArray = yArray.concat(d['y']);
    }

by

let xArray = data.map( d => d.x);
let yArray = data.map( d => d.y);

It will be at least data.length faster

I guess also for 'x' the min / max will be data[0].x and data[data.length-1].x

Story books

We would need the following stories in storybook:

  • 1H NMR spectrum
  • 13C NMR spectrum
  • 1H NMR spectrum FID
  • 13C NMR spectrum FID
  • 13C coupled and 13C decoupled superimposition
  • 20 NMR spectra of metabo
  • 20 NMR fid of metabo
  • COSY with corresponding 1D spectrum
  • COSY + TOCSY + ROESY with corresponding 1D spectrum
  • HSQC + HMBC with corresponding 1D spectra

Vertical scales of 2D spectra: Consider DOSY spectra / series of 1D spectra.

In DOSY spectra, the F1 scale is not Hz or ppm, but a diffusion coordinate. In some cases, 2D spectra are series of 1D spectra. The unit in the F1 dimensions may be an experiment number, a temperature, a spacial coordinate in the tube (slice-selective experiment), or fuction of a delay (T1, T2 measurement). The scale should completely "user definable", (values and units). Default using ppm (and optionally) Hz, should be default, but should allow more flexibility.

How to combine multi Reducers using useRedusers

if i have multi reduers how can i combine it and pass it to useReduer??
it will be very helplful if you have a way to do it, so it will give me the ability to split the big reduer that i implemented all features in it.
@targos

Peak picking improvement

  • currently the peak picking is not working (not able to add more than one peak)
  • trying to delete a peak throw an error
  • when adding a new peak the label with the value should not be a the level of the mouse but it should really show what will be a label if it is clicked. This means that there is a small vertical line, the top peak detection and the same number of decimals that will be present at the end.
  • undo should cancel not only a value change but also the addition of a peak label (you should be able to cancel step by step all the peak addition)
  • undo of peak addition gives a strange result, the spectrum is duplicate

image

  • Change the icon for peak picking to a SVG looking similar to

label

2D format description and demo

Demo of the behaviour with conrec library:

2020-01-11 10 47 50

A link using old system to get an idea of the code

https://www.lactame.com/visualizer/src/index.html?config=../testcase/config/default.json&viewURL=../testcase/data/spectra2DWheel/view.json&dataURL=../testcase/data/spectra2DWheel/data.json

{
z: z, // a matrix
minX: Math.min(firstX, lastX),
maxX: Math.max(firstX, lastX),
minY: Math.min(firstY, lastY),
maxY: Math.max(firstY, lastY),
minZ: minZ,
maxZ: maxZ,
noise: getMedian(z[0].map(Math.abs))
};

manage aliased spectra

In some cases, the 2D spectra are aliased (the scale is in F1 is smaller in the 2D spectrum as in 1D or reference 2D spectrum. This can happen in protein NMR for all 1H-15N and 1H-13C HSQC or in 2D NMR. In this case the management of projections and display of chemical shift require some work (I can help with all the functions associtaed with this type of development). Often, aliased spectra are recorded as complement with non-aliased spectra.

Display spectrum with zoom

Use D3 library to create SVG for axis and spectrum

Many components:

  • Axis
  • Spectrum1D

Zoom

  • vertical zoom with scroll wheel or 2 fingers vertically
  • horizontal zoom click + drag (should show a rectangle + release)

Get inspired:
https://www.c6h6.org/
Click once on ethylbenzen and then on 1D NMR peak picking

Axis label

For NMR 1D we have for the horizontal axis 2 possibilities:

  • δ [ppm] (for a spectrum after fourrier transform) (please take care about unicode characters)
  • time [s] (for FID, the spectrum acquire by the instrument before fourrier transform)

Vertical axis will most of the time be hidden and the unit is 'Arbitrary unit'

Please plan props for the axis:

  • show: true / false
  • for xAxis : isFID : true / false and depending the value display the correct label

Integration improvement

  • integral should probably be attached to it's own vertical axis
  • the integral should start 10% of the height above the baseline
  • by default the first integral should take 20% of the height of the drawing area
  • possibility to delete the integral
  • allow undo / redo each time you add / remote an integral
  • the value of the integration should be drawn in the middle of the integral with 1 decimal. The integration is obtained using the XY.integration method
  • mouse wheel should allow to vertical scale the integral
  • it should be possible to resize the integral
  • Create a new icon for the integral in SVG based on the attached image

integral

add shortcut for menu items

What about introducing a shortcut for the selection of the zoom button ('z') and for zoom out ('f').
Also for peak-picking ...
as in other commercial NMR software!?

Undo / Redo

Based on Datum1D filters and the original data.

Simple backend using GraphQL

  • Drag / drop a jcamp -> saved on the HD
  • Save / load assignment
  • List existing spectra

npm start server : starts a local graphQL server that stores on the hardisk

  • /data/uuid : a folder containing sample
  • /data/uuid/index.json : sample information
  • /data/uuid/spectra/nmr/md5/ md5 of the jcamp file
  • /data/uuid/spectra/nmr/md5/index.json filename, peaks, integrals, ...
  • /data/uuid/spectra/nmr/md5/jcamp.jdx

Flip X axis

For 1H NMR the higher value is on the left and the smallest on the right.

You should invert the X axis

image

Current version is broken

When I clone the project, npm i and npm start I obtain the following message:

./src/component/chart-window.jsx Module not found: Can't resolve './css/chart-window.css'

Parameter for function call

What is the best way to implement basic function to process NMR spectra ?

export default function baseline(data = {x:[], re:[], im:[]}, options = {}) {
  let x = data.x.slice(0);
  let re = data.re.map( (re) => re * re);
  let im = data.im.map( (im) => im * im);
  return {x, re, im};
}

Change Datum1D constructor parameter

In order to prevent too many parameters in the constructor we should make some simplification and have only 3 parameters:

  • id
  • data {x, re, im}
  • options {display: {name, color, isVisible, isPeaksMarksVisible, ...}, meta: {isFid, nucleus}, ... }

Internally we could as well keep some object like displayOptions and metaInformation to reduce the size of the code.

The same change should be done as well in the Data1DManager.

Once this is done I will add the isFid and nucleus if the meta field (it is available in the jcamp).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.