Commit 9bdae72b authored by Lauri Himanen's avatar Lauri Himanen Committed by Markus Scheidgen
Browse files

Removed the custom ErrorCard-component in favour of the Alert-component in...

Removed the custom ErrorCard-component in favour of the Alert-component in MUI, added better error handling for invalid geometry optimization data.
parent a39461bd
Subproject commit 52e4caf2dab39e1ddf3fbff7d9c4adef06851f87
Subproject commit 51e2d0d8d30d29f0399bd669aa7cfbb9f12aa94b
......@@ -16,19 +16,8 @@
* limitations under the License.
*/
import React from 'react'
import clsx from 'clsx'
import { makeStyles } from '@material-ui/core/styles'
import PropTypes from 'prop-types'
import {
Box,
Button,
Card,
CardContent,
Typography
} from '@material-ui/core'
import {
Error
} from '@material-ui/icons'
import Alert from '@material-ui/lab/Alert'
export class ErrorHandler extends React.Component {
state = {
......@@ -49,11 +38,13 @@ export class ErrorHandler extends React.Component {
render() {
if (this.state.hasError) {
let msg = typeof this.props.message === 'string' ? this.props.message : this.props.message(this.state.error)
return <ErrorCard
message={msg}
return <Alert
severity="error"
className={this.props.className}
classes={this.props.classes}
></ErrorCard>
>
{msg}
</Alert>
}
return this.props.children
}
......@@ -65,73 +56,6 @@ ErrorHandler.propTypes = ({
className: PropTypes.string
})
export function ErrorCard({message, className, classes, actions}) {
const useStyles = makeStyles((theme) => {
return {
root: {
color: theme.palette.error.main
},
content: {
paddingBottom: '16px'
},
'content:last-child': {
paddingBottom: '16px !important'
},
title: {
marginBottom: 0
},
pos: {
marginBottom: 12
},
row: {
display: 'flex'
},
actions: {
display: 'flex',
justifyContent: 'flex-end'
},
column: {
display: 'flex',
flexDirection: 'column'
},
errorIcon: {
marginRight: theme.spacing(1)
}
}
})
const style = useStyles(classes)
return <Card className={clsx(style.root, className)}>
<CardContent className={[style.content, style['content:last-child']].join(' ')}>
<Box className={style.row}>
<Error className={style.errorIcon}/>
<Box className={style.column}>
<Typography className={style.title} color="error" gutterBottom>
{message}
</Typography>
{actions
? <Box className={style.actions}>
{actions.map((action) => <Button key={action.label} onClick={action.onClick}>
{action.label}
</Button>
)}
</Box>
: ''
}
</Box>
</Box>
</CardContent>
</Card>
}
ErrorCard.propTypes = ({
message: PropTypes.string,
classes: PropTypes.object,
className: PropTypes.string,
actions: PropTypes.array
})
export const withErrorHandler = (WrappedComponent, message) => props => (
<ErrorHandler message={message}>
<WrappedComponent {...props}></WrappedComponent>
......
......@@ -225,32 +225,44 @@ export default function DFTEntryOverview({data}) {
// Gather energies, trajectory and energy change threshold from geometry
// optimization
if (wfType === 'geometry_optimization') {
const calculations = section_wf.calculations_ref
let failed = false
let energies = []
const trajectory = []
let initialEnergy = null
let failed = false
for (let i = 0; i < calculations.length; ++i) {
let ref = calculations[i]
const calc = resolveRef(ref, archive)
const e = calc?.energy_total
if (e === undefined) {
failed = true
break
try {
const calculations = section_wf.calculations_ref
let initialEnergy = null
if (!calculations) {
throw Error('no calculations')
}
if (i === 0) {
initialEnergy = e
for (let i = 0; i < calculations.length; ++i) {
let ref = calculations[i]
const calc = resolveRef(ref, archive)
let e = calc.energy_total
if (e === undefined) {
if (i === calculations.length - 1) {
break
} else {
throw Error('invalid energy value')
}
}
if (i === 0) {
initialEnergy = e
}
energies.push(e - initialEnergy)
let sys = calc.single_configuration_calculation_to_system_ref
sys = resolveRef(sys, archive)
if (sys === undefined) {
throw Error('invalid system reference')
}
trajectory.push({
species: sys.atom_species,
cell: sys.lattice_vectors ? convertSI(sys.lattice_vectors, 'meter', {length: 'angstrom'}, false) : undefined,
positions: convertSI(sys.atom_positions, 'meter', {length: 'angstrom'}, false),
pbc: sys.configuration_periodic_dimensions
})
}
energies.push(e - initialEnergy)
let sys = calc?.single_configuration_calculation_to_system_ref
sys = resolveRef(sys, archive)
trajectory.push({
species: sys.atom_species,
cell: sys.lattice_vectors ? convertSI(sys.lattice_vectors, 'meter', {length: 'angstrom'}, false) : undefined,
positions: convertSI(sys.atom_positions, 'meter', {length: 'angstrom'}, false),
pbc: sys.configuration_periodic_dimensions
})
} catch (err) {
failed = true
}
if (!failed) {
energies = convertSI(energies, 'joule', {energy: 'electron_volt'}, false)
......@@ -259,6 +271,8 @@ export default function DFTEntryOverview({data}) {
const e_criteria_fs = sampling_method && sampling_method[0]?.geometry_optimization_energy_change
const e_criteria = e_criteria_wf || e_criteria_fs
setGeoOpt({energies: energies, structures: trajectory, energy_change_criteria: e_criteria})
} else {
setGeoOpt({})
}
} else if (wfType === 'phonon') {
// Find phonon dos and dispersion
......
......@@ -21,12 +21,13 @@ import { makeStyles, fade } from '@material-ui/core/styles'
import {
Box,
Checkbox,
Button,
Menu,
MenuItem,
Typography,
FormControlLabel
} from '@material-ui/core'
import { ToggleButton, ToggleButtonGroup } from '@material-ui/lab'
import { ToggleButton, ToggleButtonGroup, Alert } from '@material-ui/lab'
import {
MoreVert,
Fullscreen,
......@@ -40,7 +41,7 @@ import Floatable from './Floatable'
import Placeholder from '../visualization/Placeholder'
import Actions from '../Actions'
import { mergeObjects } from '../../utils'
import { withErrorHandler, ErrorCard } from '../ErrorHandler'
import { withErrorHandler } from '../ErrorHandler'
import { useHistory } from 'react-router-dom'
import _ from 'lodash'
import clsx from 'clsx'
......@@ -160,7 +161,7 @@ export const Structure = withErrorHandler(({
if (options === undefined) {
viewerOptions = {
view: {
autoResize: true,
autoResize: false,
autoFit: true,
fitMargin: 0.6
},
......@@ -207,9 +208,9 @@ export const Structure = withErrorHandler(({
}, [positionsSubject])
const loadSystem = useCallback((system, refViewer) => {
// If the cell all zeroes, positions are assumed to be cartesian.
// If the cell is all zeroes, positions are assumed to be cartesian.
if (system.cell !== undefined) {
if (_.sum(_.flattenDeep(system.cell)) === 0) {
if (_.flattenDeep(system.cell).every(v => v === 0)) {
system.cell = undefined
}
}
......@@ -245,6 +246,7 @@ export const Structure = withErrorHandler(({
// Systems without cell are centered on the center of positions
} else {
opts.layout.viewCenter = 'COP'
opts.layout.periodicity = 'none'
}
refViewer.current.setOptions(opts, false, false)
refViewer.current.load(system)
......@@ -289,8 +291,10 @@ export const Structure = withErrorHandler(({
}, [showLatticeConstants])
useEffect(() => {
refViewer.current.setOptions({layout: {periodicity: wrap ? 'wrap' : 'none'}})
}, [wrap])
if (finalSystem?.cell) {
refViewer.current.setOptions({layout: {periodicity: wrap ? 'wrap' : 'none'}})
}
}, [wrap, finalSystem])
useEffect(() => {
refViewer.current.setOptions({cell: {enabled: showCell}})
......@@ -344,12 +348,20 @@ export const Structure = withErrorHandler(({
}
if (showPrompt) {
return <ErrorCard
message={`Visualization is by default disabled for systems with more than ${sizeLimit} atoms. Do you wish to enable visualization for this system with ${nAtoms} atoms?`}
className={styles.error}
actions={[{label: 'Yes', onClick: e => { setShowPrompt(false); loadSystem(finalSystem, refViewer); setAccepted(true) }}]}
return <Alert
severity="info"
action={
<Button
color="inherit"
size="small"
onClick={e => { setShowPrompt(false); loadSystem(finalSystem, refViewer); setAccepted(true) }}
>
YES
</Button>
}
>
</ErrorCard>
{`Visualization is by default disabled for systems with more than ${sizeLimit} atoms. Do you wish to enable visualization for this system with ${nAtoms} atoms?`}
</Alert>
}
if (loading) {
return <Placeholder variant="rect" aspectRatio={aspectRatio}></Placeholder>
......@@ -403,42 +415,46 @@ export const Structure = withErrorHandler(({
label='Show bonds'
/>
</MenuItem>
<MenuItem key='show-axis'>
<FormControlLabel
control={
<Checkbox
checked={showLatticeConstants}
onChange={(event) => { setShowLatticeConstants(!showLatticeConstants) }}
color='primary'
{finalSystem?.cell &&
<>
<MenuItem key='show-axis'>
<FormControlLabel
control={
<Checkbox
checked={showLatticeConstants}
onChange={(event) => { setShowLatticeConstants(!showLatticeConstants) }}
color='primary'
/>
}
label='Show lattice constants'
/>
}
label='Show lattice constants'
/>
</MenuItem>
<MenuItem key='show-cell'>
<FormControlLabel
control={
<Checkbox
checked={showCell}
onChange={(event) => { setShowCell(!showCell) }}
color='primary'
</MenuItem>
<MenuItem key='show-cell'>
<FormControlLabel
control={
<Checkbox
checked={showCell}
onChange={(event) => { setShowCell(!showCell) }}
color='primary'
/>
}
label='Show simulation cell'
/>
}
label='Show simulation cell'
/>
</MenuItem>
<MenuItem key='wrap'>
<FormControlLabel
control={
<Checkbox
checked={wrap}
onChange={(event) => { setWrap(!wrap) }}
color='primary'
</MenuItem>
<MenuItem key='wrap'>
<FormControlLabel
control={
<Checkbox
checked={wrap}
onChange={(event) => { setWrap(!wrap) }}
color='primary'
/>
}
label='Wrap positions'
/>
}
label='Wrap positions'
/>
</MenuItem>
</MenuItem>
</>
}
</Menu>
</div>
</Box>
......
......@@ -130,7 +130,7 @@ export function add(value, addition) {
*
* @param {*} value The values to convert. Can be a scalar or an n-dimensional
* array.
* @param {string} from Original SI unit definition. Can be any algebraic
* @param {string} unit Original SI unit definition. Can be any algebraic
* combination of SI units, e.g. "1 / meter^2". The unit names should follow
* the definitions provided in the file units.js that is generated by the NOMAD
* CLI.
......@@ -138,6 +138,9 @@ export function add(value, addition) {
* physical quantity (e.g. "length") acts as a key that corresponds to a target
* unit (e.g. "angstrom"). The unit names should follow the definitions
* provided in the file units.js that is generated by the NOMAD CLI.
* array.
* @param {string} units Whether to return the new unit as a string together
* with the new values.
*
* @return {*} A copy of the original data with units converted.
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment