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