Skip to content

Commit

Permalink
Windows-Compatible Update, GPI Version 1.2.0 (#37)
Browse files Browse the repository at this point in the history
* Basic changes to create minimal working windows example

* Use spawn type multiproc on Windows

* Modify gpi.command for correct windows launching

* Search menu works properly on Windows

* Add batch file for launching with Windows shells

Co-authored-by: Ashley Anderson <aganders3@gmail.com>
  • Loading branch information
borupdaniel and aganders3 authored Jan 8, 2020
1 parent dc19fed commit b1a6db3
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 109 deletions.
11 changes: 8 additions & 3 deletions include/PyFI/PyFIArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@
#include <vector>
using namespace std;

#include <execinfo.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h> /* fabs */

#include "PyFI/PyFIMacros.h"
#include "PyFI/backtrace.cpp"

#ifdef __linux__
#include <execinfo.h>
#include "PyFI/backtrace.cpp"
#endif

/* allow the user to change this */
#ifndef PYFI_PRINT_ELEMLIMIT
Expand Down Expand Up @@ -2208,7 +2212,8 @@ ostream& operator<<(ostream& os, const Array<T>& out)
uint64_t elem_limit = PYFI_PRINT_ELEMLIMIT;

/* print array info */
os << "Array<" << PyFI::Demangle(typeid(T).name()) << "> " << out.ndim() << "D (";
// TODO: Demangle doesn't work/exist on Windows
// os << "Array<" << PyFI::Demangle(typeid(T).name()) << "> " << out.ndim() << "D (";
for(uint64_t i=0; i<out.ndim(); ++i)
{
os << out.dimensions()[i];
Expand Down
35 changes: 29 additions & 6 deletions include/PyFI/PyFIArray_WrappedFFTW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@
* TODO: Create a macro case for the mutex calls when excluding pthread.h is
* necessary (i.e. for the R2 reconstructor platform).
*/
#include <pthread.h>
#include <pthread.h>
// #include <boost/thread.hpp>

namespace PyFI
{
Expand All @@ -141,10 +142,16 @@ namespace FFTW
#define SHIFT_OFF 237387

// stdout color
#define _fftw_PYFI_RED "\e[31m"
#define _fftw_PYFI_NOC "\e[39m"
#ifdef _WIN32
#define _fftw_PYFI_RED "0x1B[31m"
#define _fftw_PYFI_NOC "0x1B[39m"
#else
#define _fftw_PYFI_RED "\e[31m"
#define _fftw_PYFI_NOC "\e[39m"
#endif

pthread_mutex_t _fftw_mutex = PTHREAD_MUTEX_INITIALIZER;
// boost::mutex _fftw_mutex;

unsigned global_fftFlags = FFTW_ESTIMATE;
int global_shiftMode = SHIFT_ON;
Expand Down Expand Up @@ -632,6 +639,7 @@ void fft1 (Array<T>& in, Array<T>& out, int fftDirection)

// generate plan according to fftw advanced interface
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
{
planD = fftw_plan_many_dft (1, dims, howmany, reinterpret_cast<fftw_complex*> (temp.data()), NULL, 1, dist, reinterpret_cast<fftw_complex*> (temp.data()), NULL, 1, dist, fftDirection, global_fftFlags);
Expand All @@ -641,6 +649,7 @@ void fft1 (Array<T>& in, Array<T>& out, int fftDirection)
planF = fftwf_plan_many_dft (1, dims, howmany, reinterpret_cast<fftwf_complex*> (temp.data()), NULL, 1, dist, reinterpret_cast<fftwf_complex*> (temp.data()), NULL, 1, dist, fftDirection, global_fftFlags);
}
pthread_mutex_unlock(&_fftw_mutex);
// _fftw_mutex.unlock();

// call shifting routines (if SHIFT_ON) and execute fft
if (global_shiftMode == SHIFT_ON)
Expand All @@ -660,11 +669,13 @@ void fft1 (Array<T>& in, Array<T>& out, int fftDirection)

// destroy allocated memory
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
fftw_destroy_plan (planD);
else
fftwf_destroy_plan (planF);
pthread_mutex_unlock(&_fftw_mutex);
// _fftw_mutex.unlock();

// scale fft result if inverse fft is performed
if (fftDirection == FFTW_BACKWARD)
Expand Down Expand Up @@ -715,6 +726,7 @@ void fft2 (Array<T>& in, Array<T>& out, int fftDirection)

// generate plan according to fftw advanced interface
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
{
planD = fftw_plan_many_dft (2, dims, howmany, reinterpret_cast<fftw_complex*> (temp.data()), NULL, 1, dist, reinterpret_cast<fftw_complex*> (temp.data()), NULL, 1, dist, fftDirection, global_fftFlags);
Expand All @@ -724,7 +736,8 @@ void fft2 (Array<T>& in, Array<T>& out, int fftDirection)
planF = fftwf_plan_many_dft (2, dims, howmany, reinterpret_cast<fftwf_complex*> (temp.data()), NULL, 1, dist, reinterpret_cast<fftwf_complex*> (temp.data()), NULL, 1, dist, fftDirection, global_fftFlags);
}
pthread_mutex_unlock(&_fftw_mutex);

// _fftw_mutex.unlock();

// call shifting routines (if SHIFT_ON) and execute fft
if (global_shiftMode == SHIFT_ON)
shift2 (in, temp, beforeFFT);
Expand All @@ -743,11 +756,13 @@ void fft2 (Array<T>& in, Array<T>& out, int fftDirection)

// destroy allocated memory
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
fftw_destroy_plan (planD);
else
fftwf_destroy_plan (planF);
pthread_mutex_unlock(&_fftw_mutex);
// _fftw_mutex.unlock();

// scale fft result if inverse fft is performed
if (fftDirection == FFTW_BACKWARD)
Expand Down Expand Up @@ -800,6 +815,7 @@ void fft3 (Array<T>& in, Array<T>& out, int fftDirection)

// generate plan according to fftw advanced interface
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
{
planD = fftw_plan_many_dft (3, dims, howmany, reinterpret_cast<fftw_complex*> (temp.data()), NULL, 1, dist, reinterpret_cast<fftw_complex*> (temp.data()), NULL, 1, dist, fftDirection, global_fftFlags);
Expand All @@ -809,6 +825,7 @@ void fft3 (Array<T>& in, Array<T>& out, int fftDirection)
planF = fftwf_plan_many_dft (3, dims, howmany, reinterpret_cast<fftwf_complex*> (temp.data()), NULL, 1, dist, reinterpret_cast<fftwf_complex*> (temp.data()), NULL, 1, dist, fftDirection, global_fftFlags);
}
pthread_mutex_unlock(&_fftw_mutex);
// _fftw_mutex.unlock();

// call shifting routines (if SHIFT_ON) and execute fft
if (global_shiftMode == SHIFT_ON)
Expand All @@ -828,11 +845,13 @@ void fft3 (Array<T>& in, Array<T>& out, int fftDirection)

// destroy allocated memory
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
fftw_destroy_plan (planD);
else
fftwf_destroy_plan (planF);
pthread_mutex_unlock(&_fftw_mutex);
// _fftw_mutex.unlock();

// scale fft result if inverse fft is performed
if (fftDirection == FFTW_BACKWARD)
Expand Down Expand Up @@ -902,6 +921,7 @@ void fft1n (Array<T>& in, Array<T>& out, int fftDirection, uint64_t fftDim)

// generate plan according to fftw guru interface
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
{
planD = fftw_plan_guru_dft (1, &dims, (int) (in.ndim() - i_start - 1), howmany_dims, reinterpret_cast<fftw_complex*> (temp.data()), reinterpret_cast<fftw_complex*> (temp.data()), fftDirection, global_fftFlags);
Expand All @@ -911,7 +931,8 @@ void fft1n (Array<T>& in, Array<T>& out, int fftDirection, uint64_t fftDim)
planF = fftwf_plan_guru_dft (1, &dims, (int) (in.ndim() - i_start - 1), howmany_dims, reinterpret_cast<fftwf_complex*> (temp.data()), reinterpret_cast<fftwf_complex*> (temp.data()), fftDirection, global_fftFlags);
}
pthread_mutex_unlock(&_fftw_mutex);

// _fftw_mutex.unlock();

// call shifting routines (if SHIFT_ON) and execute fft
if (global_shiftMode == SHIFT_ON)
shift1n (in, temp, beforeFFT, fftDim);
Expand All @@ -932,13 +953,15 @@ void fft1n (Array<T>& in, Array<T>& out, int fftDirection, uint64_t fftDim)

// destroy allocated memory
pthread_mutex_lock(&_fftw_mutex);
// _fftw_mutex.lock();
if(is_double)
fftw_destroy_plan (planD);
else
{
fftwf_destroy_plan (planF);
}
pthread_mutex_unlock(&_fftw_mutex);
pthread_mutex_unlock(&_fftw_mutex);
// _fftw_mutex.unlock();

// scale fft result if inverse fft is performed
if (fftDirection == FFTW_BACKWARD)
Expand Down
12 changes: 9 additions & 3 deletions include/PyFI/PyFIMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ inline T __PYFI_itself(T arg)

/* Simple macros for debugging. */
/* stdout color */
#define _PYFI_YEL "\e[93m"
#define _PYFI_RED "\e[31m"
#define _PYFI_NOC "\e[39m"
#ifdef _WIN32
#define _PYFI_YEL "0x1B[93m"
#define _PYFI_RED "0x1B[31m"
#define _PYFI_NOC "0x1B[39m"
#else
#define _PYFI_YEL "\e[93m"
#define _PYFI_RED "\e[31m"
#define _PYFI_NOC "\e[39m"
#endif

#define coutv(var) cout << __FILE__ << ":" << __LINE__ << "\t"<< #var \
<< " = " << var << "\n"
Expand Down
2 changes: 2 additions & 0 deletions include/PyFI/PyFunctionIF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -988,10 +988,12 @@ Parm_Abstract *FuncIF::NewParm(string name, const type_info *type)

if (parm_ptr == NULL)
{
/* TODO: Demangle not working on Windows
stringstream ss;
ss << _PYFI_RED "PyFI: Arg \'" << name << "\' (zero-based if PosArg): NewParm() requested typeid \'"
<< PyFI::Demangle(type->name()) << "\' not supported.\n" _PYFI_NOC <<supportedTypes();
Error(ss.str());
*/
}

return parm_ptr;
Expand Down
2 changes: 1 addition & 1 deletion include/multiproc/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ extern "C"
pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;

#ifndef DOXYGEN_IGNORE
__attribute__((__deprecated__))
// __attribute__((__deprecated__))
#endif
/**
\brief A standard mutex for printing to stdout.
Expand Down
11 changes: 8 additions & 3 deletions launch/gpi.command
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,21 @@ fi
ANACONDA=/opt/anaconda1anaconda2anaconda3
PYTHON=${ANACONDA}/bin/python
GPI_LAUNCH=${ANACONDA}/bin/gpi_launch
WIN_PYTHON=${ANACONDA}/python
WIN_GPI_LAUNCH=${ANACONDA}/Scripts/gpi_launch

GPI_LINK=/tmp/GPI

# OSX
if [ "$(uname)" == "Darwin" ]; then
ln -f -s $PYTHON $GPI_LINK
$GPI_LINK $GPI_LAUNCH $@
fi

# Linux
if [ "$(uname)" == "Linux" ]; then
elif [ "$(uname)" == "Linux" ]; then
$PYTHON $GPI_LAUNCH -style cleanlooks $@
# Windows
else
$WIN_PYTHON -u $WIN_GPI_LAUNCH -style Windows $@
fi


38 changes: 38 additions & 0 deletions launch/gpi_cmd.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@echo off

:: Copyright (C) 2014 Dignity Health
::
:: This program is free software: you can redistribute it and/or modify
:: it under the terms of the GNU Lesser General Public License as published by
:: the Free Software Foundation, either version 3 of the License, or
:: (at your option) any later version.
::
:: This program is distributed in the hope that it will be useful,
:: but WITHOUT ANY WARRANTY; without even the implied warranty of
:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
:: GNU Lesser General Public License for more details.
::
:: You should have received a copy of the GNU Lesser General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>.
::
:: NO CLINICAL USE. THE SOFTWARE IS NOT INTENDED FOR COMMERCIAL PURPOSES
:: AND SHOULD BE USED ONLY FOR NON-COMMERCIAL RESEARCH PURPOSES. THE
:: SOFTWARE MAY NOT IN ANY EVENT BE USED FOR ANY CLINICAL OR DIAGNOSTIC
:: PURPOSES. YOU ACKNOWLEDGE AND AGREE THAT THE SOFTWARE IS NOT INTENDED FOR
:: USE IN ANY HIGH RISK OR STRICT LIABILITY ACTIVITY, INCLUDING BUT NOT
:: LIMITED TO LIFE SUPPORT OR EMERGENCY MEDICAL OPERATIONS OR USES. LICENSOR
:: MAKES NO WARRANTY AND HAS NO LIABILITY ARISING FROM ANY USE OF THE
:: SOFTWARE IN ANY HIGH RISK OR STRICT LIABILITY ACTIVITIES.

:: The GPI launcher script. The .command suffix is used by OSX open.

:: get user environment settings
:: -this will pickup the user's visual editor

set ANACONDA=/opt/anaconda1anaconda2anaconda3
set PYTHON=%ANACONDA%\python
set GPI_LAUNCH=%ANACONDA%\Scripts\gpi_launch

%PYTHON% %GPI_LAUNCH% -style Windows %*


5 changes: 4 additions & 1 deletion lib/gpi/canvasGraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@
# start logger for this module
log = manager.getLogger(__name__)


class GraphWidget(QtWidgets.QGraphicsView):
'''Provides the main canvas widget and background painting as well as the
execution model for the canvas.'''
Expand Down Expand Up @@ -1624,6 +1623,10 @@ def rightButtonMenu(self, event):
menu.addAction(macroAct)
menu.addMenu(layoutMenu)
#menu.addSeparator()

# trigger a search menu close when the main menu is hovered
menu.hovered.connect(lambda: self._library.removeSearchPopup())

#quitAction = menu.addAction(quitAct)
action = menu.exec_(self.mapToGlobal(event.pos()))

Expand Down
31 changes: 18 additions & 13 deletions lib/gpi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,33 @@
from .associate import Bindings, BindCatalogItem
from gpi import VERSION
from .logger import manager
from .sysspecs import Specs

# start logger for this module
log = manager.getLogger(__name__)

GPIRC_FILENAME = '.gpirc'
# for windows
# GPIRC_FILENAME = 'gpi.conf'
if Specs.inWindows():
GPIRC_FILENAME = 'gpi.conf'
else:
GPIRC_FILENAME = '.gpirc'

### ENVIRONMENT VARIABLES
USER_HOME = os.environ['HOME']
USER_LIB_BASE_PATH_DEFAULT = USER_HOME+'/gpi'
if Specs.inWindows():
USER_HOME = os.path.expanduser('~')
else:
USER_HOME = os.environ['HOME']

USER_LIB_BASE_PATH_DEFAULT = os.path.join(USER_HOME, 'gpi')
try:
USER_LIB_PATH_DEFAULT = USER_LIB_BASE_PATH_DEFAULT+'/'+os.environ['USER']
USER_LIB_PATH_DEFAULT = os.path.join(USER_LIB_BASE_PATH_DEFAULT, os.environ['USER'])
except KeyError:
USER_LIB_PATH_DEFAULT = ''

ANACONDA_PREFIX='/opt/anaconda1anaconda2anaconda3' # is this needed?
GPI_PREFIX = os.path.dirname(os.path.realpath(__file__))
SP_PREFIX = os.path.dirname(GPI_PREFIX)

# for windows
# USER_HOME = os.path.expanduser('~')
GPI_NET_PATH_DEFAULT = USER_HOME
GPI_DATA_PATH_DEFAULT = USER_HOME
GPI_FOLLOW_CWD = True
Expand Down Expand Up @@ -85,16 +90,16 @@ def __init__(self):
# root dirs for organizing gpi related files.
self._c_networkDir = GPI_NET_PATH_DEFAULT
self._c_dataDir = GPI_DATA_PATH_DEFAULT
self._c_configFileName = os.path.expanduser('~/'+GPIRC_FILENAME)
self._c_configFileName = os.path.join(os.path.expanduser('~'), GPIRC_FILENAME)

# all the fix'ns for an initial lib
self._c_userLibraryBasePath = os.path.expanduser(USER_LIB_BASE_PATH_DEFAULT)
self._c_userLibraryPath = os.path.expanduser(USER_LIB_PATH_DEFAULT)
self._c_userLibraryPath_def = self._c_userLibraryPath+'/default'
self._c_userLibraryPath_def_GPI = self._c_userLibraryPath_def+'/GPI'
self._c_userLibraryPath_init = self._c_userLibraryPath+'/__init__.py'
self._c_userLibraryPath_def_init = self._c_userLibraryPath_def+'/__init__.py'
self._c_userLibraryPath_def_node = self._c_userLibraryPath_def_GPI+'/MyNode_GPI.py'
self._c_userLibraryPath_def = os.path.join(self._c_userLibraryPath, 'default')
self._c_userLibraryPath_def_GPI = os.path.join(self._c_userLibraryPath_def, 'GPI')
self._c_userLibraryPath_init = os.path.join(self._c_userLibraryPath, '__init__.py')
self._c_userLibraryPath_def_init = os.path.join(self._c_userLibraryPath_def, '__init__.py')
self._c_userLibraryPath_def_node = os.path.join(self._c_userLibraryPath_def_GPI, 'MyNode_GPI.py')

# env vars
self._c_gpi_lib_path = list(GPI_LIBRARY_PATH_DEFAULT)
Expand Down
Loading

0 comments on commit b1a6db3

Please sign in to comment.