Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:48

0001 /*
0002  * Copyright (c) 2019 Opticks Team. All Rights Reserved.
0003  *
0004  * This file is part of Opticks
0005  * (see https://bitbucket.org/simoncblyth/opticks).
0006  *
0007  * Licensed under the Apache License, Version 2.0 (the "License"); 
0008  * you may not use this file except in compliance with the License.  
0009  * You may obtain a copy of the License at
0010  *
0011  *   http://www.apache.org/licenses/LICENSE-2.0
0012  *
0013  * Unless required by applicable law or agreed to in writing, software 
0014  * distributed under the License is distributed on an "AS IS" BASIS, 
0015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
0016  * See the License for the specific language governing permissions and 
0017  * limitations under the License.
0018  */
0019 
0020 #include <sstream>
0021 #include <iostream>
0022 #include <iomanip>
0023 #include <cstdlib>
0024 #include <cstring>
0025 #include <csignal>
0026 #include <cmath>
0027 #include <math.h>
0028 
0029 #include <cassert>
0030 #include <cstdio>
0031 #include <fstream> 
0032 
0033 #include <sys/wait.h>
0034 
0035 #include "SSys.hh"
0036 #include "SStr.hh"
0037 #include "SLOG.hh"
0038 
0039 #include "scuda.h"
0040 
0041 
0042 extern char **environ;
0043 
0044 const plog::Severity SSys::LEVEL = SLOG::EnvLevel("SSys", "DEBUG")  ; 
0045 
0046 const char* SSys::OS = "Linux"  ; 
0047 
0048 
0049 void SSys::DumpEnv(const char* pfx ) // static
0050 {
0051     int i = 1;
0052     for (char* s = *environ ; s; i++) 
0053     {
0054        if(pfx == NULL || strncmp(s, pfx, strlen(pfx)) == 0) printf("%s\n", s);
0055        s = *(environ+i);
0056     }
0057 }
0058 
0059 
0060 const unsigned SSys::SIGNBIT32  = 0x80000000 ;
0061 const unsigned SSys::OTHERBIT32 = 0x7fffffff ;
0062 
0063 
0064 bool SSys::IsNegativeZero(float f)
0065 {
0066    return std::signbit(f) && f == -0.f ;  
0067 }
0068 
0069 
0070 const char* SSys::fmt(const char* tmpl, unsigned val)
0071 {
0072     char buf[100] ; 
0073     snprintf(buf, 100, tmpl, val );
0074     return strdup(buf);
0075 }
0076 
0077 
0078 int SSys::exec(const char* exe, const char* arg1, const char* arg2)
0079 {
0080     std::stringstream ss ; 
0081     ss << exe << " " ; 
0082     if(arg1) ss << arg1 << " " ; 
0083     if(arg2) ss << arg2 << " " ; 
0084 
0085     std::string cmd = ss.str();
0086     return SSys::run(cmd.c_str());
0087 }
0088 
0089 int SSys::run(const char* cmd)
0090 {
0091     int rc_raw = system(cmd);
0092     int rc =  WEXITSTATUS(rc_raw) ;
0093 
0094     LOG(info) << cmd 
0095               << " rc_raw : " << rc_raw 
0096               << " rc : " << rc
0097               ;
0098 
0099     if(rc != 0)
0100     {
0101         LOG(error) 
0102             << "FAILED with "
0103             << " cmd " << cmd 
0104             << " RC " << rc 
0105             ;
0106         LOG(verbose) << " possibly you need to set export PATH=$OPTICKS_HOME/ana:$OPTICKS_HOME/bin:/usr/local/opticks/lib:$PATH " ;
0107     }
0108     return rc ;  
0109 }
0110 
0111 
0112 
0113 
0114 
0115 
0116 
0117 
0118 
0119 std::string SSys::Which(const char* script)
0120 {
0121     bool chomp = true ; 
0122 
0123     int rc(0); 
0124     std::string path = SSys::POpen("which 2>/dev/null", script, chomp, rc );
0125     LOG(LEVEL) 
0126          << " script " << script
0127          << " path " << path 
0128          << " rc " << rc
0129          ;
0130 
0131     std::string empty ; 
0132     return rc == 0 ? path : empty ; 
0133 }
0134 
0135 
0136 /**
0137 SSys::POpen
0138 -------------
0139 Run command and get output into string, 
0140 Newlines are removed when chomp is true.
0141 
0142 **/
0143 
0144 
0145 std::string SSys::POpen(const char* cmd, bool chomp, int& rc)
0146 {
0147     LOG(LEVEL) << "[ " << cmd ; 
0148 
0149     std::stringstream ss ; 
0150     FILE *fp = popen(cmd, "r");
0151     char line[512];    
0152     while (fgets(line, sizeof(line), fp) != NULL) 
0153     {
0154        if(chomp) line[strcspn(line, "\n")] = 0;
0155        //LOG(info) << "[" << line << "]" ; 
0156        ss << line ;  
0157     }
0158 
0159     rc=0 ; 
0160     int st = pclose(fp);
0161     if(WIFEXITED(st)) rc=WEXITSTATUS(st);
0162     LOG(LEVEL) << "] " << cmd << " rc " << rc ; 
0163 
0164     return ss.str() ; 
0165 }
0166 
0167 std::string SSys::POpen(const char* cmda, const char* cmdb, bool chomp, int& rc)
0168 {
0169     std::stringstream ss ; 
0170     if(cmda) ss << cmda ; 
0171     ss << " " ; 
0172     if(cmdb) ss << cmdb ; 
0173 
0174     std::string s = ss.str(); 
0175     return POpen(s.c_str(), chomp, rc ); 
0176 }
0177 
0178 
0179 
0180 
0181 
0182 
0183 
0184 
0185 
0186 int SSys::npdump(const char* path, const char* nptype, const char* postview, const char* printoptions)
0187 {
0188     if(!printoptions) printoptions = "suppress=True,precision=3" ;
0189 
0190     std::stringstream ss ; 
0191     ss << "python -c 'import sys, os, numpy as np ;"
0192        << " np.set_printoptions(" << printoptions << ") ;"
0193        << " a=np.load(os.path.expandvars(\"" << path << "\")) ;"
0194        << " print(a.shape);"
0195        << " print(a.view(" << nptype << ")" << ( postview ? postview : "" ) << ") ;"
0196        << " sys.exit(0) ' " 
0197     ;    
0198 
0199     std::string cmd = ss.str();
0200     return run(cmd.c_str());
0201 }
0202 
0203 
0204 void SSys::xxdump(char* buf, int num_bytes, int width, char non_printable )
0205 {
0206 
0207 /*
0208      LOG(info) << " SSys::xxdump "
0209              << " '0' " << (int)'0' 
0210              << " '9' " << (int)'9' 
0211              << " 'A' " << (int)'A' 
0212              << " 'Z' " << (int)'Z'
0213              << " 'a' " << (int)'a'
0214              << " 'z' " << (int)'z'
0215              ;
0216 */
0217 
0218     for(int i=0 ; i < num_bytes ; i++) 
0219     {   
0220         char c = buf[i] ; 
0221         bool printable = c >= ' ' && c <= '~' ;  // https://en.wikipedia.org/wiki/ASCII
0222         std::cout << ( printable ? c : non_printable )  ;
0223         if((i+1) % width == 0 ) std::cout << "\n" ; 
0224    }   
0225 }
0226 
0227 
0228 std::string SSys::xxd( char* buf, int num_bytes, int width, char non_printable )
0229 {
0230     std::stringstream ss ;  
0231     for(int i=0 ; i < num_bytes ; i++) 
0232     {   
0233         char c = buf[i] ; 
0234         bool printable = c >= ' ' && c <= '~' ;  // https://en.wikipedia.org/wiki/ASCII
0235         ss << ( printable ? c : non_printable )  ;
0236         if((i+1) % width == 0 ) ss << "\n" ; 
0237    }   
0238    return ss.str(); 
0239 }
0240 
0241 
0242 
0243 std::string SSys::hexlify(const void* obj, size_t size, bool reverse)
0244 { 
0245     const unsigned char * const bytes = static_cast<const unsigned char *>(obj);
0246     std::stringstream ss ; 
0247     for(size_t i=0 ; i < size ; i++) ss << std::setw(2) << std::hex << std::setfill('0') << unsigned(bytes[reverse ? size - 1 - i : i]) ; 
0248     return ss.str(); 
0249 }
0250 
0251 
0252 
0253 
0254 
0255 /**
0256 SSys::GetInteractivityLevel
0257 -------------------------------
0258 
0259 Defines an interactivity level of the session 
0260 as discerned from the existance of certain environment
0261 variables characteristic of test running and remote ssh sessions.
0262 
0263 see opticks/notes/issues/automated_interop_tests.rst
0264 
0265 hmm these envvars are potentially dependant on CMake/CTest version 
0266 if that turns out to be the case will have to define an OPTICKS_INTERACTIVITY 
0267 envvar for this purpose
0268 
0269 
0270 This is used by OpticksMode::getInteractivityLevel see `opticks-f getInteractivityLevel`
0271 
0272 
0273 
0274 **/
0275 
0276 int SSys::GetInteractivityLevel()
0277 {
0278     char* dtmd = getenv("DART_TEST_FROM_DART");           //  ctest run with --interactive-debug-mode 0
0279     char* cidm = getenv("CTEST_INTERACTIVE_DEBUG_MODE");  //  ctest run with --interactive-debug-mode 1  (the default)
0280 
0281     int level = 2 ;   
0282     if(dtmd && dtmd[0] == '1') 
0283     {
0284         level = 0 ;  // running under CTest with --interactive-debug-mode 0 meaning no-interactivity 
0285     }
0286     else if(IsRemoteSession())
0287     {
0288         level = 0 ;   // remote SSH running 
0289     }
0290     else if(cidm && cidm[0] == '1') 
0291     {
0292         level = 1 ;  // running under CTest with --interactive-debug-mode 1  
0293     }
0294     else if(cidm && cidm[0] == '0') 
0295     {
0296         level = 0 ;  
0297     } 
0298     else
0299     {
0300         level = 2 ;  // not-running under CTest 
0301     }
0302     return level ;
0303 }
0304 
0305 
0306 
0307 bool SSys::IsCTestRunning()
0308 {
0309     char* dtmd = getenv("DART_TEST_FROM_DART");           //  ctest run with --interactive-debug-mode 0
0310     char* cidm = getenv("CTEST_INTERACTIVE_DEBUG_MODE");  //  ctest run with --interactive-debug-mode 1  (the default)
0311     return dtmd || cidm ; 
0312 }
0313 
0314 
0315 bool SSys::IsENVVAR(const char* envvar)
0316 {
0317     char* e = getenv(envvar);
0318     return e != NULL ;
0319 }
0320 
0321 bool SSys::IsVERBOSE() {  return IsENVVAR("VERBOSE") ; }
0322 bool SSys::IsHARIKARI() { return IsENVVAR("HARIKARI") ; }
0323 
0324 
0325 
0326 bool SSys::IsRemoteSession()
0327 {
0328     char* ssh_client = getenv("SSH_CLIENT");
0329     char* ssh_tty = getenv("SSH_TTY");
0330 
0331     bool is_remote = ssh_client != NULL || ssh_tty != NULL ; 
0332 
0333     LOG(verbose) << "SSys::IsRemoteSession"
0334                << " ssh_client " << ssh_client 
0335                << " ssh_tty " << ssh_tty
0336                << " is_remote " << is_remote
0337                ; 
0338 
0339     return is_remote ; 
0340 }
0341 
0342 
0343 void SSys::WaitForInput(const char* msg)
0344 {
0345     LOG(info) << "SSys::WaitForInput " << msg  ; 
0346     int c = '\0' ;
0347     do
0348     {
0349         c = std::cin.get() ;  
0350 
0351     } while(c != '\n' ); 
0352    
0353     LOG(info) << "SSys::WaitForInput DONE " ; 
0354 }
0355 
0356 int SSys::getenvint( const char* envkey, int fallback )
0357 {
0358     char* val = getenv(envkey);
0359     int ival = val ? atoi_(val) : fallback ;
0360     return ival ; 
0361 }
0362 
0363 char SSys::getenvchar( const char* envkey, char fallback )
0364 {
0365     char* val = getenv(envkey);
0366     char c = val ? val[0] : fallback ;
0367     return c ; 
0368 }
0369 
0370 unsigned SSys::getenvunsigned_fallback_max( const char* envkey)
0371 {
0372     return SSys::getenvunsigned(envkey, std::numeric_limits<unsigned>::max() ); 
0373 }
0374 
0375 unsigned SSys::getenvunsigned( const char* envkey, unsigned fallback )
0376 {
0377     char* val = getenv(envkey);
0378     unsigned uval = val ? atoi_(val) : fallback ;
0379     return uval ; 
0380 }
0381 
0382 float SSys::getenvfloat( const char* envkey, float fallback )
0383 {
0384     char* val = getenv(envkey);
0385     float fval = val ? atof_(val) : fallback ;
0386     return fval ; 
0387 }
0388 
0389 double SSys::getenvdouble( const char* envkey, double fallback )
0390 {
0391     char* val = getenv(envkey);
0392     double fval = val ? atod_(val) : fallback ;
0393     return fval ; 
0394 }
0395 
0396 bool SSys::getenvbool( const char* envkey )
0397 {
0398     char* val = getenv(envkey);
0399     bool ival = val ? true : false ;
0400     return ival ; 
0401 }
0402 
0403 /**
0404 SSys::getenvintvec
0405 --------------------
0406 
0407 All usage should migrate to::
0408 
0409     ssys::getenv_vec<int> 
0410 
0411 **/
0412 
0413 std::vector<int>* SSys::getenvintvec(const char* envkey, char delim)   // static
0414 {
0415     if(getenv(envkey) == nullptr) return nullptr ; 
0416  
0417     std::vector<int>* ivec = new std::vector<int>() ; 
0418 
0419     int nitem = getenvintvec(envkey, *ivec, delim, "" ); 
0420 
0421     LOG(LEVEL) << " nitem " << nitem ; 
0422 
0423     return ivec ; 
0424 } 
0425 
0426 
0427 int SSys::getenvintvec( const char* envkey, std::vector<int>& ivec, char delim, const char* fallback  )
0428 {
0429     char* line = getenv(envkey);
0430     std::stringstream ss; 
0431     ss.str(line ? line : fallback)  ;
0432     std::string s;
0433     while (std::getline(ss, s, delim)) ivec.push_back(atoi_(s.c_str())) ; 
0434     return ivec.size(); 
0435 }
0436 
0437 std::string SSys::Desc(const std::vector<int>* ivec)
0438 {
0439     std::stringstream ss ; 
0440     if(ivec == nullptr) ss << "ivec null" ; 
0441     else for(unsigned i=0 ; i < ivec->size() ; i++ ) ss << std::setw(7) << (*ivec)[i] << " " ; 
0442     std::string s = ss.str(); 
0443     return s ; 
0444 }
0445 
0446 
0447 
0448 std::vector<float>* SSys::getenvfloatvec(const char* envkey, const char* fallback, char delim  )
0449 {
0450     std::vector<float>* fvec = new std::vector<float>() ; 
0451     int nitem = getenvfloatvec(envkey, *fvec,fallback, delim  ); 
0452     LOG(LEVEL) << " nitem " << nitem ; 
0453     return fvec ; 
0454 }
0455 
0456 
0457 
0458 
0459 int  SSys::getenvfloatvec( const char* envkey, std::vector<float>& fvec, const char* fallback, char delim )
0460 {
0461     char* line = getenv(envkey);
0462     std::stringstream ss; 
0463     ss.str(line ? line : fallback)  ;
0464     std::string s;
0465     while (std::getline(ss, s, delim)) fvec.push_back(atof_(s.c_str())) ; 
0466     return fvec.size(); 
0467 }
0468 
0469 float3 SSys::getenvfloat3( const char* envkey, const char* fallback, char delim  )
0470 {
0471    std::vector<float> fvec ;  
0472    getenvfloatvec(envkey, fvec, fallback, delim ); 
0473    return make_float3( 
0474               fvec.size() > 0 ? fvec[0] : 0.f , 
0475               fvec.size() > 1 ? fvec[1] : 0.f , 
0476               fvec.size() > 2 ? fvec[2] : 0.f  
0477              );  
0478 }
0479 
0480 float3 SSys::getenvfloat3norm( const char* envkey, const char* fallback, char delim  )
0481 {
0482     float3 v = getenvfloat3(envkey, fallback, delim); 
0483     return normalize(v); 
0484 }
0485 
0486 
0487 float4 SSys::getenvfloat4( const char* envkey, const char* fallback, char delim  )
0488 {
0489    std::vector<float> fvec ;  
0490    getenvfloatvec(envkey, fvec, fallback, delim ); 
0491    return make_float4( 
0492               fvec.size() > 0 ? fvec[0] : 0.f , 
0493               fvec.size() > 1 ? fvec[1] : 0.f , 
0494               fvec.size() > 2 ? fvec[2] : 0.f ,
0495               fvec.size() > 3 ? fvec[3] : 0.f 
0496             );  
0497 }
0498 
0499 
0500 std::string SSys::Desc(const std::vector<float>* fvec)
0501 {
0502     std::stringstream ss ; 
0503     if(fvec == nullptr) ss << "fvec null" ; 
0504     else for(unsigned i=0 ; i < fvec->size() ; i++ ) ss << std::setw(10) << std::fixed << std::setprecision(4) << (*fvec)[i] << " " ; 
0505     std::string s = ss.str(); 
0506     return s ; 
0507 }
0508 
0509 
0510 
0511 int SSys::atoi_( const char* a )
0512 {
0513     std::string s(a);
0514     std::istringstream iss(s);
0515     int i ;
0516     iss >> i ; 
0517     return i ;
0518 }
0519 
0520 
0521 float SSys::atof_( const char* a )
0522 {
0523     std::string s(a);
0524     std::istringstream iss(s);
0525     float f ;
0526     iss >> f ; 
0527     return f ;
0528 }
0529 
0530 double SSys::atod_( const char* a )
0531 {
0532     std::string s(a);
0533     std::istringstream iss(s);
0534     double f ;
0535     iss >> f ; 
0536     return f ;
0537 }
0538 
0539 
0540 
0541 
0542 
0543 void SSys::split(std::vector<std::string>& elem, const char* str, char delim )
0544 {
0545     if(strchr(str, delim) == nullptr )
0546     {
0547         elem.push_back(str); 
0548     } 
0549     else
0550     {
0551         std::stringstream ss; 
0552         ss.str(str)  ;
0553         std::string s;
0554         while (std::getline(ss, s, delim)) elem.push_back(s) ; 
0555     } 
0556 }
0557 
0558 
0559 bool SSys::hasenvvar( const char* ekey )
0560 {
0561     return getenv(ekey) != nullptr ;
0562 }
0563 
0564 /**
0565 SSys::getenvvar
0566 ------------------
0567 
0568 When the argument contains ',' it is split with this delimiter
0569 into separate keys which are checked in order.
0570 The first with non-null value is returned.
0571 
0572 **/
0573 
0574 const char* SSys::getenvvar( const char* envvar )
0575 {
0576     std::vector<std::string> evars ; 
0577     split(evars, envvar, ','); 
0578     const char* evalue = nullptr ; 
0579     for(unsigned i=0 ; i < evars.size() ; i++)
0580     {
0581         const char* ekey = evars[i].c_str(); 
0582         evalue = getenv(ekey);
0583         if(evalue) break ; 
0584     }
0585     return evalue ; 
0586 }
0587 
0588 const char* SSys::getenvvar( const char* envkey, const char* fallback )
0589 {
0590     const char* evalue = getenvvar(envkey) ; 
0591     return evalue ? evalue : fallback ; 
0592 }
0593 
0594 const char* SSys::username()
0595 {
0596 #ifdef _MSC_VER
0597     const char* user = SSys::getenvvar("USERNAME") ;
0598 #else
0599     const char* user = SSys::getenvvar("USER") ;
0600 #endif
0601     return user ? user : "SSys-username-undefined" ; 
0602 }
0603 
0604 
0605 #ifdef _MSC_VER
0606 const char* SSys::hostname()
0607 {
0608     // https://stackoverflow.com/questions/27914311/get-computer-name-and-logged-user-name
0609     return NULL ; 
0610 }
0611 #else
0612 
0613 #ifndef HOST_NAME_MAX
0614 # if defined(_POSIX_HOST_NAME_MAX)
0615 #  define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
0616 # elif defined(MAXHOSTNAMELEN)
0617 #  define HOST_NAME_MAX MAXHOSTNAMELEN
0618 # endif
0619 #endif /* HOST_NAME_MAX */
0620 
0621 
0622 #include <unistd.h>
0623 #include <limits.h>
0624 const char* SSys::hostname()
0625 {
0626     char hostname[HOST_NAME_MAX];
0627     hostname[0] = '\0' ;
0628     gethostname(hostname, HOST_NAME_MAX);
0629     return hostname[0] == '\0' ? "SSys-hostname-undefined" : strdup(hostname) ; 
0630 }
0631 #endif
0632 
0633 int SSys::unsetenv( const char* ekey )
0634 {
0635     return ::unsetenv(ekey); 
0636 }
0637 
0638 /**
0639 SSys::setenvvar
0640 -----------------
0641 
0642 When overwrite is false a preexisting envvar is not overridden. 
0643 
0644 As shell handling of empty strings is inconvenient the special_empty_token char 
0645 allows a single char to represent the empty string, eg '-' 
0646 
0647 **/
0648 
0649 int SSys::setenvvar( const char* ekey, const char* value, bool overwrite, char special_empty_token)
0650 {
0651     std::stringstream ss ;
0652     ss << ekey << "=" ;
0653 
0654     if(value)
0655     {
0656         if(special_empty_token != '\0' && strlen(value) == 1 && value[0] == special_empty_token)
0657         {
0658             ss << "" ; 
0659         }
0660         else
0661         {
0662             ss << value ; 
0663         }
0664     }
0665 
0666     std::string ekv = ss.str();
0667     const char* prior = getenv(ekey) ;
0668 
0669     char* ekv_ = const_cast<char*>(strdup(ekv.c_str()));
0670 
0671     int rc = ( overwrite || !prior ) ? putenv(ekv_) : 0  ; 
0672 
0673     const char* after = getenv(ekey) ;
0674 
0675     LOG(debug) 
0676         << " ekey " << ekey 
0677         << " ekv " << ekv 
0678         << " overwrite " << overwrite
0679         << " prior " << ( prior ? prior : "NULL" )
0680         << " value " << ( value ? value : "NULL" )   
0681         << " after " << ( after ? after : "NULL" )   
0682         << " rc " << rc 
0683         ;
0684 
0685     //std::raise(SIGINT);  
0686     return rc ;
0687 }
0688 
0689 unsigned SSys::COUNT = 0 ; 
0690 
0691 /**
0692 SSys::Dump_
0693 --------------
0694 
0695 Dump the message using std::cout std::cerr printf and std::printf, used for testing stream redirection
0696 
0697 **/
0698 
0699 void SSys::Dump_(const char* msg)
0700 {
0701     std::cout << std::setw(3) << COUNT << "[" << std::setw(20) << "std::cout" << "] " << msg << std::endl;  
0702     std::cerr << std::setw(3) << COUNT << "[" << std::setw(20) << "std::cerr" << "] " << msg << std::endl;  
0703     printf("%3d[%20s] %s \n", COUNT, "printf", msg );  
0704     std::printf("%3d[%20s] %s \n", COUNT, "std::printf", msg );  
0705 }
0706 void SSys::Dump(const char* msg)
0707 {
0708     Dump_(msg);
0709     std::cerr << std::endl  ;   
0710     COUNT++ ; 
0711 }
0712 
0713 
0714 
0715 const char* SSys::ResolveExecutable(const char* envvar_key, const char* default_executable)
0716 {
0717     const char* ev = SSys::getenvvar(envvar_key, default_executable) ; 
0718     if(ev && ev[0] == '/') return strdup(ev) ;  // assume absolute path of python executable is provided
0719     std::string path = SSys::Which(ev); 
0720     return strdup(path.c_str()); 
0721 }
0722 const char* SSys::ResolvePython()
0723 {
0724     return SSys::ResolveExecutable("OPTICKS_PYTHON", "python"); 
0725 }
0726 
0727 /**
0728 SSys::RunPythonScript
0729 -----------------------
0730 
0731 Control which python to use with envvar OPTICKS_PYTHON eg::
0732 
0733     OPTICKS_PYTHON=python2.7 SSysTest 
0734     OPTICKS_PYTHON=python3   SSysTest
0735     OPTICKS_PYTHON=/Users/blyth/miniconda3/bin/python3 SSysTest 
0736 
0737 **/
0738 
0739 
0740 
0741 int SSys::RunPythonScript(const char* script)
0742 {
0743     std::string script_path = SSys::Which(script);
0744     const char* python_executable = SSys::ResolvePython() ; 
0745     LOG(info) 
0746          << " script " << script
0747          << " script_path " << script_path 
0748          << " python_executable " << python_executable 
0749          ;   
0750 
0751     int RC = script_path.empty() ? 101 : SSys::exec(python_executable,script_path.c_str()) ;
0752     LOG(info) << " RC " << RC ; 
0753     LOG_IF(error, RC != 0) << std::endl << RunPythonScript_NOTES  ; 
0754 
0755     return RC ; 
0756 }
0757 
0758 const char* SSys::RunPythonScript_NOTES  = R"LITERAL(
0759 SSys::RunPythonScript_NOTES 
0760 ------------------------------
0761 
0762 Common causes of error when running python scripts via SSys::RunPythonScript are:
0763 
0764 1. using a python which does not have the *numpy* module
0765 2. not configuring PYTHONPATH such that the *opticks* modules can be found 
0766 3. not configuring PATH to allow SSys::Which to find the python scripts 
0767 
0768 Example settings of envvars to configure within .bash_profile or .bashrc which 
0769 control the python that opticks C++ will use with SSys::RunPythonScript are::
0770 
0771    export OPTICKS_PYTHON=/Users/blyth/miniconda3/bin/python
0772    export PYTHONPATH=$PYTHONPATH:$(opticks-fold)
0773    export PATH=$PATH:$(opticks-home)/bin
0774 
0775 Note that opticks-fold is the directory above opticks-home "/home/blyth/opticks" 
0776 so that will often be the HOME directory, eg /home/blyth
0777 
0778 )LITERAL";
0779 
0780 
0781 
0782 int SSys::RunPythonCode(const char* code)
0783 {
0784     const char* python_executable = SSys::ResolvePython() ; 
0785     LOG(info) 
0786          << " code [" << code  << "]"
0787          << " python_executable " << python_executable 
0788          ;   
0789 
0790     const char* arg1 = "-c" ; 
0791     const char* arg2 = SStr::Concat("'", code, "'") ;  
0792 
0793     int RC = code == NULL ? 101 : SSys::exec(python_executable,arg1, arg2) ;
0794     LOG(info) << " RC " << RC ; 
0795     return RC ; 
0796 }
0797 
0798 
0799 void SSys::Exit(int rc)
0800 {
0801     LOG(fatal) << " rc " << rc ; 
0802     std::raise(SIGINT) ; 
0803 }
0804 
0805 
0806 
0807