Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
nomad-FAIR
Commits
16dd821a
Commit
16dd821a
authored
Apr 28, 2020
by
Markus Scheidgen
Browse files
Refactored QuantityHistogram.
parent
0ae29760
Changes
15
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
16dd821a
...
...
@@ -25,4 +25,4 @@ nomad.yaml
./gunicorn.conf
build/
dist/
setup.json
\ No newline at end of file
setup.json
gui/.gitignore
View file @
16dd821a
...
...
@@ -12,6 +12,7 @@
# generated
public/metainfo/
public/meta.json
str/searchQuantities.json
# misc
.DS_Store
...
...
gui/src/components/api.js
View file @
16dd821a
...
...
@@ -204,8 +204,6 @@ class Api {
}
constructor
(
keycloak
)
{
this
.
statistics
=
{}
this
.
_swaggerClient
=
Swagger
(
`
${
apiBase
}
/swagger.json`
)
this
.
keycloak
=
keycloak
...
...
@@ -403,7 +401,7 @@ class Api {
.
finally
(
this
.
onFinishLoading
)
}
async
search
(
search
,
statisticsToRefresh
=
[]
)
{
async
search
(
search
)
{
this
.
onStartLoading
()
return
this
.
swagger
()
.
then
(
client
=>
client
.
apis
.
repo
.
search
({
...
...
@@ -411,32 +409,6 @@ class Api {
...
search
}))
.
catch
(
handleApiError
)
.
then
(
response
=>
response
.
body
)
.
then
(
response
=>
{
// fill absent statistics values with values from prior searches
// this helps to keep consistent values, e.g. in the metadata search view
if
(
response
.
statistics
)
{
const
empty
=
{}
const
refreshList
=
[
'
total
'
,
'
authors
'
,
'
atoms
'
].
concat
(
statisticsToRefresh
)
Object
.
keys
(
response
.
statistics
.
total
.
all
).
forEach
(
metric
=>
{
empty
[
metric
]
=
0
})
Object
.
keys
(
response
.
statistics
)
.
filter
(
key
=>
!
refreshList
.
includes
(
key
))
.
forEach
(
key
=>
{
if
(
!
this
.
statistics
[
key
])
{
this
.
statistics
[
key
]
=
new
Set
()
}
const
values
=
this
.
statistics
[
key
]
Object
.
keys
(
response
.
statistics
[
key
]).
forEach
(
value
=>
values
.
add
(
value
))
values
.
forEach
(
value
=>
{
if
(
!
response
.
statistics
[
key
][
value
])
{
response
.
statistics
[
key
][
value
]
=
empty
}
})
})
}
return
response
})
.
finally
(
this
.
onFinishLoading
)
}
...
...
gui/src/components/dft/DFTVisualizations.js
View file @
16dd821a
import
React
,
{
useContext
,
useEffect
}
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
Grid
}
from
'
@material-ui/core
'
import
{
Quantity
}
from
'
../search/QuantityHistogram
'
import
Quantity
Histogram
from
'
../search/QuantityHistogram
'
import
{
searchContext
}
from
'
../search/SearchContext
'
export
function
DFTMethodVisualizations
(
props
)
{
...
...
@@ -28,11 +28,11 @@ export function DFTMethodVisualizations(props) {
return
(
<
Grid
container
spacing
=
{
2
}
>
<
Grid
item
xs
=
{
8
}
>
<
Quantity
quantity
=
"
dft.code_name
"
title
=
"
Code
"
s
cale
=
{
0.25
}
metric
=
{
metric
}
sort
columns
=
{
2
}
/
>
<
Quantity
Histogram
quantity
=
"
dft.code_name
"
title
=
"
Code
"
initialS
cale
=
{
0.25
}
columns
=
{
2
}
/
>
<
/Grid
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.basis_set
"
title
=
"
Basis set
"
s
cale
=
{
0.25
}
metric
=
{
metric
}
sort
/>
<
Quantity
quantity
=
"
dft.xc_functional
"
title
=
"
XC functionals
"
s
cale
=
{
0.5
}
metric
=
{
metric
}
sort
/>
<
Quantity
Histogram
quantity
=
"
dft.basis_set
"
title
=
"
Basis set
"
initialS
cale
=
{
0.25
}
/
>
<
Quantity
Histogram
quantity
=
"
dft.xc_functional
"
title
=
"
XC functionals
"
initialS
cale
=
{
0.5
}
/
>
<
/Grid
>
<
/Grid
>
)
...
...
@@ -44,9 +44,8 @@ DFTMethodVisualizations.propTypes = {
export
function
DFTSystemVisualizations
(
props
)
{
const
{
info
}
=
props
const
{
response
:
{
statistics
,
metric
},
setStatisticsToRefresh
,
setStatistics
}
=
useContext
(
searchContext
)
const
{
response
:
{
statistics
,
metric
},
setStatistics
}
=
useContext
(
searchContext
)
useEffect
(()
=>
{
setStatisticsToRefresh
(
'
dft.labels_springer_compound_class
'
)
setStatistics
([
'
dft.labels_springer_compound_class
'
,
'
dft.system
'
,
'
dft.crystal_system
'
,
'
dft.compound_type
'
])
},
[])
...
...
@@ -67,14 +66,14 @@ export function DFTSystemVisualizations(props) {
return
(
<
Grid
container
spacing
=
{
2
}
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.compound_type
"
title
=
"
Compound type
"
scale
=
{
1
}
metric
=
{
metric
}
sort
/>
<
Quantity
Histogram
quantity
=
"
dft.compound_type
"
title
=
"
Compound type
"
initialScale
=
{
0.25
}
/
>
<
/Grid
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.system
"
title
=
"
System type
"
s
cale
=
{
0.25
}
metric
=
{
metric
}
sort
/>
<
Quantity
quantity
=
"
dft.crystal_system
"
title
=
"
Crystal system
"
scale
=
{
1
}
metric
=
{
metric
}
sort
/>
<
Quantity
Histogram
quantity
=
"
dft.system
"
title
=
"
System type
"
initialS
cale
=
{
0.25
}
/
>
<
Quantity
Histogram
quantity
=
"
dft.crystal_system
"
title
=
"
Crystal system
"
/>
<
/Grid
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.labels_springer_compound_class
"
title
=
"
Springer compound
"
scale
=
{
1
}
metric
=
{
metric
}
/
>
<
Quantity
Histogram
quantity
=
"
dft.labels_springer_compound_class
"
title
=
"
Springer compound
"
/>
<
/Grid
>
<
/Grid
>
)
...
...
@@ -84,51 +83,75 @@ DFTSystemVisualizations.propTypes = {
info
:
PropTypes
.
object
}
const
searchable_quantities_categories
=
{
energy_quantities
:
[
'
energy_total
'
,
'
energy_total_T0
'
,
'
energy_free
'
,
'
energy_electrostatic
'
,
'
energy_X
'
,
'
energy_XC
'
,
'
energy_sum_eigenvalues
'
],
electronic_quantities
:
[
'
dos_values
'
,
'
eigenvalues_values
'
,
'
volumetric_data_values
'
,
'
electronic_kinetic_energy
'
,
'
total_charge
'
,
'
atomic_multipole_values
'
],
forces_quantities
:
[
'
atom_forces_free
'
,
'
atom_forces_raw
'
,
'
atom_forces_T0
'
,
'
atom_forces
'
,
'
stress_tensor
'
],
vibrational_quantities
:
[
'
thermodynamical_property_heat_capacity_C_v
'
,
'
vibrational_free_energy_at_constant_volume
'
,
'
band_energies
'
],
magnetic_quantities
:
[
'
spin_S2
'
],
optical_quantities
:
[
'
excitation_energies
'
,
'
oscillator_strengths
'
,
'
transition_dipole_moments
'
]
}
const
energy_quantities
=
[
'
energy_total
'
,
'
energy_total_T0
'
,
'
energy_free
'
,
'
energy_electrostatic
'
,
'
energy_X
'
,
'
energy_XC
'
,
'
energy_sum_eigenvalues
'
]
const
electronic_quantities
=
[
'
dos_values
'
,
'
eigenvalues_values
'
,
'
volumetric_data_values
'
,
'
electronic_kinetic_energy
'
,
'
total_charge
'
,
'
atomic_multipole_values
'
]
const
forces_quantities
=
[
'
atom_forces_free
'
,
'
atom_forces_raw
'
,
'
atom_forces_T0
'
,
'
atom_forces
'
,
'
stress_tensor
'
]
const
vibrational_quantities
=
[
'
thermodynamical_property_heat_capacity_C_v
'
,
'
vibrational_free_energy_at_constant_volume
'
,
'
band_energies
'
]
const
magnetic_quantities
=
[
'
spin_S2
'
]
const
optical_quantities
=
[
'
excitation_energies
'
,
'
oscillator_strengths
'
,
'
transition_dipole_moments
'
]
const
labels
=
{
'
energy_total
'
:
'
Total energy
'
,
'
energy_total_T0
'
:
'
Total energy (0K)
'
,
'
energy_free
'
:
'
Free energy
'
,
'
energy_electrostatic
'
:
'
Electrostatic
'
,
'
energy_X
'
:
'
Exchange
'
,
'
energy_XC
'
:
'
Exchange-correlation
'
,
'
energy_sum_eigenvalues
'
:
'
Band energy
'
,
'
dos_values
'
:
'
DOS
'
,
'
eigenvalues_values
'
:
'
Eigenvalues
'
,
'
volumetric_data_values
'
:
'
Volumetric data
'
,
'
electronic_kinetic_energy
'
:
'
Kinetic energy
'
,
'
total_charge
'
:
'
Charge
'
,
'
atom_forces_free
'
:
'
Free atomic forces
'
,
'
atom_forces_raw
'
:
'
Raw atomic forces
'
,
'
atom_forces_T0
'
:
'
Atomic forces (0K)
'
,
'
atom_forces
'
:
'
Atomic forces
'
,
'
stress_tensor
'
:
'
Stress tensor
'
,
'
thermodynamical_property_heat_capacity_C_v
'
:
'
Heat capacity
'
,
'
vibrational_free_energy_at_constant_volume
'
:
'
Free energy (const=V)
'
,
'
band_energies
'
:
'
Band energies
'
,
'
spin_S2
'
:
'
Spin momentum operator
'
,
'
excitation_energies
'
:
'
Excitation energies
'
,
'
oscillator_strengths
'
:
'
Oscillator strengths
'
,
'
transition_dipole_moments
'
:
'
Transition dipole moments
'
,
'
atomic_multipole_values
'
:
'
Atomic multipole values
'
}
export
function
DFTPropertyVisualizations
(
props
)
{
const
{
info
}
=
props
const
{
response
:
{
statistics
,
metric
},
setStatisticsToRefresh
,
setStatistics
}
=
useContext
(
searchContext
)
const
{
response
:
{
statistics
,
metric
},
setStatistics
}
=
useContext
(
searchContext
)
useEffect
(()
=>
{
setStatisticsToRefresh
(
'
dft.labels_springer_classification
'
)
setStatistics
([
'
dft.searchable_quantities
'
,
'
dft.labels_springer_classification
'
...
...
@@ -149,35 +172,20 @@ export function DFTPropertyVisualizations(props) {
statistics
.
code_name
=
filteredCodeNames
}
const
data
=
(
category
)
=>
{
const
results
=
{}
const
data
=
statistics
[
'
dft.searchable_quantities
'
]
if
(
!
data
)
{
return
null
}
searchable_quantities_categories
[
category
].
forEach
(
value
=>
{
if
(
data
[
value
])
{
results
[
value
]
=
data
[
value
]
}
})
return
results
}
return
(
<
Grid
container
spacing
=
{
2
}
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.searchable_quantities
"
data
=
{
data
(
'
energy_quantities
'
)}
title
=
"
Energy
"
scale
=
{
1
}
metric
=
{
metric
}
sort
tooltips
/>
<
Quantity
quantity
=
"
dft.searchable_quantities
"
data
=
{
data
(
'
electronic_quantities
'
)}
title
=
"
Electronic
"
scale
=
{
1
}
metric
=
{
metric
}
sort
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.searchable_quantities
"
values
=
{
energy_quantities
}
valueLabels
=
{
labels
}
title
=
"
Energy
"
initialScale
=
{
0.5
}
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.searchable_quantities
"
values
=
{
electronic_quantities
}
valueLabels
=
{
labels
}
title
=
"
Electronic
"
initialScale
=
{
0.5
}
tooltips
/>
<
/Grid
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.searchable_quantities
"
data
=
{
data
(
'
forces_quantities
'
)}
title
=
"
Forces
"
scale
=
{
1
}
metric
=
{
metric
}
sort
tooltips
/>
<
Quantity
quantity
=
"
dft.searchable_quantities
"
data
=
{
data
(
'
vibrational_quantities
'
)
}
title
=
"
Vibrational
"
scale
=
{
1
}
metric
=
{
metric
}
sort
tooltips
/>
<
Quantity
quantity
=
"
dft.searchable_quantities
"
data
=
{
data
(
'
optical_quantities
'
)}
title
=
"
Optical
"
scale
=
{
1
}
metric
=
{
metric
}
sort
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.searchable_quantities
"
values
=
{
forces_quantities
}
valueLabels
=
{
labels
}
title
=
"
Forces
"
initialScale
=
{
0.5
}
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.searchable_quantities
"
values
=
{
vibrational_quantities
}
valueLabels
=
{
labels
}
title
=
"
Vibrational
"
initialScale
=
{
0.5
}
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.searchable_quantities
"
values
=
{
optical_quantities
}
valueLabels
=
{
labels
}
title
=
"
Optical
"
initialScale
=
{
1
}
tooltips
/>
<
/Grid
>
<
Grid
item
xs
=
{
4
}
>
<
Quantity
quantity
=
"
dft.labels_springer_classification
"
title
=
"
Springer classification
"
scale
=
{
1
}
metric
=
{
metric
}
tooltips
/>
<
Quantity
quantity
=
"
dft.searchable_quantities
"
data
=
{
data
(
'
magnetic_quantities
'
)}
title
=
"
Magnetic
"
scale
=
{
1
}
metric
=
{
metric
}
sort
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.labels_springer_classification
"
title
=
"
Springer classification
"
initialScale
=
{
1
}
tooltips
/>
<
Quantity
Histogram
quantity
=
"
dft.searchable_quantities
"
values
=
{
magnetic_quantities
}
valueLabels
=
{
labels
}
title
=
"
Magnetic
"
initialScale
=
{
1
}
tooltips
/>
<
/Grid
>
<
/Grid
>
)
...
...
gui/src/components/ems/EMSVisualizations.js
View file @
16dd821a
import
React
,
{
useContext
,
useEffect
}
from
'
react
'
import
{
Grid
}
from
'
@material-ui/core
'
import
{
Quantity
}
from
'
../search/QuantityHistogram
'
import
Quantity
Histogram
from
'
../search/QuantityHistogram
'
import
{
searchContext
}
from
'
../search/SearchContext
'
export
default
function
EMSVisualizations
(
props
)
{
const
{
state
:
{
usedMetric
},
setStatistics
}
=
useContext
(
searchContext
)
const
{
setStatistics
}
=
useContext
(
searchContext
)
useEffect
(()
=>
{
setStatistics
([
'
ems.method
'
,
'
ems.probing_method
'
,
'
ems.sample_microstructure
'
,
'
ems.sample_constituents
'
])
},
[])
return
(
<
Grid
container
spacing
=
{
2
}
>
<
Grid
item
xs
=
{
6
}
>
<
Quantity
quantity
=
"
ems.method
"
title
=
"
Method
"
scale
=
{
1
}
metric
=
{
usedMetric
}
/
>
<
Quantity
quantity
=
"
ems.probing_method
"
title
=
"
Probing
"
scale
=
{
1
}
metric
=
{
usedMetric
}
/
>
<
Quantity
Histogram
quantity
=
"
ems.method
"
title
=
"
Method
"
/>
<
Quantity
Histogram
quantity
=
"
ems.probing_method
"
title
=
"
Probing
"
/>
<
/Grid
>
<
Grid
item
xs
=
{
6
}
>
<
Quantity
quantity
=
"
ems.sample_microstructure
"
title
=
"
Sample structure
"
scale
=
{
1
}
metric
=
{
usedMetric
}
/
>
<
Quantity
quantity
=
"
ems.sample_constituents
"
title
=
"
Sample constituents
"
scale
=
{
1
}
metric
=
{
usedMetric
}
/
>
<
Quantity
Histogram
quantity
=
"
ems.sample_microstructure
"
title
=
"
Sample structure
"
/>
<
Quantity
Histogram
quantity
=
"
ems.sample_constituents
"
title
=
"
Sample constituents
"
/>
<
/Grid
>
<
/Grid
>
)
...
...
gui/src/components/search/QuantityHistogram.js
View file @
16dd821a
import
React
,
{
useContext
}
from
'
react
'
import
React
,
{
useRef
,
useState
,
useEffect
,
useContext
}
from
'
react
'
import
PropTypes
from
'
prop-types
'
import
{
withStyles
,
Select
,
MenuItem
,
Card
,
CardContent
,
CardHeader
,
makeStyles
}
from
'
@material-ui/core
'
import
{
Select
,
MenuItem
,
Card
,
CardContent
,
CardHeader
,
makeStyles
}
from
'
@material-ui/core
'
import
*
as
d3
from
'
d3
'
import
{
scaleBand
,
scalePow
}
from
'
d3-scale
'
import
{
formatQuantity
,
nomadPrimaryColor
,
nomadSecondaryColor
}
from
'
../../config.js
'
import
{
searchContext
}
from
'
./SearchContext
'
import
{
searchContext
}
from
'
./SearchContext.js
'
import
*
as
searchQuantities
from
'
../../searchQuantities.json
'
const
unprocessedLabel
=
'
not processed
'
const
unavailableLabel
=
'
unavailable
'
...
...
@@ -17,135 +18,66 @@ function split(array, cols) {
return
[
array
.
slice
(
0
,
size
),
...
split
(
array
.
slice
(
size
),
cols
-
1
)]
}
const
_mapping
=
{
'
energy_total
'
:
'
Total energy
'
,
'
energy_total_T0
'
:
'
Total energy (0K)
'
,
'
energy_free
'
:
'
Free energy
'
,
'
energy_electrostatic
'
:
'
Electrostatic
'
,
'
energy_X
'
:
'
Exchange
'
,
'
energy_XC
'
:
'
Exchange-correlation
'
,
'
energy_sum_eigenvalues
'
:
'
Band energy
'
,
'
dos_values
'
:
'
DOS
'
,
'
eigenvalues_values
'
:
'
Eigenvalues
'
,
'
volumetric_data_values
'
:
'
Volumetric data
'
,
'
electronic_kinetic_energy
'
:
'
Kinetic energy
'
,
'
total_charge
'
:
'
Charge
'
,
'
atom_forces_free
'
:
'
Free atomic forces
'
,
'
atom_forces_raw
'
:
'
Raw atomic forces
'
,
'
atom_forces_T0
'
:
'
Atomic forces (0K)
'
,
'
atom_forces
'
:
'
Atomic forces
'
,
'
stress_tensor
'
:
'
Stress tensor
'
,
'
thermodynamical_property_heat_capacity_C_v
'
:
'
Heat capacity
'
,
'
vibrational_free_energy_at_constant_volume
'
:
'
Free energy (const=V)
'
,
'
band_energies
'
:
'
Band energies
'
,
'
spin_S2
'
:
'
Spin momentum operator
'
,
'
excitation_energies
'
:
'
Excitation energies
'
,
'
oscillator_strengths
'
:
'
Oscillator strengths
'
,
'
transition_dipole_moments
'
:
'
Transition dipole moments
'
}
class
QuantityHistogramUnstyled
extends
React
.
Component
{
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
title
:
PropTypes
.
string
.
isRequired
,
width
:
PropTypes
.
number
.
isRequired
,
data
:
PropTypes
.
object
,
metric
:
PropTypes
.
string
.
isRequired
,
value
:
PropTypes
.
string
,
onChanged
:
PropTypes
.
func
.
isRequired
,
defaultScale
:
PropTypes
.
number
,
sort
:
PropTypes
.
bool
,
tooltips
:
PropTypes
.
bool
,
columns
:
PropTypes
.
number
}
static
styles
=
theme
=>
({
root
:
{},
content
:
{
paddingTop
:
0
,
position
:
'
relative
'
},
tooltip
:
{
textAlign
:
'
center
'
,
position
:
'
absolute
'
,
pointerEvents
:
'
none
'
,
opacity
:
0
},
tooltipContent
:
{
// copy of the material ui popper style
display
:
'
inline-block
'
,
color
:
'
#fff
'
,
padding
:
'
4px 8px
'
,
fontSize
:
'
0.625rem
'
,
fontFamily
:
'
"Roboto", "Helvetica", "Arial", sans-serif
'
,
lineHeight
:
'
1.4em
'
,
borderRadius
:
'
4px
'
,
backgroundColor
:
'
#616161
'
}
})
constructor
(
props
)
{
super
(
props
)
this
.
container
=
React
.
createRef
()
}
state
=
{
scalePower
:
this
.
props
.
defaultScale
||
0.25
}
componentDidMount
()
{
this
.
updateChart
()
}
componentDidUpdate
()
{
this
.
updateChart
()
const
useStyles
=
makeStyles
(
theme
=>
({
root
:
{
marginTop
:
theme
.
spacing
(
2
)
},
content
:
{
paddingTop
:
0
,
position
:
'
relative
'
},
tooltip
:
{
textAlign
:
'
center
'
,
position
:
'
absolute
'
,
pointerEvents
:
'
none
'
,
opacity
:
0
},
tooltipContent
:
{
// copy of the material ui popper style
display
:
'
inline-block
'
,
color
:
'
#fff
'
,
padding
:
'
4px 8px
'
,
fontSize
:
'
0.625rem
'
,
fontFamily
:
'
"Roboto", "Helvetica", "Arial", sans-serif
'
,
lineHeight
:
'
1.4em
'
,
borderRadius
:
'
4px
'
,
backgroundColor
:
'
#616161
'
}
handleItemClicked
(
item
)
{
if
(
this
.
props
.
value
===
item
.
key
)
{
this
.
props
.
onChanged
(
null
)
}
else
{
this
.
props
.
onChanged
(
item
.
key
)
}
}))
export
default
function
QuantityHistogram
({
quantity
,
initialScale
=
1
,
valueLabels
=
{},
title
,
values
,
numberOfValues
,
columns
=
1
,
tooltips
})
{
title
=
title
||
quantity
values
=
values
||
(
searchQuantities
[
quantity
]
&&
searchQuantities
[
quantity
].
statistic_values
)
numberOfValues
=
numberOfValues
||
(
values
&&
values
.
length
)
||
(
searchQuantities
[
quantity
]
&&
searchQuantities
[
quantity
].
statistic_size
)
const
{
response
:
{
statistics
,
metric
},
query
,
setQuery
}
=
useContext
(
searchContext
)
const
statisticsData
=
statistics
[
quantity
]
const
classes
=
useStyles
()
const
containerRef
=
useRef
()
const
[
scale
,
setScale
]
=
useState
(
initialScale
)
const
handleItemClicked
=
item
=>
{
setQuery
({[
quantity
]:
(
query
[
quantity
]
===
item
.
key
)
?
null
:
item
.
key
})
}
u
pdateChart
()
{
const
{
classes
,
sort
,
tooltips
}
=
this
.
props
u
seEffect
(()
=>
{
let
data
=
null
if
(
!
this
.
props
.
data
)
{
return
}
const
data
=
Object
.
keys
(
this
.
props
.
data
)
.
map
(
key
=>
({
key
:
key
,
name
:
_mapping
[
key
]
||
key
,
value
:
this
.
props
.
data
[
key
][
this
.
props
.
metric
]
if
(
!
statistics
[
quantity
])
{
data
=
[]
}
else
if
(
values
)
{
data
=
values
.
map
(
value
=>
({
key
:
value
,
name
:
valueLabels
[
value
]
||
value
,
value
:
statisticsData
[
value
]
?
statisticsData
[
value
][
metric
]
:
0
}))
if
(
sort
)
{
data
.
sort
((
a
,
b
)
=>
{
const
nameA
=
a
.
name
const
nameB
=
b
.
name
if
(
nameA
===
nameB
)
{
return
0
}
if
(
nameA
===
unprocessedLabel
)
{
return
1
}
if
(
nameB
===
unprocessedLabel
)
{
return
-
1
}
if
(
nameA
===
unavailableLabel
)
{
return
1
}
if
(
nameB
===
unavailableLabel
)
{
return
-
1
}
return
nameA
.
localeCompare
(
nameB
)
})
}
else
{
data
=
Object
.
keys
(
statisticsData
)
.
map
(
value
=>
({
key
:
value
,
name
:
valueLabels
[
value
]
||
value
,
value
:
statisticsData
[
value
][
metric
]
}))
// keep the data sorting, but put unavailable and not processed to the end
const
unavailableIndex
=
data
.
findIndex
(
d
=>
d
.
name
===
unavailableLabel
)
const
unprocessedIndex
=
data
.
findIndex
(
d
=>
d
.
name
===
unprocessedLabel
)
...
...
@@ -157,21 +89,23 @@ class QuantityHistogramUnstyled extends React.Component {
}
}
const
columns
=
this
.
props
.
columns
||
1
for
(
let
i
=
data
.
length
;
i
<
numberOfValues
;
i
++
)
{
data
.
push
({
key
:
`empty
${
i
}
`
,
name
:
''
,
value
:
0
})
}
const
columnSize
=
Math
.
ceil
(
data
.
length
/
columns
)
for
(
let
i
=
data
.
length
;
i
<
columnSize
*
columns
;
i
++
)
{
data
.
push
({
key
:
`empty
${
i
}
`
,
name
:
''
,
value
:
0
})
}
const
columnsData
=
split
(
data
,
columns
)
const
{
scalePower
}
=
this
.
state
const
selected
=
this
.
props
.
value
const
selected
=
query
[
quantity
]
const
containerWidth
=
this
.
container
.
current
.
offsetWidth
const
containerWidth
=
container
Ref
.
current
.
offsetWidth
const
width
=
containerWidth
/
columns
-
(
12
*
(
columns
-
1
))
const
height
=
columnSize
*
32
const
x
=
scalePow
().
range
([
0
,
width
]).
exponent
(
scale
Power
)
const
x
=
scalePow
().
range
([
0
,
width
]).
exponent
(
scale
)
// we use at least the domain 0..1, because an empty domain causes a weird layout
const
max
=
d3
.
max
(
data
,
d
=>
d
.
value
)
||
1
...
...
@@ -180,7 +114,7 @@ class QuantityHistogramUnstyled extends React.Component {
const
rectColor
=
d
=>
selected
===
d
.
key
?
nomadPrimaryColor
.
main
:
nomadSecondaryColor
.
light
const
textColor
=
d
=>
selected
===
d
.
key
?
'
#FFF
'
:
'
#000
'
const
container
=
d3
.
select
(
this
.
container
.
current
)
const
container
=
d3
.
select
(
container
Ref
.
current
)
const
tooltip
=
container
.
select
(
'
.
'
+
classes
.
tooltip
)
.
style
(
'
width
'
,
width
+
'
px
'
)
.
style
(
'
opacity
'
,
0
)
...
...
@@ -203,14 +137,17 @@ class QuantityHistogramUnstyled extends React.Component {
columnsData
.
forEach
((
data
,
i
)
=>
{
const
y
=
scaleBand
().
rangeRound
([
0
,
height
]).
padding
(
0.1
)
y
.
domain
(
data
.
map
(
d
=>
d
.
name
))
y
.
domain
(
data
.
map
(
d
=>
d
.
key
))
const
items
=
svg
.
select
(
'
#column
'
+
i
)
.
selectAll
(
'
.item
'
)
.
data
(
data
,
d
=>
d
.
name
)
.
data
(
data
,
d
=>
d
.
key
)
items
.
exit
().
remove
()
items
.
on
(
'
click
'
,
d
=>
handleItemClicked
(
d
))
let
item
=
items
.
enter
()