diff --git a/__COPYRIGHT__.txt b/README-COPYRIGHT.txt similarity index 100% rename from __COPYRIGHT__.txt rename to README-COPYRIGHT.txt diff --git a/__LICENCE_utf-8__.txt b/README-LICENCE-utf8.txt similarity index 100% rename from __LICENCE_utf-8__.txt rename to README-LICENCE-utf8.txt diff --git a/standalone/NutriMorph-4-NT.zip b/standalone/NutriMorph-4-NT.zip new file mode 100644 index 0000000000000000000000000000000000000000..b53f969a74e3ffd25ddcbcf6ccc81e1eef219237 Binary files /dev/null and b/standalone/NutriMorph-4-NT.zip differ diff --git a/standalone/README-REQUIREMENTS.txt b/standalone/README-REQUIREMENTS.txt new file mode 100644 index 0000000000000000000000000000000000000000..cad6588be6ebb86b18fe7b67ba70ffc4a9743442 --- /dev/null +++ b/standalone/README-REQUIREMENTS.txt @@ -0,0 +1,39 @@ +# Requirements automatically generated by pigar. +# https://github.com/damnever/pigar + +# brick/general/feedback.py: 38 +# brick/processing/plot.py: 39,40 +# nutrimorph.py: 52 +matplotlib == 3.1.2 + +# brick/component/connection.py: 41 +# brick/component/extension.py: 41 +# brick/component/glial_cmp.py: 38 +# brick/component/soma.py: 42 +# brick/feature/features_ext.py: 32 +# brick/feature/features_soma.py: 32 +# brick/general/type.py: 34 +# brick/processing/dijkstra_1_to_n.py: 46 +# brick/processing/frangi3.py: 45 +# brick/processing/map_labeling.py: 34 +# brick/processing/plot.py: 41 +# nutrimorph.py: 53 +numpy == 1.18.1 + +# brick/component/extension.py: 42,43,44 +# brick/component/soma.py: 44,45,46 +# brick/feature/features_ext.py: 33 +# brick/feature/features_soma.py: 33 +# brick/processing/plot.py: 42 +# nutrimorph.py: 54,55 +# parameters.py: 32 +scikit_image == 0.16.2 + +# brick/feature/features_soma.py: 34 +scikit_learn == 0.22.1 + +# brick/component/extension.py: 45 +# brick/component/soma.py: 43 +# brick/processing/dijkstra_1_to_n.py: 47 +# brick/processing/frangi3.py: 46 +scipy == 1.4.1 diff --git a/standalone/auto-py-to-exe.json b/standalone/auto-py-to-exe.json deleted file mode 100644 index b606edd62933c47d97d09311df720d43ea72406c..0000000000000000000000000000000000000000 --- a/standalone/auto-py-to-exe.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "command_data":{ - "onefile":false, - "console":true, - "additional_files":{ - "addFiles_lbb4d":{ - "source":"C:/Users/eric/Documents/code/python-to-exe/nutrimorph/main_prm.py", - "destination":"." - }, - "addFiles_ouqe7j":{ - "source":"C:/Users/eric/Documents/code/python-to-exe/nutrimorph/frangi3-nt.so", - "destination":"." - } - } - }, - "id_injectable":{ - "file":"C:/Users/eric/Documents/code/python-to-exe/nutrimorph/main.py", - "icon":"", - "output_location":"C:/Users/eric/Documents/code/python-to-exe/nutrimorph/standalone", - "VALUE--upx-dir":"", - "VALUE--log-level":"", - "VALUE-n":"", - "VALUE--add-binary":"", - "VALUE-p":"", - "COMMASPLIT--hidden-import":"", - "VALUE--additional-hooks-dir":"", - "VALUE--runtime-hook":"", - "COMMASPLIT--exclude-module":"", - "VALUE--key":"", - "VALUE--debug":"", - "VALUE--version-file":"", - "VALUE-m":"", - "VALUE-r":"", - "VALUE--osx-bundle-identifier":"", - "VALUE--runtime-tmpdir":"", - "extra_command_data":"" - }, - "switches":{ - "disable_recursion_limit":false, - "OPTION-a":false, - "OPTION--clean":false, - "OPTION-s":false, - "OPTION--noupx":false, - "OPTION--uac-admin":false, - "OPTION--uac-uiaccess":false, - "OPTION--win-private-assemblies":false, - "OPTION--win-no-prefer-redirects":false, - "OPTION--bootloader-ignore-signals":false - } -} diff --git a/standalone/generate-w-pyinstaller.py b/standalone/generate-w-pyinstaller.py new file mode 100644 index 0000000000000000000000000000000000000000..343db6124f2703ebd2aa7b431937c41ab0075fb1 --- /dev/null +++ b/standalone/generate-w-pyinstaller.py @@ -0,0 +1,159 @@ +import glob as gb_ +import os as os_ +import os.path as ph_ +import shutil as sh_ +import subprocess as sp_ +import sys as sy_ +import zipfile as zp_ +from os import name as OS_NAME +from os import pathsep as PATH_SEP +from typing import Sequence, Union + +import pprint as pp_ +import PyInstaller.__main__ + + +PY_SCRIPT = "nutrimorph.py" +PARAMETERS = "parameters.py" +BRICK_FOLDER = "brick" +RES_PATH_CMPS = ("data",) +SRC_PATH_CMPS = ("..",) +README_PREFIX = "README" +RES_PREFIX = "DIO" + +DEP_LIST_DOC = f"{README_PREFIX}-REQUIREMENTS.txt" +REQUIREMENTS_MARKER = "Requires:" + +DIST_ROOT_FOLDER = "__dist__" +BUILD_ROOT_FOLDER = "__build__" +PER_OS_DIST_FOLDER = f"NutriMorph-4-{OS_NAME.upper()}" +DST_RES_FOLDER = "data" + + +def InBaseFolder(path: Union[str, Sequence[str]]) -> str: + # + if isinstance(path, str): + return ph_.realpath(ph_.join(*SRC_PATH_CMPS, path)) + else: + return ph_.realpath(ph_.join(*SRC_PATH_CMPS, *path)) + + +SCRIPT_NAME = ph_.splitext(PY_SCRIPT)[0] +PER_OS_DIST_FOLDER_PATH = ph_.join(DIST_ROOT_FOLDER, PER_OS_DIST_FOLDER) +PER_OS_and_SCRIPT_DIST_PATH = ph_.join(PER_OS_DIST_FOLDER_PATH, SCRIPT_NAME) +PER_OS_BUILD_FOLDER_PATH = ph_.join(BUILD_ROOT_FOLDER, OS_NAME) + +PY_SCRIPT_PATH = InBaseFolder(PY_SCRIPT) +PARAMETERS_PATH = InBaseFolder(PARAMETERS) +BRICK_FOLDER_PATH = InBaseFolder(BRICK_FOLDER) +RES_FOLDER_PATH = InBaseFolder(ph_.join(*RES_PATH_CMPS)) + +FRANGI3_PREFIX = "frangi3" +if OS_NAME == "nt": + # In Wine on Linux, realpath does not resolve symbolic links (2020-02-03) + FRANGI3_PY_FOLDER = r"G:\home\eric\Code\brick\def\frangi3\frangi_py" + assert ph_.isdir(FRANGI3_PY_FOLDER) +else: + FRANGI3_PY_FOLDER = ph_.dirname( + ph_.realpath(ph_.join(BRICK_FOLDER_PATH, "processing", f"{FRANGI3_PREFIX}.py")) + ) +DATA_ELEMENTS = ( + (BRICK_FOLDER_PATH, BRICK_FOLDER), + (PARAMETERS_PATH, "."), +) +BINARY_ELEMENTS = ( + (f"{ph_.join(FRANGI3_PY_FOLDER, FRANGI3_PREFIX)}-{OS_NAME}.so", "."), +) + +arguments = [ + f"--distpath={PER_OS_DIST_FOLDER_PATH}", + f"--specpath={PER_OS_BUILD_FOLDER_PATH}", + f"--workpath={PER_OS_BUILD_FOLDER_PATH}", + "--noconfirm", + "--onedir", + PY_SCRIPT_PATH, +] +for elm_type, elm_list in zip( + ("--add-data", "--add-binary"), (DATA_ELEMENTS, BINARY_ELEMENTS) +): + for element in elm_list: + arguments.insert( + arguments.__len__() - 1, f"{elm_type}={element[0]}{PATH_SEP}{element[1]}" + ) + +for resource in gb_.glob(ph_.join(RES_FOLDER_PATH, f"{RES_PREFIX}*.tif")): + arguments.insert( + arguments.__len__() - 1, f"--add-data={resource}{PATH_SEP}{DST_RES_FOLDER}" + ) + +dependencies = [] +with open(DEP_LIST_DOC) as doc_accessor: + for line in doc_accessor: + if (line.__len__() == 0) or line.isspace() or line.startswith("#"): + continue + module = line.split("=")[0].rstrip() + dependencies.append(module) + deps_info = sp_.check_output( + [sy_.executable, "-m", "pip", "show", module] + ).decode() + sub_deps = () + for dep_info in deps_info.split("\n")[:-1]: + # [:-1]: Excludes the last, empty line + if dep_info.startswith(REQUIREMENTS_MARKER): + dep_info_wo_marker = dep_info[REQUIREMENTS_MARKER.__len__() :] + if "," in dep_info_wo_marker: + sub_deps = dep_info_wo_marker.split(",") + elif not dep_info_wo_marker.isspace(): + sub_deps = [dep_info_wo_marker] + break + for sub_dep in sub_deps: + dependencies.append(sub_dep.strip()) +dependencies = sorted(set(dependencies)) +for dep in dependencies: + arguments.insert(arguments.__len__() - 1, f"--hidden-import={dep}") + +excluded_modules_w_version = sp_.check_output( + [sy_.executable, "-m", "pip", "freeze"] +).decode() +excluded_modules = [] +for module in excluded_modules_w_version.split("\n")[:-1]: + # [:-1]: Excludes the last, empty line + excluded_modules.append(module.split("=")[0]) +excluded_modules = set(excluded_modules) - set(dependencies) +for module in excluded_modules: + arguments.insert(arguments.__len__() - 1, f"--exclude-module={module}") + +for readme in gb_.glob(InBaseFolder(f"{README_PREFIX}*")): + readme = ph_.realpath(readme) + arguments.insert(arguments.__len__() - 1, f"--add-data={readme}{PATH_SEP}.") + +if OS_NAME == "nt": + arguments.insert(arguments.__len__() - 1, "--console") + +print("--- Launching PyInstaller with arguments:") +pp_.pprint(arguments) +PyInstaller.__main__.run(arguments) + +print("--- Moving/copying elements into place") +if OS_NAME == "nt": + sh_.copy(f"{SCRIPT_NAME}.bat", PER_OS_DIST_FOLDER_PATH) +else: + print(f" /!\\ TODO: MAKE a SHELL SCRIPT for {OS_NAME.upper()} and COPY IT") +sh_.move(ph_.join(PER_OS_and_SCRIPT_DIST_PATH, PARAMETERS), PER_OS_DIST_FOLDER_PATH) +sh_.move(ph_.join(PER_OS_and_SCRIPT_DIST_PATH, DST_RES_FOLDER), PER_OS_DIST_FOLDER_PATH) +for readme in gb_.glob(ph_.join(PER_OS_and_SCRIPT_DIST_PATH, f"{README_PREFIX}*")): + sh_.move(readme, PER_OS_DIST_FOLDER_PATH) + +print("--- Creating ZIP archive") +with zp_.ZipFile( + ph_.join(DIST_ROOT_FOLDER, f"{PER_OS_DIST_FOLDER}.zip"), + mode="w", + compression=zp_.ZIP_DEFLATED, + compresslevel=9, +) as archive: + for folder, _, documents in os_.walk(PER_OS_DIST_FOLDER_PATH): + for document in documents: + doc_path = ph_.join(folder, document) + archive.write( + doc_path, arcname=ph_.relpath(doc_path, start=DIST_ROOT_FOLDER) + ) diff --git a/standalone/lin-to-win.txt b/standalone/lin-to-win.txt deleted file mode 100644 index 9ab12e4e5f256a6294e5c2b56de4aa4b00188516..0000000000000000000000000000000000000000 --- a/standalone/lin-to-win.txt +++ /dev/null @@ -1,16 +0,0 @@ -Remove all brick... hierarchy in imports -Remove hierarchy in c-extension loading in frangi3.py -Change name nutrimorph.py into main.py -Change name parameters.py into main_prm.py -In main.py (re-check necessity periodically as this should not be necessary): - > import tifffile - Then - < assert image.ndim == 3 # TODO: replace assertion with proper exception handling - --- - > if image.ndim == 4: - > image = image[:,:,:,0] - > assert image.ndim == 3, f"Image dimension: {image.ndim}={image.shape}, expected 3" - ---- Some random notes (should be obsolete) - -If tifffile is missing, then DIO_6H_6_1.70bis_2.2_3.tif, when read with skimage.imread, appears as a 4-D (last dim=color) image which only contains zeros in the first channel. diff --git a/standalone/setup.py b/standalone/setup.py deleted file mode 100644 index 93728a2f0680d4e21fdd3da6854fb221e990d728..0000000000000000000000000000000000000000 --- a/standalone/setup.py +++ /dev/null @@ -1,11 +0,0 @@ -from distutils.core import setup - -import numpy as np_ -from Cython.Build import cythonize - - -setup( - ext_modules=cythonize("frangi_3d.py"), - requires=["numpy", "scipy"], - include_dirs=[np_.get_include()], -)