Skip to content

Commit

Permalink
Merge pull request #43 from stan-donarise/master
Browse files Browse the repository at this point in the history
coincided atoms handling
  • Loading branch information
blokhin authored Jul 29, 2024
2 parents b4c9bb2 + aef5daf commit 4dfe534
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 72 deletions.
2 changes: 1 addition & 1 deletion matinfio/cif/cif.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ namespace $ {
atom.overlays.label = atom.label
if( !atom.symbol ) atom.symbol = atom.label.replace( /[0-9]/g, '' )
}
if( !( $optimade_cifplayer_matinfio_chemical_elements.JmolColors as any )[ atom.symbol ]
if( ! $optimade_cifplayer_matinfio_chemical_elements.JmolColors[ atom.symbol ]
&& atom.symbol
&& atom.symbol.length > 1
) {
Expand Down
23 changes: 8 additions & 15 deletions matinfio/matinfio.web.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace $ {

export const $optimade_cifplayer_matinfio_chemical_elements = {
export const $optimade_cifplayer_matinfio_chemical_elements: {
JmolColors: Record< string, string >,
AseRadii: Record< string, number >,
} = {
JmolColors: { "D": "#FFFFC0", "H": "#FFFFFF", "He": "#D9FFFF", "Li": "#CC80FF", "Be": "#C2FF00", "B": "#FFB5B5", "C": "#909090", "N": "#3050F8", "O": "#FF0D0D", "F": "#90E050", "Ne": "#B3E3F5", "Na": "#AB5CF2", "Mg": "#8AFF00", "Al": "#BFA6A6", "Si": "#F0C8A0", "P": "#FF8000", "S": "#FFFF30", "Cl": "#1FF01F", "Ar": "#80D1E3", "K": "#8F40D4", "Ca": "#3DFF00", "Sc": "#E6E6E6", "Ti": "#BFC2C7", "V": "#A6A6AB", "Cr": "#8A99C7", "Mn": "#9C7AC7", "Fe": "#E06633", "Co": "#F090A0", "Ni": "#50D050", "Cu": "#C88033", "Zn": "#7D80B0", "Ga": "#C28F8F", "Ge": "#668F8F", "As": "#BD80E3", "Se": "#FFA100", "Br": "#A62929", "Kr": "#5CB8D1", "Rb": "#702EB0", "Sr": "#00FF00", "Y": "#94FFFF", "Zr": "#94E0E0", "Nb": "#73C2C9", "Mo": "#54B5B5", "Tc": "#3B9E9E", "Ru": "#248F8F", "Rh": "#0A7D8C", "Pd": "#006985", "Ag": "#C0C0C0", "Cd": "#FFD98F", "In": "#A67573", "Sn": "#668080", "Sb": "#9E63B5", "Te": "#D47A00", "I": "#940094", "Xe": "#429EB0", "Cs": "#57178F", "Ba": "#00C900", "La": "#70D4FF", "Ce": "#FFFFC7", "Pr": "#D9FFC7", "Nd": "#C7FFC7", "Pm": "#A3FFC7", "Sm": "#8FFFC7", "Eu": "#61FFC7", "Gd": "#45FFC7", "Tb": "#30FFC7", "Dy": "#1FFFC7", "Ho": "#00FF9C", "Er": "#00E675", "Tm": "#00D452", "Yb": "#00BF38", "Lu": "#00AB24", "Hf": "#4DC2FF", "Ta": "#4DA6FF", "W": "#2194D6", "Re": "#267DAB", "Os": "#266696", "Ir": "#175487", "Pt": "#D0D0E0", "Au": "#FFD123", "Hg": "#B8B8D0", "Tl": "#A6544D", "Pb": "#575961", "Bi": "#9E4FB5", "Po": "#AB5C00", "At": "#754F45", "Rn": "#428296", "Fr": "#420066", "Ra": "#007D00", "Ac": "#70ABFA", "Th": "#00BAFF", "Pa": "#00A1FF", "U": "#008FFF", "Np": "#0080FF", "Pu": "#006BFF", "Am": "#545CF2", "Cm": "#785CE3", "Bk": "#8A4FE3", "Cf": "#A136D4", "Es": "#B31FD4", "Fm": "#B31FBA", "Md": "#B30DA6", "No": "#BD0D87", "Lr": "#C70066", "Rf": "#CC0059", "Db": "#D1004F", "Sg": "#D90045", "Bh": "#E00038", "Hs": "#E6002E", "Mt": "#EB0026" },

// NB starting from Bk the radii data are incorrect
Expand Down Expand Up @@ -30,7 +33,7 @@ namespace $ {
x: number,
y: number,
z: number,
},
} | null,
x: number,
y: number,
z: number,
Expand Down Expand Up @@ -60,19 +63,7 @@ namespace $ {
symlabel?: string,
},
overlayed: Record< string, string >,
atoms: {
fract: {
x: number,
y: number,
z: number,
} | null,
x: number,
y: number,
z: number,
c: string, //color
r: number, //radius
overlays: Record< string, string | number >,
}[],
atoms: $optimade_cifplayer_matinfio_internal_obj_atom[]
sg_name: string,
ng_name: number,
info: string,
Expand All @@ -82,6 +73,8 @@ namespace $ {

export class $optimade_cifplayer_matinfio extends $mol_object2 {

static pos_overlap_limit = 0.1

static log = this.$.$optimade_cifplayer_matinfio_log

/** Guessing what to do */
Expand Down
146 changes: 97 additions & 49 deletions matinfio/player/player.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,63 +37,98 @@ namespace $ {
mpds_data: crystal.mpds_data,
mpds_demo: crystal.mpds_demo
}
const pos2els: any = {}
const hashes: any = {}

const groups: { fpos: number[] | null, cpos: number[], atoms: $optimade_cifplayer_matinfio_internal_obj_atom[] }[] = []

// make atoms unique, i.e. remove collisions;
for( let i = 0; i < crystal.atoms.length; i++ ) {
const pos = [ crystal.atoms[ i ].x, crystal.atoms[ i ].y, crystal.atoms[ i ].z ]
const hash = pos.map( function( item ) { return item.toFixed( 2 ) } ).join( ',' )
// make atoms unique, i.e. remove collisions;
// makes special sense for partial occupancies
if( hashes.hasOwnProperty( hash ) ) {
var update = ""
for( let oprop in render.atoms[ hashes[ hash ] ].overlays ) {
const atom = crystal.atoms[ i ]

const pos = [ atom.x, atom.y, atom.z ]

// CIF has fractional positions
// OPTIMADE has cartesian positions
// POSCAR may have either of two
const fpos: number[] | null = crystal.cartesian
? cell_matrix ? math.divide( pos, cell_matrix ).map( fract_cord_norm ) : null
: pos.map( fract_cord_norm )

const cpos: number[] = fpos ? math.multiply( fpos, cell_matrix ) : pos

if( groups.some( group => {
if( is_overlap( cpos, group.cpos, $optimade_cifplayer_matinfio.pos_overlap_limit ) ) {

const AseRadii = $optimade_cifplayer_matinfio_chemical_elements.AseRadii[ atom.symbol ]
const pos = group.atoms.findIndex( atom2 => {
return AseRadii > $optimade_cifplayer_matinfio_chemical_elements.AseRadii[ atom2.symbol ]
} )

if( pos == -1 ) group.atoms.push( atom )
else group.atoms.splice( pos, 0, atom )

return true

}
} ) ) {
continue
}

groups.push( { fpos, cpos, atoms: [ atom ] } )
}

for( let i = 0; i < groups.length; i++ ) {

const { fpos, cpos, atoms } = groups[i]

const overlays: Record< string, string | number > = {
"S": atoms[0].symbol,
"N": i + 1,
}
for( let oprop in atoms[0].overlays ) {
overlays[ oprop ] = atoms[0].overlays[ oprop ]
}

atoms.slice(1).forEach( atom => {
for( let oprop in overlays ) {

if( oprop == 'S' ) {
if( pos2els[ hash ].indexOf( crystal.atoms[ i ].symbol ) == -1 ) {
update = " " + crystal.atoms[ i ].symbol
pos2els[ hash ].push( crystal.atoms[ i ].symbol )
if( atoms.every( a => a.symbol != atom.symbol ) ) {
overlays[ oprop ] += ' ' + atom.symbol
}

} else if( oprop == 'N' ) {
overlays[ oprop ] += ', ' + ( i + 1 )

} else if( oprop == '_atom_site_occupancy' ) {
overlays[ oprop ] += '+' + atom.overlays[ oprop ]

} else {
overlays[ oprop ] += ' ' + atom.overlays[ oprop ]
}
else if( oprop == 'N' )
update = ", " + ( i + 1 )
else if( oprop == '_atom_site_occupancy' )
update = "+" + crystal.atoms[ i ].overlays[ oprop ]
else
update = " " + crystal.atoms[ i ].overlays[ oprop ]

render.atoms[ hashes[ hash ] ].overlays[ oprop ] += update
}
} else {
const color = ($optimade_cifplayer_matinfio_chemical_elements.JmolColors as any)[ crystal.atoms[ i ].symbol ] || '#FFFF00'
const radius = ($optimade_cifplayer_matinfio_chemical_elements.AseRadii as any)[ crystal.atoms[ i ].symbol ] || 0.66

const overlays: Record< string, string | number > = {
"S": crystal.atoms[ i ].symbol,
"N": i + 1,
}
for( let oprop in crystal.atoms[ i ].overlays ) {
overlays[ oprop ] = crystal.atoms[ i ].overlays[ oprop ]

}
} )

// CIF has fractional positions
// OPTIMADE has cartesian positions
// POSCAR may have either of two
const cpos = crystal.cartesian ? pos : math.multiply( pos, cell_matrix )
const fpos = !crystal.cartesian ? pos : cell_matrix ? math.divide( pos, cell_matrix ) : null
const fract = fpos ? { 'x': fpos[ 0 ], 'y': fpos[ 1 ], 'z': fpos[ 2 ] } : null

render.atoms.push( {
'fract': fract,
'x': cpos[ 0 ],
'y': cpos[ 1 ],
'z': cpos[ 2 ],
'c': color,
'r': radius,
'overlays': overlays
} )
hashes[ hash ] = render.atoms.length - 1
pos2els[ hash ] = [ crystal.atoms[ i ].symbol ]
const color = $optimade_cifplayer_matinfio_chemical_elements.JmolColors[ atoms[0].symbol ] || '#FFFF00'
const radius = $optimade_cifplayer_matinfio_chemical_elements.AseRadii[ atoms[0].symbol ] || 0.66
const atom_result = {
fract: fpos ? {
x: fpos[ 0 ],
y: fpos[ 1 ],
z: fpos[ 2 ],
} : null,
x: cpos[ 0 ],
y: cpos[ 1 ],
z: cpos[ 2 ],
c: color,
r: radius,
overlays,
symbol: atoms[0].symbol,
label: atoms[0].label,
}

render.atoms.push( atom_result )

}

for( let oprop in crystal.atoms.at(-1)!.overlays ) {
Expand All @@ -102,5 +137,18 @@ namespace $ {

return render
}


function fract_cord_norm( cord: number ){
const res = cord % 1
return res > 0 ? res : res + 1
}

function is_overlap( pos1: number[], pos2: number[], threshold: number ) {
for( let i = 0; i < 3; i++ ) {
if ( pos1[i] < pos2[i] - threshold || pos1[i] > pos2[i] + threshold ) return false
}
return true
}

}
11 changes: 5 additions & 6 deletions matinfio/spacegroup/spacegroup.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ namespace $ {
const spans = symmetry.split( ',' )

const fract = {
x: fract_cord_norm( calc_symmetry_span( spans[ 0 ], atom.fract ) ),
y: fract_cord_norm( calc_symmetry_span( spans[ 1 ], atom.fract ) ),
z: fract_cord_norm( calc_symmetry_span( spans[ 2 ], atom.fract ) ),
x: fract_cord_norm( calc_symmetry_span( spans[ 0 ], atom.fract! ) ),
y: fract_cord_norm( calc_symmetry_span( spans[ 1 ], atom.fract! ) ),
z: fract_cord_norm( calc_symmetry_span( spans[ 2 ], atom.fract! ) ),
}

const [ x, y, z ] = math.multiply( [ fract.x, fract.y, fract.z ], cell )
Expand Down Expand Up @@ -96,9 +96,8 @@ namespace $ {
}

function fract_cord_norm( cord: number ){
let res = cord % 1
if( res < 0 ) res = res + 1
return res
const res = cord % 1
return res > 0 ? res : res + 1
}

}
2 changes: 1 addition & 1 deletion player/player.view.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ namespace $.$$ {
for (const name of next_symmetries) {

const atoms = this.symmetry_atoms( name )!
if( is_overlap( data, atoms, 0.01 ) ) {
if( is_overlap( data, atoms, $optimade_cifplayer_matinfio.pos_overlap_limit ) ) {
return
}
}
Expand Down

0 comments on commit 4dfe534

Please sign in to comment.