1 /*
2  *  (c) 2004-2008 Iowa State University
3  *      see the LICENSE file in the top level directory
4  */
5 
6 /* MoleculeData.h
7 
8 	class MoleculeData organizes data on the molecule involved in each window/file.
9 
10 	Created from other files, BMB, 4/1998
11 */
12 
13 #ifndef __MoleculeData__
14 #define __MoleculeData__
15 #ifndef __MyTypes__
16 #include "MyTypes.h"
17 #endif
18 
19 typedef class AtomTypeList AtomTypeList;
20 typedef class WindowData WindowData;
21 typedef class MolDisplayWin MolDisplayWin;
22 
23 /**
24  * The main data container for Molecule information.
25  * This class encapsulates all of the chemical information for a file including
26  * basis set, geometries, GAMESS options, etc.
27  */
28 class MoleculeData {
29 		friend class MolDisplayWin;
30 		friend class CoordWin;
31 		friend class EnergyPlotDialog;
32 		friend class FrequenciesDialog;
33 		friend class Surf2DBase;
34 		friend class Surf3DBase;
35 		friend class MpGLCanvas;
36 		friend class FrameSnapShot;
37 		friend class DataGroup;
38 	private:
39 		std::vector<Annotation *> Annotations;	///< Set of annotations
40 		int constrain_anno_id;
41 		CPoint3D	*RotCoords;				///< The currently displayed, rotated coordinates in 2D mode
42 		Frame *		cFrame;					///< pointer to the currently drawn frame
43 		Frame *		Frames;					///< pointer to the first frame
44 		Internals *	IntCoords;				///< The set of internal coordinate definitions
45 		BasisSet *	Basis;					///< The full basis set used in a computation
46 
47 		/** efrags is a hash from fragment name to a structure containing
48 		 * fragment text and parsed coordinates.  There's only one entry for
49 		 * each different fragment type.  FragmentNames is used to map fragment
50 		 * instances to their fragment type.  There's one entry per instance of
51 		 * each fragment type.  Use an atom's fragment number to index into
52 		 * FragmentNames, and use the string there to index into efrags.
53 		 */
54 		std::map<std::string, EFrag> efrags;
55 		std::vector<std::string> FragmentNames;	///< Effective Fragment name for each fragment (FRAGNAME)
56 		std::vector<long> FMOFragmentIds;	///< Vector containing the FMO fragment mapping for each atom
57 
58 		char *		Description;			///< Simple one line label
59 		long		CurrentFrame;			///< Number of the current frame
60 		long		NumFrames;				///< Current number of Frames
61 		long		MaxAtoms;				///< The maximum number of atoms in any frame
62 		float		MaxSize;				///< The maximum side length of any frame
63 		float		WindowSize;				///< The Window size in the molecule coordinate space (ie � or Bohrs) user adjustable to change the window scaling
64 		Matrix4D	TotalRotation;			///< Rotation matrix for displaying the molecule
65 		CPoint3D    Centroid;
66 		CPoint3D    MolCentroid;
67 		InputData *	InputOptions;			///< GAMESS run configuration information
68 
69 		/** Flag for normal mode display & MO display
70 		 *	bit 1 for showing normal modes
71 		 *	bit 2 for showing special atoms
72 		 *	4 & 5 are obsolete, 6 indicates 2D plane display
73 		 *	bit 7 for showing the axis's
74 		 *	bit 4 for plotting KE rather than Total E
75 		 *	bit 5 for plotting PE
76 		 */
77 		char		DrawMode;
78 		char		DrawLabels;				///< Flag for label drawing (both #'s and atomic labels) bit3 deactivates labeling H atoms
79 	public:
80 		MolDisplayWin *MolWin;
81 		MoleculeData(MolDisplayWin *MolWin);
82 		~MoleculeData(void);
83 		long ReadInitialFragmentCoords(BufferFile * Buffer);
84 		void ReadFragmentCoordinates(BufferFile * Buffer, long NumFragmentAtoms);
85 		void ParseMOPACZMatrix(BufferFile * Buffer, const long & nAtoms, WinPrefs * Prefs);
86 		void ParseZMatrix(BufferFile * Buffer, const long & nAtoms, WinPrefs * Prefs);
87 		void ParseGAMESSUKZMatrix(BufferFile * Buffer, WinPrefs * Prefs);
88 #ifndef __wxBuild__
89 		void ConvertMainWinData1(BufferFile *Buffer, long size);
90 		void ConvertMainWinData14(BufferFile * Buffer, long length);
91 		long UnPackOldData(BufferFile *Buffer);
92 		long UnPackData(BufferFile * Buffer);
93 		void ReadMORec10(BufferFile * Buffer, long length);
94 		long ReadMORec48(BufferFile *Buffer, const long & NumBasisFuncs, const long & ByteCount);
95 #endif
96 		void ReadRunInfoRec(BufferFile *Buffer, long length);
97 		void ReadRunTitle(BufferFile *Buffer, long length);
98 		void ReadBasisOptions(BufferFile * Buffer);
99 		void ReadControlOptions(BufferFile * Buffer);
100 		long ParseTinkerCoordinates(BufferFile * Buffer);
101 		long WriteCMLFile(BufferFile * Buffer, WinPrefs * Prefs, WindowData * wData, bool allFrames, bool AllData);
102 		/**
103 		 * Parse CML text in the provided buffer
104 		 * @param Buffer The buffer containing the CML text
105 		 * @param Prefs The window preferences
106 		 * @param wData The extra window data (sizes, etc)
107 		 * @param p A progress indicator in case the operation takes too much time
108 		 * @param readPrefs Should window preferences be read from the CML text (if present)
109 		 * @param UseAutoBond Should the SetBonds routine be called on each frame
110 		 */
111 		long OpenCMLFile(BufferFile * Buffer, WinPrefs * Prefs, WindowData * wData, Progress * p, bool readPrefs, bool UseAutoBond=true);
GetMoleculeSize(void)112 		inline float GetMoleculeSize(void) {return WindowSize;};
SetMoleculeSize(float newVal)113 		inline void SetMoleculeSize(float newVal) {if (newVal > 0.0) WindowSize = newVal;};
114 		void GetModelCenter(CPoint3D * center);
115 		void SetModelCenter(CPoint3D * center);
116 		void GetModelRotation(float * Psi, float * Phi, float * Theta);
117 		void SetModelRotation(float Psi, float Phi, float Theta);
118 	//	inline Boolean GetFrameMode(void) {return (DrawMode & (1<<3));};
119 		AtomTypeList * GetAtomTypes(void);
120 		bool SurfaceExportPossible(void);
121 		void ParseGAMESSBasisSet(BufferFile * Buffer);
122 		long ParseECPotentials(BufferFile * Buffer);
123 		/**
124 		 * Parse the INDAT array of fragment ids for FMO.
125 		 @param Buffer the file buffer stream
126 		 @param NumAtoms target atom number
127 		 @param EndOfGroup the file position to use as a limit for the parsing
128 		 */
129 		bool ParseFMOIds(BufferFile * Buffer, const long & NumAtoms, const wxFileOffset & EndOfGroup);
130 		/**
131 		 * Write the FMO array to XML
132 		 * @param parent The enclosing XML element
133 		 */
134 		void WriteFMOIdsToXML(XMLElement * parent);
135 		/**
136 		 * Read the FMO Id array from XML
137 		 * @param item XML element
138 		 */
139 		void ReadFMOIdsFromXML(XMLElement * item);
140 		/**
141 		 * Write the INDAT array of fragment ids for FMO out to the buffer in the input file format.
142 		 @param Buffer the file buffer stream
143 		 */
144 		void WriteINDAT(BufferFile * Buffer);
GetBasisSet(void)145 		inline BasisSet * GetBasisSet(void) const {return Basis;};
146 		long GetNumBasisFunctions(void) const;
GetNumFrames(void)147 		inline long GetNumFrames(void) {return NumFrames;};
148 		/**
149 		 * Does the current data include enough information to plot an orbital?
150 		 */
151 		bool OrbSurfacePossible(void) const;
152 		/**
153 		 * Determine whether it is possible to compute a total electron density with the
154 		 * current data. This requires having a set of orbitals with a known occupation.
155 		 */
156 		bool TotalDensityPossible(void) const;
157 		/**
158 		 * Determine whether it is possible to compute a molecular electrostatic potential with the
159 		 * current data. This requires having a set of orbitals with a known occupation and knowing
160 		 * the nuclear charge for each atom (potentially not known for ECP/MCPs).
161 		 */
162 		bool MEPCalculationPossible(void) const;
163 		void ResetRotation(void);
164 		void CenterModelWindow(void);
165 		void InvertMode(void);
166 		void UnitConversion(bool AngToBohr);
167 		void FlipRotation(short theItem);
168 		/**
169 		 * Rotate/translate the reference coordinates into the principle orientation.
170 		 * @param Prefs The current window preferences
171 		 * @param precision The tolerance for slop in the coordinates (ex 1.0D-5)
172 		 */
173 		void RotateToPrincipleOrientation(WinPrefs * Prefs, double precision=1.0E-4);
174 		/**
175 		 * Determine the set of point groups satisfied by the current set of coordinates.
176 		 * @param pgFlags One flag per point group indicating whether the coordinates satisfy the point group.
177 		 * @param Prefs The current window preferences
178 		 * @param tolerance how tight should the operator tolerances be
179 		 */
180 		void DeterminePointGroup(bool * pgFlags, WinPrefs * Prefs, double tolerance);
181 		/**
182 		 * Compute the principle orientation of the current set of coordinates.
183 		 * The return value indicates whether the current coordinates satisfy the current point group.
184 		 * @param result The rotation/translation to convert the coordinates to the princ. orientation.
185 		 * @param translation vector translating the molecule such that the center of mass is at the origin.
186 		 * @param Prefs The current window preferences
187 		 * @param precision The tolerance for slop in the coordinates (ex 1.0D-5)
188 		 */
189 		bool DeterminePrincipleOrientation(Matrix4D result, CPoint3D& translation, WinPrefs * Prefs, double precision) const;
190 		void GenerateSymmetryDependentAtoms(bool do_warnings = true);
191 		/**
192 		 * Flag the symmetry unique atoms.
193 		 * The coordinates are left unchanged, just the symmetry unique flag on the atoms
194 		 * may be changed. A failure in the result would indicate a problem with the coordinates
195 		 * or that the point group is not corrent.
196 		 * @param tolerance The maximum distance between atoms that will be considered a match.
197 		 */
198 		bool GenerateSymmetryUniqueAtoms(double tolerance);
199 		/**
200 		 * Cleanup the coordinates to more tightly match the selected point group.
201 		 * The routine assumes the symmetry unique atoms are already correctly marked.
202 		 * This routine should not add or remove atoms, but will change the positions slightly.
203 		 */
204 		void SymmetrizeCoordinates(bool selected_only = false);
205 		bool SetScreenPlane(CPoint3D *Points);
206 		void LinearLeastSquaresFit(Progress * lProgress);
207 		void CreateLLM(long NumPts, WinPrefs * Prefs);
208 		void CreateInternalLLM(long NumPts, WinPrefs * Prefs);
209 // routines to get/set the current/active frame
210 		/// Return the index of the active frame.
GetCurrentFrame(void)211 		inline long GetCurrentFrame(void) {return CurrentFrame;};
212 		/// Return a pointer to the active frame.
GetCurrentFramePtr(void)213 		inline Frame* GetCurrentFramePtr(void) {return cFrame;};
214 		/// Return a pointer to the first frame in a series.
GetFirstFrame(void)215 		inline Frame * GetFirstFrame(void) {return Frames;};
216 		/// Increment the frame to the next one
217 		void AdvanceFrame(void);
218 		/**
219 		 * Change the active frame to the one indexed by FrameNum. If the index is invalid the call does nothing.
220 		 * @param FrameNum the index of the desired Frame.
221 		 */
222 		void SetCurrentFrame(long FrameNum);
223 // routines to add/delete a frame or increase the memory allocations
224 		/** Add a new frame to the list after the current/active frame. Preallocate memory for the specified number of
225 		 * atoms and bonds. A pointer to the new frame is returned and also becomes the active frame.
226 		 * @param NumAtoms Desired length of the Atom array
227 		 * @param NumBonds Desired length of the Bonds array
228 		 */
229 		Frame * AddFrame(long NumAtoms, long NumBonds);
230 		/** Add a new frame to the series ordered based on the provided XPosition. If successful, a pointer to the
231 		 * new frame is returned and the new frame becomes the active frame. The call will fail if there is an
232 		 * existing frame with the same XPosition value in which case the returned value will be NULL and the
233 		 * state unchanged.
234 		 * @param XPosition A value ordering the new frame in the existing series.
235 		 */
236 		Frame * LocateNewFrame(float XPosition);
237 		/** Delete the current/active frame. The next frame will become the active frame, if deleting the last
238 		 * frame, the previous frame will become active. If there is only one frame nothing is changed.
239 		 */
240 		void DeleteFrame(void);
241 		/** Change the memory allocation for the atoms and bonds. Any existing data is preservered so you can't
242 		 * set the allocation smaller than what is currently in use. Returns false if memory allocation fails.
243 		 * @param NumAtoms Desired length of the Atom array
244 		 * @param NumBonds Desired length of the Bonds array
245 		 */
246 		bool SetupFrameMemory(long NumAtoms, long NumBonds);
247 
DrawHLabels(void)248 		inline bool DrawHLabels(void) const {return ((DrawLabels & 4) == 0);};
SetHLabelMode(bool State)249 		inline void SetHLabelMode(bool State) {DrawLabels = (DrawLabels & 0xFB) + (State ? 0: 4);};
250 		bool ModeVisible(void) const;
251 		void SetDescription(char * NewLabel);
SetSpecialAtomDrawMode(bool State)252 		inline bool SetSpecialAtomDrawMode(bool State) {if (DrawMode&2) DrawMode-=2; if (State) DrawMode+=2; return State;};
GetSpecialAtomDrawMode(void)253 		inline bool GetSpecialAtomDrawMode(void) const {return ((DrawMode & 2)!=0);};
SetDrawMode(bool State)254 		inline bool SetDrawMode(bool State) {if (DrawMode&1) DrawMode--; if (State) DrawMode++; return State;};
GetDrawMode(void)255 		inline bool GetDrawMode(void) const {return (DrawMode & 1);};
ShowAxis(void)256 		inline bool ShowAxis(void) const {return ((DrawMode & 0x40) != 0);};
SetShowAxis(bool newState)257 		inline void SetShowAxis(bool newState) {DrawMode = (DrawMode & 0xBF) + (newState ? 0x40 : 0);};
258 		long GetNumBonds(void) const;
259 		long GetNumElectrons(void) const;
260 		short GetMultiplicity(void) const;
GetMaximumAtomCount(void)261 		inline long GetMaximumAtomCount(void) const {return MaxAtoms;};
262 		/** Output a GAMESS input file after prompting the user for the name of the output file.
263 		 * @param owner The main document window
264 		 */
265 		void WriteInputFile(MolDisplayWin * owner);
266 		/** Output a GAMESS input file to a temporary file and open a window to allowing editing of that file.
267 		 * The user can then save to a file name of their choice or discard.
268 		 * The data in this window is independent of the originating document when this call returns.
269 		 * @param owner The main document window
270 		 */
271 		void WriteEditInputFile(MolDisplayWin * owner);
272 		InputData * GetInputData(void);
273 		InputData * SetInputData(InputData * NewData);
274 		/**
275 		 * Add a new atom with type AtomType and located at Position
276 		 * @param AtomType The type of the new atom
277 		 * @param Position x,y,z coordinates for the new atom
278 		 * @param updateGlobal Update the global arrays and structures (needed at some point)
279 		 * @param index Insert the atom in the atom list at the specified index (-1 for the end)
280 		 */
281 		void NewAtom(long AtomType, const CPoint3D & Position, bool updateGlobal=true, long index=-1);
282 		/**
283 		 * Add a new atom as a copy of atom
284 		 * @param atom The atom to copy
285 		 * @param updateGlobal Update the global arrays and structures (needed at some point)
286 		 * @param index Insert the atom in the atom list at the specified index (-1 for the end)
287 		 * @param pos Optionally set the position of the new atom to pos.
288 		 */
289 		void NewAtom(const mpAtom& atom, bool updateGlobal=true, long index=-1, const CPoint3D *pos = NULL);
290 		/**
291 		 * Updates internal data structures to make sure they are consistent with the current atom count.
292 		 */
293 		void AtomAdded(void);
294 		/**
295 			Make the current rotated view the reference orientation.
296 		 */
297 		void StickCoordinates(void);
298 		void InitializeInternals(void);
299 		/**
300 			Accessor for the internal coordinates class.
301 		 */
GetInternalCoordinates(void)302 		inline Internals * GetInternalCoordinates(void) const {return IntCoords;};
303 		/**
304 			Delete an atom.
305 			The return value is the index of the next atom in the list. This routine may remove
306 			more than one atom. For example in the case of effective fragments the entire fragment
307 			must be removed.
308 			@param AtomNum The index of the atom to delete.
309 			@param allFrames If true the atom with the same index will be removed from all frames.
310 		 */
311 		long DeleteAtom(long AtomNum, bool allFrames=false);
312 		/**
313 			Reorders the atom list.
314 			@param index1 The initial index of the atom
315 			@param index2 The final index of the atom
316 		 */
317 		void ReorderAtomList(long index1, long index2);
318 		/**
319 			Is the provided atom index valid for the current frame?
320 			@param AtomNum The atom index to test
321 		 */
322 		bool ValidAtom(long AtomNum);
323 		/**
324 			Returns the FRAGNAME for the indicated effective fragment.
325 			@param index The index of the fragment.
326 		 */
327 		const char * GetFragmentName(unsigned long index) const;
328 		void PruneUnusedFragments();
329 		void GetRotationMatrix(Matrix4D copy);
330 		const Matrix4D& GetRotationMatrix() const;
GetAnnotationCount(void)331 		int GetAnnotationCount(void) const {return Annotations.size();};
332 		void DeleteAllAnnotations(void);
ConstrainToAnnotation(int anno_id)333 		void ConstrainToAnnotation(int anno_id) {
334 			constrain_anno_id = anno_id;
335 		}
GetConstrainAnnotation(void)336 		int GetConstrainAnnotation(void) {
337 			return constrain_anno_id;
338 		}
RemoveAnnotationConstraint(void)339 		void RemoveAnnotationConstraint(void) { constrain_anno_id = -1; }
340 		void ExportPOV(BufferFile *Buffer, WinPrefs *Prefs);
341 		/**
342 		 Create an FMO fragment list
343 		 @param NumMolecules The number of non-bonded molecules to group together in the same FMO fragment
344 		 @param newFragmentation The resulting fragmentation vector
345 		 */
346 		long CreateFMOFragmentation(const int & NumMolecules, std::vector<long> & newFragmentation);
347 		/**
348 		 Returns the FMO fragment number for the selected atom
349 		 @param AtomId the index of the desired atom
350 		 */
351 		long GetFMOFragmentId(const long & AtomId) const;
352 		/**
353 		 Set the FragmentId for atom index AtomId. This routine will initialize the fragment id
354 		 array if it is empty.
355 		 @param AtomId index of the atom to target
356 		 @param FragmentId the new fragment id for the targeted atom
357 		 */
358 		void SetFMOFragmentId(const long & AtomId, const long & FragmentId);
359 		/// Test to see if the gradient vector is available which would allow displaying that vector
360 		bool GradientVectorAvailable(void) const;
361 };
362 
363 #endif
364