1 /*
2  *  (c) 2006 Iowa State University
3  *      see the LICENSE file in the top level directory
4  */
5 
6 /* Routines to manage the open/save file interfaces
7 
8 	Created by Brett Bode 3/2006
9 */
10 
11 #include "Globals.h"
12 #include "GlobalExceptions.h"
13 #include "Progress.h"
14 #include "MoleculeData.h"
15 #include "MolDisplayWin.h"
16 #include "BFiles.h"
17 #include "myFiles.h"
18 #include "InputData.h"
19 #include "inputfileeditor.h"
20 #include "Prefs.h"
21 #include "exportoptionsdialog.h"
22 #include "energyplotdialog.h"
23 #include <wx/wfstream.h>
24 #include <wx/anidecod.h>
25 #include <wx/filename.h>
26 
27 extern WinPrefs *	gPreferences;
28 
29 	//Prompt for a filename and then write out a valid input file for GAMESS
WriteInputFile(MoleculeData * lData,MolDisplayWin * owner)30 long InputData::WriteInputFile(MoleculeData * lData, MolDisplayWin * owner) {
31 
32     wxString filePath = wxFileSelector(wxT("Save As"), wxT(""), wxT(""), wxT(""),
33                               wxT("GAMESS input files (*.inp)|*.inp"),
34 #if wxCHECK_VERSION(2,9,0)
35                               wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
36 #else
37                               wxSAVE | wxOVERWRITE_PROMPT,
38 #endif
39 							  owner);
40 
41     if(!filePath.IsEmpty()) {
42 		return WriteInputFile(filePath, lData, owner);
43 	}
44 	return -1;
45 }
46 
47 //Output the GAMESS input file to a temp file, then open a text editor for the user.
WriteEditInputFile(MoleculeData * lData,MolDisplayWin * owner)48 long InputData::WriteEditInputFile(MoleculeData * lData, MolDisplayWin * owner) {
49 	wxFile * t=NULL;
50 	wxString tempfile = wxFileName::CreateTempFileName(wxString(_("MacMolPlt_temp_")), t);
51 
52 	if(!tempfile.IsEmpty()) {
53 		long result = WriteInputFile(tempfile, lData, owner);
54 		InputFileEditor * leditor = new InputFileEditor(owner);
55 		if (leditor) {
56 			leditor->LoadFile(tempfile);
57 			leditor->Layout();
58 			leditor->Show();
59 		}
60 		return result;
61 	}
62 	return -1;
63 }
64 
WriteInputFile(const wxString & filePath,MoleculeData * lData,MolDisplayWin * owner)65 long InputData::WriteInputFile(const wxString &filePath, MoleculeData * lData, MolDisplayWin * owner) {
66 
67     FILE *currFile = NULL;
68     BufferFile *buffer = NULL;
69 
70     if((currFile = fopen(filePath.mb_str(wxConvUTF8), "wb")) == NULL) {
71         MessageAlert("Unable to open the file for output.");
72         return 0;
73     }
74     try {
75 		lData->PruneUnusedFragments();
76         buffer = new BufferFile(currFile, true);
77 		long BasisTest=0;
78 		buffer->WriteLine("!   File created by MacMolPlt " wxMacMolPlt_VERSION, true);
79 		if (Control) Control->WriteToFile(buffer, this, lData->GetNumElectrons());
80 		DFT.WriteToFile(buffer, this);
81 		if (System) System->WriteToFile(buffer);
82 		if (Basis && (Control->GetRunType() != G3MP2)) BasisTest = Basis->WriteToFile(buffer, lData);
83 		if (Guess) Guess->WriteToFile(buffer, this, lData);
84 		if (SCF) SCF->WriteToFile(buffer, this);
85 		if (MP2) MP2->WriteToFile(buffer, this);
86 		if (StatPt) StatPt->WriteToFile(buffer, this);
87 		if (Hessian) Hessian->WriteToFile(buffer, this);
88 		FMO.WriteToFile(buffer, lData);
89 		if (Data) Data->WriteToFile(buffer, lData, owner->GetPrefs(), BasisTest);
90 		if (Guess) Guess->WriteVecGroup(buffer, lData);
91     }
92     catch (MemoryError) {
93         MessageAlert("Not enough memory to open the file for writing.");
94     }
95 	if(buffer) {
96 		delete buffer;
97 	}
98 	fclose(currFile);
99 	return 1;
100 }
101 
102 	//Prompt for the dat file name and return a buffer to it
OpenDatFile(void)103 BufferFile * OpenDatFile(void) {
104 	BufferFile * Buffer = NULL;
105 
106     wxString filename = wxFileSelector(wxT("Choose a GAMESS .DAT file corresponding to this log file."));
107     if (!filename.empty()) {
108         FILE * myfile = fopen(filename.mb_str(wxConvUTF8), "rb");
109         if (myfile == NULL) {
110             MessageAlert("Unable to open the selected file!");
111         } else {
112 			Buffer = new BufferFile(myfile, false);
113 		}
114 	}
115 
116 	return Buffer;
117 }
118 
119 #if wxCHECK_VERSION(2,9,0)
120 #include <wx/quantize.h>
121 
WriteGIFMovie(wxString & filepath,ExportOptionsDialog * dlg)122 void MolDisplayWin::WriteGIFMovie(wxString & filepath, ExportOptionsDialog * dlg) {
123 	wxImageArray images;
124 	long AnimateTime = 10*Prefs->GetAnimateTime();
125 	bool killEPlotWin=false, includeEP = false;
126 	int savedEPlotWidth, savedEPlotHeight;
127 	wxBitmap  *bmp=NULL, *ePlotbmp=NULL;
128 	wxMemoryDC memDC, ePlotmemDC;
129 	long saveFrame = MainData->GetCurrentFrame();
130 
131 	try {
132 		ProgressInd = new Progress;
133 		if (!ProgressInd) throw MemoryError();
134 		ProgressInd->ChangeText("Creating Animated GIF... Patience...");
135 			//Setup a memory draw context to buffer each image at the full resolution
136 		bmp = new wxBitmap(dlg->getWidth(),
137 						   dlg->getHeight());
138 		memDC.SelectObject(*bmp);
139 			//Set the line width appropriate to the resolution (reset at the end)
140 		Prefs->SetLineWidth(dlg->getImageRatio());
141 
142 		if (dlg->GetMovieChoice() == 0) {	//Multi-frame animation
143 			ProgressInd->SetScaleFactor(100.0f / MainData->NumFrames);
144 			includeEP = dlg->AddEnergyPlot();
145 
146 			if(includeEP) {	//Add the energy plot to the movie
147 				if(!energyPlotWindow) {	//If the energy plot window is not open, temporarily open it
148 					energyPlotWindow = new EnergyPlotDialog(this);
149 					killEPlotWin = true;
150 				}
151 				else {
152 					energyPlotWindow->GetSize(&savedEPlotWidth, &savedEPlotHeight);
153 				}
154 				energyPlotWindow->SetSize(dlg->getHeight(), dlg->getHeight());
155 				energyPlotWindow->Show(true);
156 				energyPlotWindow->Update();
157 				//Setup a draw context for the extended image size including the energy plot
158 				ePlotbmp = new wxBitmap(dlg->getWidth()+dlg->getHeight(),
159 										dlg->getHeight());
160 				ePlotmemDC.SelectObject(*ePlotbmp);
161 			}
162 
163 			for(int i = 1; i <= MainData->NumFrames; ++i) {
164 				if(!ProgressInd->UpdateProgress((float)i)) {
165 					throw UserCancel();
166 				}
167 
168 				MainData->SetCurrentFrame(i);
169 
170 				Surface *temp = MainData->cFrame->SurfaceList;
171 				while(temp) {
172 					temp->RotateEvent(MainData);
173 					temp = temp->GetNextSurface();
174 				}
175 				MainData->ResetRotation();
176 				ReleaseLists();
177 				DrawGL();
178 					//Generate the possibly hi-res image
179 				glCanvas->GenerateHiResImageForExport(&memDC);
180 				wxImage frame;
181 
182 				if(dlg->AddEnergyPlot()) {
183 						//update the energy plot, copy it, then copy both bitmaps to the extended buffer
184 					energyPlotWindow->FrameChanged();
185 					wxBitmap *epBitmap = NULL;
186 					energyPlotWindow->CopyToBitMap(&epBitmap);
187 					if(epBitmap == NULL) {
188 						wxLogMessage(_("Error! Unable to copy energy plot. Aborted!"));
189 						throw UserCancel();
190 					}
191 					ePlotmemDC.Clear();
192 					ePlotmemDC.DrawBitmap(*bmp, 0, 0);
193 					ePlotmemDC.DrawBitmap(*epBitmap, dlg->getWidth(), 0);
194 					//finally create the image off of the extended bitmap.
195 					frame = ePlotbmp->ConvertToImage();
196 					delete epBitmap;
197 				} else	// or standard bitmap
198 					frame = bmp->ConvertToImage();
199 					//GIFs require this step to reduce the colors
200 				wxQuantize::Quantize(frame, frame);
201 				if (frame.HasAlpha()) {
202 					frame.ConvertAlphaToMask();
203 				}
204 				images.push_back(frame);
205 			}
206 		} else { //normal mode movie
207 			bool savedrawmode=false;
208 			long AnimateTime = 10*Prefs->GetAnimateTime();
209 			if(!MainData->cFrame->Vibs) {
210 				wxLogMessage(_("Error! No normal modes found when trying to create a normal mode animation. Aborted!"));
211 				throw UserCancel();
212 			}
213 			Frame * lFrame = MainData->cFrame;
214 
215 			long cmode = (lFrame->NumAtoms) * (lFrame->Vibs->CurrentMode);
216 			long AnimationSpeed = Prefs->GetAnimationSpeed();
217 			float offsetFactor = 1.0f/(4.5f*AnimationSpeed);
218 			float VectorScale = Prefs->GetVectorScale();
219 			CPoint3D *ModeOffset = new CPoint3D[lFrame->NumAtoms];
220 			if(!ModeOffset) {
221 				wxLogMessage(_("Unable to allocate memory for ModeOffset. Aborted!"));
222 				throw UserCancel();
223 			}
224 			CPoint3D *SavedAtoms = new CPoint3D[lFrame->NumAtoms];
225 			if(!SavedAtoms) {
226 				wxLogMessage(_("Unable to allocate memory for SavedAtoms. Aborted!"));
227 				delete[] ModeOffset;
228 				throw UserCancel();
229 			}
230 			if (MainData->GetDrawMode()) {
231 				savedrawmode=true;
232 				if(!Prefs->GetAnimateMode()) MainData->SetDrawMode(false);
233 			}
234 
235 			mpAtom *lAtoms = lFrame->Atoms;
236 			long iatm;
237 			for(iatm = 0; iatm < (lFrame->NumAtoms); ++iatm) {
238 				SavedAtoms[iatm] = lAtoms[iatm].Position;
239 				ModeOffset[iatm] = lFrame->Vibs->NormMode[iatm + cmode];
240 				ModeOffset[iatm] *= VectorScale;
241 			}
242 			MainData->ResetRotation();
243 			ReleaseLists();
244 			DrawGL();
245 
246 			if(AnimateTime < 1) AnimateTime = 1;
247 
248 			long npoint = 0;
249 			long inc = 1;
250 
251 			ProgressInd->SetScaleFactor(100.0f / (float)(4 * AnimationSpeed));
252 
253 			for(long i = 0; i < (4 * AnimationSpeed); i++) {
254 				if(!ProgressInd->UpdateProgress((float)i)) {
255 					for (iatm=0; iatm<(lFrame->NumAtoms); iatm++) {
256 						lAtoms[iatm].Position = SavedAtoms[iatm];
257 					}
258 					MainData->ResetRotation();
259 
260 					MainData->SetDrawMode(savedrawmode);
261 					ReleaseLists();
262 					DrawGL();
263 
264 					delete [] ModeOffset;
265 					delete [] SavedAtoms;
266 
267 					throw UserCancel();
268 				}
269 				if((npoint == AnimationSpeed) || (npoint == -AnimationSpeed)) {
270 					inc *= -1;
271 					offsetFactor *= -1.0;
272 				}
273 				npoint += inc;
274 
275 				glCanvas->GenerateHiResImageForExport(&memDC);
276 				wxImage frame = bmp->ConvertToImage();
277 				wxQuantize::Quantize(frame, frame);
278 				if (frame.HasAlpha()) {
279 					frame.ConvertAlphaToMask();
280 				}
281 
282 				images.push_back(frame);
283 
284 				for (iatm=0; iatm<(lFrame->NumAtoms); iatm++) {
285 					lAtoms[iatm].Position.x += offsetFactor * (ModeOffset[iatm].x);
286 					lAtoms[iatm].Position.y += offsetFactor * (ModeOffset[iatm].y);
287 					lAtoms[iatm].Position.z += offsetFactor * (ModeOffset[iatm].z);
288 				}
289 
290 				MainData->ResetRotation();
291 				ReleaseLists();
292 				DrawGL();
293 			}
294 
295 			for (iatm=0; iatm<(lFrame->NumAtoms); iatm++) {
296 				lAtoms[iatm].Position = SavedAtoms[iatm];
297 			}
298 			MainData->ResetRotation();
299 
300 			MainData->SetDrawMode(savedrawmode);
301 			ReleaseLists();
302 			DrawGL();
303 
304 			delete [] ModeOffset;
305 			delete [] SavedAtoms;
306 		}
307 
308 		//Series of frames is complete, now save to the requested file.
309 		if(!filepath.Lower().Matches(wxT("*.gif"))) {
310 
311 			filepath.Append(wxT(".gif"));
312 		}
313 		wxFileOutputStream outFile(filepath);
314 		if (outFile.IsOk()) {
315 			wxGIFHandler * gfhandler = (wxGIFHandler *) wxImage::FindHandler(wxBITMAP_TYPE_GIF);
316 			gfhandler->SaveAnimation(images, &outFile, true, AnimateTime);
317 		} else {
318 			wxLogMessage(_("Unable to open the requested file. Aborted!"));
319 		}
320 	}
321 	catch (UserCancel & p) {
322 		//User canceled, just cleanup and exit
323 	}
324 
325 	//Cleanup any memory and reset the windows to their entry state
326 	delete ProgressInd;
327 	ProgressInd = NULL;
328 	Prefs->SetLineWidth(1);
329 	memDC.SelectObject(wxNullBitmap); // bmp has now been destroyed
330 	ePlotmemDC.SelectObject(wxNullBitmap);
331 	if(includeEP) {
332 		if(killEPlotWin) {
333 			delete energyPlotWindow;
334 			energyPlotWindow = NULL;
335 		}
336 		else {
337 			energyPlotWindow->SetSize(savedEPlotWidth, savedEPlotHeight);
338 			energyPlotWindow->FrameChanged();
339 		}
340 	}
341 	ChangeFrames(saveFrame);
342 
343 }
344 #endif
345