Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
gy4443
chemotion_eln_server
Commits
84bc6514
Commit
84bc6514
authored
Oct 05, 2015
by
Marco Sehrer
Browse files
Merge pull request #130 from ninjaconcept/130-reaction-sample-calculations
Sample & Reaction Calculations
parents
dcac3c7c
756aacb6
Changes
11
Hide whitespace changes
Inline
Side-by-side
app/assets/javascripts/components/Material.js
View file @
84bc6514
...
...
@@ -45,17 +45,37 @@ class Material extends Component {
<
/td
>
<
td
>
{
material
.
name
}
<
/td
>
<
td
>
{
material
.
molecule
.
sum_formular
}
<
/td
>
<
td
className
=
"
padding-right
"
>
<
td
>
<
NumeralInputWithUnits
key
=
{
material
.
id
}
value
=
{
material
.
amount_mg
}
unit
=
'
mg
'
numeralFormat
=
'
0,0.0000
'
onChange
=
{(
amount
)
=>
this
.
handleAmountChange
(
amount
)}
/
>
<
/td
>
<
td
>
<
NumeralInputWithUnits
key
=
{
material
.
id
}
value
=
{
material
.
amount_value
}
unit
=
{
material
.
amount_unit
||
'
mg
'
}
units
=
{[
'
mg
'
,
'
ml
'
,
'
mmol
'
]}
numeralFormat
=
'
0,0.00
'
convertValueFromUnitToNextUnit
=
{(
unit
,
nextUnit
,
value
)
=>
this
.
handleUnitChange
(
unit
,
nextUnit
,
value
)}
value
=
{
material
.
amount_ml
}
unit
=
'
ml
'
numeralFormat
=
'
0,0.0000
'
onChange
=
{(
amount
)
=>
this
.
handleAmountChange
(
amount
)}
/
>
<
/td
>
<
td
>
<
NumeralInputWithUnits
key
=
{
material
.
id
}
value
=
{
material
.
amount_mmol
}
unit
=
'
mmol
'
numeralFormat
=
'
0,0.0000
'
onChange
=
{(
amount
)
=>
this
.
handleAmountChange
(
amount
)}
/
>
<
/td
>
<
td
className
=
"
padding-right
"
>
<
Input
type
=
"
text
"
...
...
app/assets/javascripts/components/MaterialGroup.js
View file @
84bc6514
...
...
@@ -11,9 +11,11 @@ export default class MaterialGroup extends Component {
<
th
width
=
"
5%
"
><
/th
>
<
th
width
=
"
5%
"
>
Ref
<
/th
>
<
th
width
=
"
20%
"
>
Name
<
/th
>
<
th
width
=
"
20%
"
>
Molecule
<
/th
>
<
th
width
=
"
25%
"
>
Amount
<
/th
>
<
th
width
=
"
20%
"
>
Equi
<
/th
>
<
th
width
=
"
15%
"
>
Molecule
<
/th
>
<
th
width
=
"
15%
"
>
mg
<
/th
>
<
th
width
=
"
15%
"
>
ml
<
/th
>
<
th
width
=
"
15%
"
>
mmol
<
/th
>
<
th
width
=
"
10%
"
>
Equi
<
/th
>
<
th
width
=
"
5%
"
><
/th
>
<
/thead
>
<
tbody
>
...
...
app/assets/javascripts/components/NumeralInputWithUnits.js
View file @
84bc6514
...
...
@@ -82,5 +82,5 @@ export default class NumeralInputWithUnits extends Component {
NumeralInputWithUnits
.
defaultProps
=
{
value
:
0
,
numeralFormat
:
''
,
units
:
[
''
]
units
:
[]
};
app/assets/javascripts/components/ReactionDetails.js
View file @
84bc6514
...
...
@@ -73,28 +73,28 @@ export default class ReactionDetails extends React.Component {
updatedReactionForAmountChange
(
changeEvent
)
{
let
{
sampleID
,
amount
}
=
changeEvent
;
let
s
ample
=
this
.
findSampleById
(
sampleID
);
let
updatedS
ample
=
this
.
findSampleById
(
sampleID
);
sample
.
amount_value
=
amount
.
value
;
s
ample
.
a
mount
_unit
=
amount
.
unit
;
// normalize to milligram
updatedS
ample
.
setA
mount
AndNormalizeToMilligram
(
amount
.
value
,
amount
.
unit
)
;
return
this
.
updatedReactionWithSample
(
this
.
updatedSamplesForAmountChange
.
bind
(
this
),
s
ample
)
return
this
.
updatedReactionWithSample
(
this
.
updatedSamplesForAmountChange
.
bind
(
this
),
updatedS
ample
)
}
updatedReactionForEquivalentChange
(
changeEvent
)
{
let
{
sampleID
,
equivalent
}
=
changeEvent
;
let
s
ample
=
this
.
findSampleById
(
sampleID
);
let
updatedS
ample
=
this
.
findSampleById
(
sampleID
);
s
ample
.
equivalent
=
equivalent
;
updatedS
ample
.
equivalent
=
equivalent
;
return
this
.
updatedReactionWithSample
(
this
.
updatedSamplesForEquivalentChange
.
bind
(
this
),
s
ample
)
return
this
.
updatedReactionWithSample
(
this
.
updatedSamplesForEquivalentChange
.
bind
(
this
),
updatedS
ample
)
}
updatedReactionWithSample
(
updateFunction
,
s
ample
)
{
updatedReactionWithSample
(
updateFunction
,
updatedS
ample
)
{
let
{
reaction
}
=
this
.
state
;
reaction
.
starting_materials
=
updateFunction
(
reaction
.
starting_materials
,
s
ample
);
reaction
.
reactants
=
updateFunction
(
reaction
.
reactants
,
s
ample
);
reaction
.
products
=
updateFunction
(
reaction
.
products
,
s
ample
);
reaction
.
starting_materials
=
updateFunction
(
reaction
.
starting_materials
,
updatedS
ample
);
reaction
.
reactants
=
updateFunction
(
reaction
.
reactants
,
updatedS
ample
);
reaction
.
products
=
updateFunction
(
reaction
.
products
,
updatedS
ample
);
return
reaction
;
}
...
...
@@ -111,21 +111,23 @@ export default class ReactionDetails extends React.Component {
return
samples
.
map
((
sample
)
=>
{
if
(
sample
.
id
==
updatedSample
.
id
)
{
sample
.
amount_value
=
updatedSample
.
amount_value
;
sample
.
amount_unit
=
updatedSample
.
amount_unit
;
if
(
referenceSample
)
{
if
(
!
updatedSample
.
reference
&&
referenceSample
.
amount_value
)
{
sample
.
equivalent
=
sample
.
amount_value
/
referenceSample
.
amount_value
;
sample
.
setAmountAndNormalizeToMilligram
(
updatedSample
.
amount_value
,
updatedSample
.
amount_unit
);
if
(
referenceSample
)
{
if
(
!
updatedSample
.
reference
&&
referenceSample
.
amount_value
)
{
sample
.
equivalent
=
sample
.
amount_mmol
/
referenceSample
.
amount_mmol
;
}
else
{
sample
.
equivalent
=
1.0
;
}
}
}
else
{
if
(
updatedSample
.
reference
)
{
if
(
sample
.
equivalent
)
{
sample
.
amount_value
=
sample
.
equivalent
*
updatedSample
.
amount_value
;
if
(
updatedSample
.
reference
)
{
if
(
sample
.
equivalent
)
{
sample
.
setAmountAndNormalizeToMilligram
(
sample
.
equivalent
*
updatedSample
.
amount_mmol
,
'
mmol
'
);
}
}
}
...
...
@@ -139,11 +141,11 @@ export default class ReactionDetails extends React.Component {
return
samples
.
map
((
sample
)
=>
{
if
(
sample
.
id
==
updatedSample
.
id
)
{
sample
.
equivalent
=
updatedSample
.
equivalent
;
if
(
referenceSample
&&
referenceSample
.
amount_value
)
{
sample
.
a
mount
_value
=
updatedSample
.
equivalent
*
referenceSample
.
amount_
value
;
if
(
referenceSample
&&
referenceSample
.
amount_value
)
{
sample
.
setA
mount
AndNormalizeToMilligram
(
updatedSample
.
equivalent
*
referenceSample
.
amount_
mmol
,
'
mmol
'
)
;
}
else
if
(
sample
.
amount_value
)
{
sample
.
a
mount
_value
=
updatedSample
.
equivalent
*
sample
.
amount_
value
;
else
if
(
sample
.
amount_value
)
{
sample
.
setA
mount
AndNormalizeToMilligram
(
updatedSample
.
equivalent
*
sample
.
amount_
mmol
,
'
mmol
'
)
;
}
}
return
sample
;
...
...
@@ -157,10 +159,10 @@ export default class ReactionDetails extends React.Component {
sample
.
reference
=
true
;
}
else
{
if
(
sample
.
amount_value
)
{
let
referenceAmount
=
referenceSample
.
amount_
value
;
if
(
referenceSample
&&
referenceAmount
)
{
sample
.
equivalent
=
sample
.
amount_
value
/
referenceAmount
;
if
(
sample
.
amount_value
)
{
let
referenceAmount
=
referenceSample
.
amount_
mmol
;
if
(
referenceSample
&&
referenceAmount
)
{
sample
.
equivalent
=
sample
.
amount_
mmol
/
referenceAmount
;
}
}
sample
.
reference
=
false
;
...
...
@@ -245,11 +247,12 @@ export default class ReactionDetails extends React.Component {
const
svgPath
=
(
reaction
.
reactionSvg
)
?
"
/images/reactions/
"
+
reaction
.
reactionSvg
:
""
;
const
svgContainerStyle
=
{
position
:
'
relative
'
,
height
:
0
,
width
:
'
100%
'
,
//
height: 0,
//
width: '100%',
padding
:
0
,
paddingBottom
:
'
5
0%
'
paddingBottom
:
'
3
0%
'
};
return
(
<
div
>
<
Panel
header
=
"
Reaction Details
"
bsStyle
=
'
primary
'
>
...
...
@@ -261,7 +264,7 @@ export default class ReactionDetails extends React.Component {
<
/td
>
<
td
width
=
"
70%
"
>
<
div
style
=
{
svgContainerStyle
}
>
<
SVG
key
=
{
reaction
.
reactionSvg
}
src
=
{
svgPath
}
/
>
<
SVG
key
=
{
reaction
.
reactionSvg
}
src
=
{
svgPath
}
className
=
"
molecule-small
"
/>
<
/div
>
<
/td
>
<
/tr
>
...
...
app/assets/javascripts/components/SampleDetails.js
View file @
84bc6514
...
...
@@ -99,8 +99,8 @@ export default class SampleDetails extends React.Component {
handleAmountChanged
(
amount
)
{
let
sample
=
this
.
state
.
sample
;
sample
.
a
mount
_unit
=
amount
.
unit
;
sample
.
amount_value
=
amount
.
value
;
sample
.
setA
mount
AndNormalizeToMilligram
(
amount
.
value
,
amount
.
unit
)
;
this
.
setState
({
sample
:
sample
});
...
...
@@ -534,16 +534,38 @@ export default class SampleDetails extends React.Component {
sampleAmount
(
sample
)
{
if
(
sample
.
is_scoped
==
false
||
sample
.
amount_value
||
sample
.
id
==
'
_new_
'
)
{
return
(
<
NumeralInputWithUnits
key
=
{
sample
.
id
}
value
=
{
sample
.
amount_value
}
unit
=
{
sample
.
amount_unit
||
'
mg
'
}
label
=
"
Amount
"
units
=
{[
'
mg
'
,
'
ml
'
,
'
mmol
'
]}
numeralFormat
=
'
0,0.00
'
convertValueFromUnitToNextUnit
=
{(
unit
,
nextUnit
,
value
)
=>
this
.
handleUnitChanged
(
unit
,
nextUnit
,
value
)}
onChange
=
{(
amount
)
=>
this
.
handleAmountChanged
(
amount
)}
/
>
<
table
><
tr
>
<
td
>
<
NumeralInputWithUnits
key
=
{
sample
.
id
}
value
=
{
sample
.
amount_mg
}
unit
=
'
mg
'
label
=
"
mg
"
numeralFormat
=
'
0,0.00
'
onChange
=
{(
amount
)
=>
this
.
handleAmountChanged
(
amount
)}
/
>
<
/td
>
<
td
>
<
NumeralInputWithUnits
key
=
{
sample
.
id
}
value
=
{
sample
.
amount_ml
}
unit
=
'
ml
'
label
=
"
ml
"
numeralFormat
=
'
0,0.00
'
onChange
=
{(
amount
)
=>
this
.
handleAmountChanged
(
amount
)}
/
>
<
/td
>
<
td
>
<
NumeralInputWithUnits
key
=
{
sample
.
id
}
value
=
{
sample
.
amount_mmol
}
unit
=
'
mmol
'
label
=
"
mmol
"
numeralFormat
=
'
0,0.00
'
onChange
=
{(
amount
)
=>
this
.
handleAmountChanged
(
amount
)}
/
>
<
/td
>
<
/tr></
table
>
)
}
else
{
return
(
...
...
@@ -558,6 +580,7 @@ export default class SampleDetails extends React.Component {
<
Input
type
=
"
text
"
label
=
"
Purity
"
ref
=
"
purityInput
"
value
=
{
sample
.
purity
}
numeralFormat
=
'
0,0.00
'
onChange
=
{(
e
)
=>
this
.
handlePurityChanged
(
e
)}
/
>
)
...
...
app/assets/javascripts/components/actions/ElementActions.js
View file @
84bc6514
...
...
@@ -9,6 +9,10 @@ import ReactionSvgFetcher from '../fetchers/ReactionSvgFetcher';
import
UIActions
from
'
../actions/UIActions
'
;
import
ScreensFetcher
from
'
../fetchers/ScreensFetcher
'
;
import
Molecule
from
'
../models/Molecule
'
;
import
Sample
from
'
../models/Sample
'
;
import
Reaction
from
'
../models/Reaction
'
;
class
ElementActions
{
fetchSampleById
(
id
)
{
...
...
@@ -68,7 +72,7 @@ class ElementActions {
fetchReactionById
(
id
)
{
ReactionsFetcher
.
fetchById
(
id
)
.
then
((
result
)
=>
{
this
.
dispatch
(
result
.
reaction
);
this
.
dispatch
(
result
);
}).
catch
((
errorMessage
)
=>
{
console
.
log
(
errorMessage
);
});
...
...
@@ -144,7 +148,7 @@ class ElementActions {
}
generateEmptySample
()
{
let
sample
=
{
let
sample
=
new
Sample
(
{
id
:
'
_new_
'
,
type
:
'
sample
'
,
name
:
'
New Sample
'
,
...
...
@@ -157,7 +161,7 @@ class ElementActions {
location
:
''
,
molfile
:
''
,
molecule
:
{}
}
}
)
this
.
dispatch
(
sample
)
}
...
...
app/assets/javascripts/components/fetchers/ReactionsFetcher.js
View file @
84bc6514
import
'
whatwg-fetch
'
;
import
Reaction
from
'
../models/Reaction
'
;
// TODO: Extract common base functionality into ElementsFetcher
export
default
class
ReactionsFetcher
{
...
...
@@ -9,7 +10,7 @@ export default class ReactionsFetcher {
.
then
((
response
)
=>
{
return
response
.
json
()
}).
then
((
json
)
=>
{
return
json
;
return
new
Reaction
(
json
.
reaction
)
;
}).
catch
((
errorMessage
)
=>
{
console
.
log
(
errorMessage
);
});
...
...
@@ -26,7 +27,7 @@ export default class ReactionsFetcher {
.
then
((
response
)
=>
{
return
response
.
json
().
then
((
json
)
=>
{
return
{
elements
:
json
.
reactions
,
elements
:
json
.
reactions
.
map
((
r
)
=>
new
Reaction
(
r
))
,
totalElements
:
response
.
headers
.
get
(
'
X-Total
'
),
page
:
response
.
headers
.
get
(
'
X-Page
'
),
pages
:
response
.
headers
.
get
(
'
X-Total-Pages
'
)
...
...
app/assets/javascripts/components/models/Reaction.js
0 → 100644
View file @
84bc6514
import
Sample
from
'
../models/Sample
'
;
export
default
class
Reaction
{
constructor
(
args
)
{
Object
.
assign
(
this
,
args
);
}
get
starting_materials
()
{
return
this
.
_starting_materials
}
set
starting_materials
(
samples
)
{
this
.
_starting_materials
=
samples
.
map
(
s
=>
new
Sample
(
s
))
}
get
reactants
()
{
return
this
.
_reactants
}
set
reactants
(
samples
)
{
this
.
_reactants
=
samples
.
map
(
s
=>
new
Sample
(
s
))
}
get
products
()
{
return
this
.
_products
}
set
products
(
samples
)
{
this
.
_products
=
samples
.
map
(
s
=>
new
Sample
(
s
))
}
}
app/assets/javascripts/components/models/Sample.js
View file @
84bc6514
import
Molecule
from
'
./
m
olecule
'
;
import
Molecule
from
'
./
M
olecule
'
;
export
default
class
Sample
{
...
...
@@ -7,15 +7,107 @@ export default class Sample {
}
get
name
()
{
//console.log(`Sample(${this.id}).name`)
return
this
.
_name
}
set
name
(
name
)
{
//console.log(`Sample(${this.id}).name=${name}`)
this
.
_name
=
name
}
get
amount
()
{
return
({
value
:
amount_value
,
unit
:
amount_unit
})
}
setAmountAndNormalizeToMilligram
(
amount_value
,
amount_unit
)
{
this
.
amount_value
=
this
.
convertToMilligram
(
amount_value
,
amount_unit
)
this
.
amount_unit
=
'
mg
'
}
get
amount_value
()
{
return
this
.
_amount_value
||
0
;
}
set
amount_value
(
amount_value
)
{
this
.
_amount_value
=
amount_value
}
get
amount_unit
()
{
return
this
.
_amount_unit
||
'
mg
'
;
}
set
amount_unit
(
amount_unit
)
{
this
.
_amount_unit
=
amount_unit
}
get
amount_mg
()
{
return
this
.
convertMilligramToUnit
(
this
.
amount_value
,
'
mg
'
)
}
get
amount_ml
()
{
return
this
.
convertMilligramToUnit
(
this
.
amount_value
,
'
ml
'
)
}
get
amount_mmol
()
{
return
this
.
convertMilligramToUnit
(
this
.
amount_value
,
'
mmol
'
)
}
//Menge in mmol = Menge (mg) * Reinheit / Molmasse (g/mol)
//Volumen (ml) = Menge (mg) / Dichte (g/ml)
//Menge (mg) = Volumen (ml) * Dichte
//Menge (mg) = Menge (mmol) * Molmasse / Reinheit
convertMilligramToUnit
(
amount_mg
,
unit
)
{
switch
(
unit
)
{
case
'
mg
'
:
return
amount_mg
;
break
;
case
'
ml
'
:
return
amount_mg
/
this
.
molecule_density
;
break
;
case
'
mmol
'
:
return
amount_mg
*
this
.
purity
/
this
.
molecule_molecular_weight
;
break
;
default
:
return
amount_mg
}
}
convertToMilligram
(
amount_value
,
amount_unit
)
{
switch
(
amount_unit
)
{
case
'
mg
'
:
return
amount_value
;
break
;
case
'
ml
'
:
return
amount_value
*
this
.
molecule_density
;
break
;
case
'
mmol
'
:
return
amount_value
/
this
.
purity
*
this
.
molecule_molecular_weight
;
break
;
default
:
return
amount_value
}
}
get
molecule_density
()
{
return
this
.
molecule
&&
this
.
molecule
.
density
||
1.0
}
get
molecule_molecular_weight
()
{
return
this
.
molecule
&&
this
.
molecule
.
molecular_weight
}
get
purity
()
{
return
this
.
_purity
||
1.0
}
set
purity
(
purity
)
{
this
.
_purity
=
purity
}
get
molecule
()
{
return
this
.
_molecule
}
...
...
app/assets/stylesheets/molecules.css
View file @
84bc6514
...
...
@@ -21,7 +21,7 @@
}
.molecule-mid
svg
{
width
:
180px
;
width
:
180px
;
height
:
180px
;
margin-left
:
10px
;
}
...
...
lib/svg/reaction_composer.rb
View file @
84bc6514
...
...
@@ -14,7 +14,7 @@ module SVG
width
=
(
@starting_materials
.
size
+
@products
.
size
)
*
100
+
arrow_width
@template
=
<<-
END
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:cml="http://www.xml-cml.org/schema"
width="
#{
width
}
" height="100" viewBox="0 0
#{
width
}
100" style=" position: absolute; height: 100%;
width
:
1
00
%; left: 0; top: 0
;">
width="
#{
width
}
" height="100" viewBox="0 0
#{
width
}
100" style=" position: absolute; height: 100%;
max-height
:
2
00
px; width: 100%
;">
<title>Reaction 1</title>
END
@plus
=
<<-
END
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment