org.xmlcml.cml.tools.DisorderAssembly Maven / Gradle / Ivy
/**
* Copyright 2011 Peter Murray-Rust et. al.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xmlcml.cml.tools;
/**
* Disorder Assembly as defined in CIF.
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import nu.xom.Nodes;
import org.xmlcml.cml.base.CMLConstants;
import org.xmlcml.cml.element.CMLAtom;
import org.xmlcml.cml.element.CMLMolecule;
import org.xmlcml.cml.element.CMLScalar;
/** based on IUCr Core CIF dictionary
*
atom_site_disorder_assembly
_name _atom_site_disorder_assembly
_category atom_site
_type char
_list yes
_list_reference _atom_site_label
_example _detail
A disordered methyl assembly with groups 1 and 2
B disordered sites related by a mirror
S disordered sites independent of symmetry
_definition A code which identifies a cluster of atoms that show long-range
positional disorder but are locally ordered. Within each such
cluster of atoms, _atom_site_disorder_group is used to identify
the sites that are simultaneously occupied. This field is only
needed if there is more than one cluster of disordered atoms
showing independent local order.
*
* @see DisorderGroup
* Experiemntal.
*
* A disordered crysta; should have at least one DosrderAssembly. If
* this is not explicit in the file, all disordered atoms are in a
* single DisorderAssembly.
* Each DisorderAssembly should contain at least 2 DisorderGroups.
* Within a given DisorderGroup all the occupancies should be identical
* It is likely that the occupancies of the disorderGroups will sum to
* 1.0. The DisorderGroups may have different chemical constitutions
* (e.g. a CO2H might be partially replaced by a CONH2 group
*
* @author pmr
*
*/
public class DisorderAssembly implements CMLConstants {
private List groupList = null;
private Map groupMap = null;
private Set commonAtoms = null;
// atoms common to all sub groups
private String assemblyCode = "NO ATOMS ADDED YET";
/** constructor.
*/
public DisorderAssembly() {
groupMap = new HashMap();
commonAtoms = new HashSet();
}
/** atoms common to all parts of assembly.
*
* @return list of atoms
*/
public List getCommonAtoms() {
return new ArrayList(commonAtoms);
}
/** finds all atoms with child flags (scalar) indicating disorder, or those atoms
* with less than unit occupancy.
* no analysis is done
* @param molecule
* @return list of atoms flagged as disordered
*/
public static List getDisorderedAtoms(CMLMolecule molecule) {
if(molecule == null) {
throw new IllegalArgumentException("Molecule must not be null");
}
Nodes nodes = molecule.query(
".//"+CMLAtom.NS+"["+CMLScalar.NS+"[" +
"(@dictRef='"+CrystalTool.DISORDER_ASSEMBLY+"' and .!='.') or " +
"(@dictRef='"+CrystalTool.DISORDER_GROUP+"' and .!='.')" +
"]] | .//"+CMLAtom.NS+"[@occupancy[. < 1]]", CMLConstants.CML_XPATH);
List atomList = new ArrayList();
for (int i = 0; i < nodes.size(); i++) {
atomList.add((CMLAtom) nodes.get(i));
}
return atomList;
}
/** add atom to common atoms.
*
* @param atom
*/
public void addCommonAtom(CMLAtom atom) {
if (commonAtoms.contains(atom)) {
throw new RuntimeException("atom is already common to assembly "+
CrystalTool.getFullLabel(atom));
}
commonAtoms.add(atom);
}
/** get list of disorderAssemblys. Throws an exception if it comes across disorder
* which doesn't comply with the CIF specification.
*
* @param disorderedAtomList atoms to use
* @return list of assemblies (or empty list)
*/
public static List getDisorderedAssemblyList
(List disorderedAtomList) {
List assemblyList = new ArrayList();
Map assemblyMap = new HashMap();
for (CMLAtom atom : disorderedAtomList) {
String assemblyCode = DisorderAssembly.getAtomCode(atom);
if (assemblyCode == null) {
assemblyCode = CMLConstants.S_PERIOD;
}
DisorderAssembly assembly = assemblyMap.get(assemblyCode);
if (assembly == null) {
assembly = new DisorderAssembly();
assemblyMap.put(assemblyCode, assembly);
assemblyList.add(assembly);
}
assembly.addAtom(atom);
}
return assemblyList;
}
/** gets disorder_assembly code.
*
* @see CrystalTool#isIndeterminate(String)
* @param atom with child disorder flags
* @return code or null if indterminate
*/
public static String getAtomCode(CMLAtom atom) {
String atomCode = CrystalTool.getValue(atom,
CMLScalar.NS+"[@dictRef='"+CrystalTool.DISORDER_ASSEMBLY+"']");
return (atomCode != null) ? atomCode : ".";
}
/** gets assembly code
* @return assembly code
*/
public String getAssemblyCode() {
return assemblyCode;
}
/** add atom.
* no checking at present
* @param atom
*/
public void addAtom(CMLAtom atom) {
String groupCode = DisorderGroup.getAtomCode(atom);
String assCode = DisorderAssembly.getAtomCode(atom);
if (groupCode == null) {
groupCode = CMLConstants.S_PERIOD;
}
if (assCode == null) {
assCode = CMLConstants.S_PERIOD;
addCommonAtom(atom);
} else {
assemblyCode = assCode;
if (S_PERIOD.equals(groupCode)) {
this.addCommonAtom(atom);
} else {
DisorderGroup group = groupMap.get(groupCode);
if (group == null) {
group = new DisorderGroup(this);
groupMap.put(groupCode, group);
}
group.addAtom(atom);
}
}
}
/** get the disorderGroups sorted by occupancy.
*
* @return the list
*/
public List getDisorderGroupList() {
if (groupList == null) {
groupList = new ArrayList();
for (String s : groupMap.keySet()) {
groupList.add(groupMap.get(s));
}
}
Collections.sort(groupList);
return groupList;
}
/** remove all minor groups.
* only the group with largets occupancy is retained
*/
public void removeMinorDisorder() {
getDisorderGroupList();
Collections.sort(groupList);
for (int i = 0; i < groupList.size()-1; i++) {
groupList.get(i).detachAtoms();
}
}
/** string representation.
* @return string
*/
public String toString() {
String s = "disorderAssembly: "+assemblyCode+S_NEWLINE;
s += "common atoms: "+S_NEWLINE;
for (CMLAtom commonAtom : commonAtoms) {
s += CMLConstants.S_SPACE+S_SPACE+CrystalTool.getFullLabel(commonAtom)+S_NEWLINE;
}
s += "disorderGroups: "+S_NEWLINE;
for (String groupName : groupMap.keySet()) {
s += groupMap.get(groupName);
}
return s;
}
};
© 2015 - 2025 Weber Informatics LLC | Privacy Policy