1 /*
2
3 HyPhy - Hypothesis Testing Using Phylogenies.
4
5 This file implements data and interface classes
6 used for linking HyPhy with MEGA
7
8 Written by SL Kosakovsky Pond; June 2007
9 Dedicated to Comet (http://www.hyphy.org/comet.jpg)
10 ?/?/1999-06/05/2007
11
12 Copyright (C) 1997-now
13 Core Developers:
14 Sergei L Kosakovsky Pond (sergeilkp@icloud.com)
15 Art FY Poon (apoon42@uwo.ca)
16 Steven Weaver (sweaver@temple.edu)
17
18 Module Developers:
19 Lance Hepler (nlhepler@gmail.com)
20 Martin Smith (martin.audacis@gmail.com)
21
22 Significant contributions from:
23 Spencer V Muse (muse@stat.ncsu.edu)
24 Simon DW Frost (sdf22@cam.ac.uk)
25
26 Permission is hereby granted, free of charge, to any person obtaining a
27 copy of this software and associated documentation files (the
28 "Software"), to deal in the Software without restriction, including
29 without limitation the rights to use, copy, modify, merge, publish,
30 distribute, sublicense, and/or sell copies of the Software, and to
31 permit persons to whom the Software is furnished to do so, subject to
32 the following conditions:
33
34 The above copyright notice and this permission notice shall be included
35 in all copies or substantial portions of the Software.
36
37 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
40 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
41 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
42 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
43 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44
45 */
46
47
48 #include "THyPhy.h"
49 #include "batchlan.h"
50 #include "string.h"
51
52
53 /* declare some utility functions */
54
55 void ReadPreferences (void);
56 void ApplyPreferences (void);
57
58 /* global variables */
59
60 _String _tHYPHYAskFor ("_THyPhyAskFor"),
61 _tHYPHYNotHandled ("_THyPhy_NOT_HANDLED_"),
62 _tHYPHYCurrentStatus;
63
64 long _tHYPHYDone = 0;
65 double _tHYPHYValue = 0.0;
66
67 extern long systemCPUCount;
68
69 _THyPhy * globalInterfaceInstance = nil;
70
71 //_________________________________________________________
72 // default callback hanlder
_tHyPhyDefaultHandler(const char *,int,double)73 bool _tHyPhyDefaultHandler (const char*,int,double)
74 {
75 return true;
76 }
77
78 //_________________________________________________________
79 // default callback hanlder
80 //void SetGlobalInterfaceInstance (const _THyPhy* hi)
81 //{
82 // globalInterfaceInstance = hi;
83 //}
84
85
86 /* Basic return types supported by the interface object */
87
88 //_________________________________________________________
castToString(void)89 _THyPhyString* _THyPhyReturnObject::castToString(void)
90 {
91 if (myType() == THYPHY_TYPE_STRING) {
92 return (_THyPhyString*)this;
93 }
94 return NULL;
95 }
96
97 //_________________________________________________________
castToNumber(void)98 _THyPhyNumber* _THyPhyReturnObject::castToNumber(void)
99 {
100 if (myType() == THYPHY_TYPE_NUMBER) {
101 return (_THyPhyNumber*)this;
102 }
103 return NULL;
104 }
105
106 //_________________________________________________________
castToMatrix(void)107 _THyPhyMatrix* _THyPhyReturnObject::castToMatrix(void)
108 {
109 if (myType() == THYPHY_TYPE_MATRIX) {
110 return (_THyPhyMatrix*)this;
111 }
112 return NULL;
113 }
114
115
116 //_________________________________________________________
_THyPhyString(const char * characters,long length)117 _THyPhyString::_THyPhyString(const char* characters, long length)
118 {
119 if (characters) {
120 if (length == 0) {
121 while (characters[length++]) ;
122 length --;
123 }
124 checkPointer (sData = (char*)MemAllocate (length+1));
125 memcpy (sData,characters,length+1);
126
127 } else {
128 sData = nil;
129 }
130 sLength = length;
131 }
132
133 //_________________________________________________________
~_THyPhyString(void)134 _THyPhyString::~_THyPhyString(void)
135 {
136 if (sData) {
137 free (sData);
138 }
139 };
140
141 //_________________________________________________________
_THyPhyNumber(double v)142 _THyPhyNumber::_THyPhyNumber(double v)
143 {
144 nValue = v;
145 }
146
147
148 //_________________________________________________________
_THyPhyMatrix(void)149 _THyPhyMatrix::_THyPhyMatrix(void)
150 {
151 mData = nil;
152 mRows = 0;
153 mCols = 0;
154 }
155
156 //_________________________________________________________
_THyPhyMatrix(const long r,const long c,const double * d)157 _THyPhyMatrix::_THyPhyMatrix(const long r, const long c, const double* d)
158 {
159 checkPointer (mData = (double*)MemAllocate (r*c*sizeof(double)));
160 mRows = r;
161 mCols = c;
162 for (long i = 0; i < r*c; i++,d++) {
163 mData[i] = *d;
164 }
165
166 }
167
168 //_________________________________________________________
~_THyPhyMatrix(void)169 _THyPhyMatrix::~_THyPhyMatrix(void)
170 {
171 if (mData) {
172 free (mData);
173 }
174 };
175
176 //_________________________________________________________
MatrixCell(long r,long c)177 double _THyPhyMatrix::MatrixCell(long r, long c)
178 {
179 return mData[mCols*r+c];
180 }
181
182 //_________________________________________________________
183 // Begin _THyPhy definitions
184 //_________________________________________________________
185
_THyPhy(_ProgressCancelHandler * mHandler,const char * baseDirPath,long cpuCount)186 _THyPhy::_THyPhy(_ProgressCancelHandler* mHandler, const char* baseDirPath, long cpuCount)
187 {
188 InitTHyPhy (mHandler, baseDirPath, cpuCount);
189 }
190
191 //_________________________________________________________
192
193
_THyPhy(const char * baseDirPath,long cpuCount)194 _THyPhy::_THyPhy(const char* baseDirPath, long cpuCount)
195 {
196 InitTHyPhy (_tHyPhyDefaultHandler, baseDirPath, cpuCount);
197 }
198
199 //_________________________________________________________
200
~_THyPhy(void)201 _THyPhy::~_THyPhy (void)
202 {
203 if (currentResultHolder) {
204 delete (_THyPhyReturnObject*)currentResultHolder;
205 }
206 if (baseDirectoryInstance) {
207 delete (baseDirectoryInstance);
208 }
209 ClearAll();
210 DeleteObject ((_String*)errors);
211 DeleteObject ((_String*)warnings);
212 DeleteObject ((_String*)textout);
213 if (globalInterfaceInstance == this) {
214 globalInterfaceInstance = nil;
215 }
216
217 PurgeAll(true);
218 GlobalShutdown();
219 }
220
221 //_________________________________________________________
222
InitTHyPhy(_ProgressCancelHandler * mHandler,const char * baseDirPath,long cpuCount)223 void _THyPhy::InitTHyPhy (_ProgressCancelHandler* mHandler, const char* baseDirPath, long cpuCount)
224 {
225 char dirSlash = GetPlatformDirectoryChar ();
226 systemCPUCount = cpuCount;
227 SetCallbackHandler (mHandler);
228 checkPointer (currentResultHolder = new _THyPhyString);
229 askFID = -1;
230 if (baseDirPath)
231 // set base directory
232 {
233 baseDirectory = baseDirPath;
234 if (baseDirectory.getChar(baseDirectory.sLength-1) != dirSlash) {
235 baseDirectory = baseDirectory & dirSlash;
236 }
237 baseDirectoryInstance = new _THyPhyString (baseDirectory.sData);
238 baseDirectory = baseDirectoryInstance->sData;
239 pathNames && &baseDirectory;
240 ReadPreferences ();
241 }
242
243 #ifdef _HYPHY_LIBDIRECTORY_
244 libDirectory = _HYPHY_LIBDIRECTORY_;
245 if (libDirectory.getChar(libDirectory.sLength-1) != dirSlash) {
246 libDirectory = libDirectory & dirSlash;
247 }
248 #else
249 if (baseDirectory)
250 libDirectory = baseDirectory;
251 #endif
252
253 pathNames && &libDirectory;
254 GlobalStartup();
255 errors = nil;
256 warnings = nil;
257 textout = nil;
258 globalInterfaceInstance = this;
259
260 }
261
262 //_________________________________________________________
263
ExecuteBF(const char * buffer,bool doPurge)264 _THyPhyString * _THyPhy::ExecuteBF (const char * buffer, bool doPurge)
265 {
266 if (doPurge) {
267 PurgeAll (true); // cleanup results of previous analysis
268 }
269
270 _String dd (GetPlatformDirectoryChar());
271
272 _FString bp (baseDirectory, false),
273 lp (libDirectory, false),
274 ds (dd),
275 cfp (pathNames.lLength?*(_String*)pathNames(pathNames.lLength-1):empty),
276 * stashed = (_FString*)FetchObjectFromVariableByType (&pathToCurrentBF, STRING);
277
278 setParameter (platformDirectorySeparator, &ds);
279 setParameter (hyphyBaseDirectory, &bp);
280 setParameter (hyphyLibDirectory, &lp);
281
282 if (stashed) {
283 stashed = (_FString*)stashed->makeDynamic();
284 }
285 setParameter (pathToCurrentBF,&cfp);
286
287 _String commandString (buffer);
288
289 if (commandString.beginswith ("#NEXUS"),false) {
290 lastNexusDataMatrix = ReadDataSetFile (nil, 2, &commandString);
291 commandString = nexusBFBody;
292 }
293
294 _ExecutionList compiledCode (commandString);
295
296 if (doPurge) {
297 ApplyPreferences ();
298 }
299
300 DeleteObject ((_String*)errors);
301 DeleteObject ((_String*)warnings);
302 DeleteObject ((_String*)textout);
303
304 errors = new _String (128L,true);
305 warnings = new _String (128L,true);
306 textout = new _String (128L,true);
307
308 askFID = compiledCode.ExecuteAndClean (0x7ffffff,&_tHYPHYAskFor);
309 _PMathObj bfReturn = compiledCode.GetResult ();
310
311 ((_String*)errors)->Finalize();
312 ((_String*)warnings)->Finalize();
313 ((_String*)textout)->Finalize();
314
315 if (currentResultHolder->sData) {
316 free (currentResultHolder->sData);
317 currentResultHolder->sData = nil;
318 }
319 if (bfReturn) {
320 _String * serializedReturn = (_String*) bfReturn->toStr();
321 currentResultHolder->sData = serializedReturn->sData;
322 serializedReturn->sData = nil;
323 currentResultHolder->sLength = serializedReturn->sLength;
324 }
325 return currentResultHolder;
326 }
327
328 //_________________________________________________________
329
ClearAll(void)330 void _THyPhy::ClearAll (void)
331 {
332 PurgeAll(true);
333 }
334
335 //_________________________________________________________
336
AskFor(const char * resultID)337 void* _THyPhy::AskFor (const char* resultID)
338 {
339 if (resultID && askFID >= 0) {
340 _String theCommand (128L,true);
341 theCommand << "return ";
342 theCommand << _tHYPHYAskFor;
343 theCommand << "(\"";
344 theCommand.EscapeAndAppend (resultID);
345 theCommand << "\");";
346 theCommand.Finalize();
347 _ExecutionList compiledCode (theCommand);
348 compiledCode.ExecuteAndClean (0x7ffffff);
349 _PMathObj retResult = compiledCode.GetResult ();
350 if (retResult && retResult->ObjectClass() == STRING) {
351 _FString * checkHandled = (_FString*)retResult;
352 if (checkHandled->theString->Equal (&_tHYPHYNotHandled)) {
353 return nil;
354 }
355 }
356 return retResult->makeDynamic();
357 }
358 return nil;
359 }
360
361 //_________________________________________________________
362
DumpResult(void * aResult)363 void _THyPhy::DumpResult (void* aResult)
364 {
365 if (aResult) {
366 DeleteObject ((BaseRef)aResult);
367 }
368 }
369
370 //_________________________________________________________
371
SetCallbackHandler(_ProgressCancelHandler * newHandler)372 void _THyPhy::SetCallbackHandler (_ProgressCancelHandler* newHandler)
373 {
374 theHandler = newHandler;
375 }
376
377 //_________________________________________________________
378
GetCallbackHandler(void)379 _ProgressCancelHandler* _THyPhy::GetCallbackHandler (void)
380 {
381 return theHandler;
382 }
383
384 //_________________________________________________________
385
PushWarning(void * o)386 void _THyPhy::PushWarning (void * o)
387 {
388 if (warnings) {
389 *((_String*)warnings) << *(_String*)o;
390 }
391 }
392
393 //_________________________________________________________
394
PushError(void * o)395 void _THyPhy::PushError (void * o)
396 {
397 if (errors) {
398 *((_String*)errors) << *(_String*)o;
399 }
400 }
401
402 //_________________________________________________________
403
PushOutString(void * o)404 void _THyPhy::PushOutString (void * o)
405 {
406 if (textout) {
407 *((_String*)textout) << *(_String*)o;
408 }
409 }
410
411 //_________________________________________________________
412
ConvertHyPhyString(void * o)413 _THyPhyString * _THyPhy::ConvertHyPhyString (void * o)
414 {
415 return new _THyPhyString (((_String*)o)->sData,((_String*)o)->sLength);
416 }
417
418 //_________________________________________________________
419
CanCast(const void * theObject,const int requestedType)420 bool _THyPhy::CanCast (const void* theObject, const int requestedType)
421 {
422 if (theObject) {
423 switch (((_PMathObj)theObject)->ObjectClass()) {
424 case NUMBER:
425 return true;
426 // can cast a number to everything
427 case STRING:
428 return requestedType!=THYPHY_TYPE_MATRIX;
429 // can cast anything to a string
430 case MATRIX:
431 return requestedType!=THYPHY_TYPE_NUMBER;
432 // can not cast matrix to number
433
434 case TREE:
435 case TOPOLOGY:
436 return requestedType==THYPHY_TYPE_STRING;
437
438 }
439 }
440 return false;
441 }
442
443 //_________________________________________________________
444
CastResult(const void * theObject,const int requestedType)445 _THyPhyReturnObject* _THyPhy::CastResult (const void* theObject, const int requestedType)
446 {
447 _THyPhyReturnObject * convertedObject = nil;
448 if (CanCast(theObject,requestedType)) {
449 int hyphyObjClass = ((_PMathObj)theObject)->ObjectClass();
450 switch (hyphyObjClass) {
451 case NUMBER: {
452 if (hyphyObjClass == NUMBER) {
453 return new _THyPhyNumber (((_PMathObj)theObject)->Compute()->Value());
454 }
455 if (hyphyObjClass == STRING) {
456 _String sV ((_String*)((_FString*)theObject)->toStr());
457 return new _THyPhyNumber (sV.toNum());
458 }
459 }
460 case STRING: {
461 _String sV ((_String*)((_PMathObj)theObject)->toStr());
462 return new _THyPhyString (sV.sData,sV.sLength);
463 }
464 case MATRIX: {
465 if (hyphyObjClass == NUMBER) {
466 double evaluate = ((_PMathObj)theObject)->Compute()->Value();
467 return new _THyPhyMatrix (1,1,&evaluate);
468 }
469
470 if (hyphyObjClass == MATRIX) {
471 _Matrix * evalutedNumeric = (_Matrix*)((_Matrix*)(((_PMathObj)theObject)->Compute()))
472 ->ComputeNumeric();
473
474 return new _THyPhyMatrix (evalutedNumeric->GetHDim(),evalutedNumeric->GetVDim(),evalutedNumeric->theData);
475 }
476 }
477 }
478 }
479
480 return convertedObject;
481 }
482
483 //_________________________________________________________________________
484
SetStatusLine(_String arg)485 void SetStatusLine (_String arg)
486 {
487 _tHYPHYCurrentStatus = arg;
488 yieldCPUTime();
489 }
490
491 //_________________________________________________________________________
492
SetStatusBarValue(long l,_Parameter max,_Parameter rate)493 void SetStatusBarValue (long l,_Parameter max, _Parameter rate)
494 {
495 _tHYPHYDone = l;
496 _tHYPHYCurrentStatus = _String ("LF Optimization. Value=") & _String (max) &", "&_String (rate) & " evals/sec.";
497 _tHYPHYValue = max;
498 yieldCPUTime();
499 }
500
501 //_________________________________________________________________________
502
_THyPhyGetLongStatus(void)503 long _THyPhyGetLongStatus (void)
504 {
505 return _tHYPHYDone;
506 }
507
508 //_________________________________________________________________________
509
_THyPhyGetDoubleStatus(void)510 double _THyPhyGetDoubleStatus (void)
511 {
512 return _tHYPHYValue;
513 }
514
515 //_________________________________________________________________________
516
_THyPhyGetStringStatus(void)517 const char* _THyPhyGetStringStatus (void)
518 {
519 return _tHYPHYCurrentStatus.getStr();
520 }
521