diff --git a/examples/dyneusr_fire/run_dyneusr.sh b/examples/dyneusr_fire/run_dyneusr.sh new file mode 100755 index 0000000..66b2027 --- /dev/null +++ b/examples/dyneusr_fire/run_dyneusr.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# example command-line +dyneusr-fire load_data --X trefoil.npy --y trefoil-target.npy - run_mapper - visualize \ No newline at end of file diff --git a/examples/dyneusr_fire/run_dyneusr_interactive.sh b/examples/dyneusr_fire/run_dyneusr_interactive.sh new file mode 100755 index 0000000..7db4d71 --- /dev/null +++ b/examples/dyneusr_fire/run_dyneusr_interactive.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# example command-line +dyneusr-fire init -- --interactive \ No newline at end of file diff --git a/examples/dyneusr_fire/trefoil-target.npy b/examples/dyneusr_fire/trefoil-target.npy new file mode 100644 index 0000000..4c52200 Binary files /dev/null and b/examples/dyneusr_fire/trefoil-target.npy differ diff --git a/examples/dyneusr_fire/trefoil.npy b/examples/dyneusr_fire/trefoil.npy new file mode 100644 index 0000000..6397bfc Binary files /dev/null and b/examples/dyneusr_fire/trefoil.npy differ diff --git a/requirements-conda.txt b/requirements-conda.txt index 0677bb9..d72554f 100644 --- a/requirements-conda.txt +++ b/requirements-conda.txt @@ -8,3 +8,6 @@ scikit-learn matplotlib seaborn networkx +umap-learn +hdbscan +fire diff --git a/requirements-versions.txt b/requirements-versions.txt index 7a51581..36022c4 100644 --- a/requirements-versions.txt +++ b/requirements-versions.txt @@ -12,3 +12,6 @@ seaborn==0.9.0 networkx==2.2 nilearn==0.5.0a kmapper==1.2.0 +umap-learn +hdbscan +fire diff --git a/requirements.txt b/requirements.txt index 3bd25df..d45b1d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,6 @@ seaborn networkx nilearn kmapper>=1.2 +umap-learn +hdbscan +fire diff --git a/scripts/dyneusr-fire b/scripts/dyneusr-fire new file mode 100755 index 0000000..676e094 --- /dev/null +++ b/scripts/dyneusr-fire @@ -0,0 +1,166 @@ +#!/usr/bin/env python + +import numpy as np +import pandas as pd +from sklearn.datasets.base import Bunch +from sklearn.preprocessing import MinMaxScaler, StandardScaler +from sklearn.cluster import KMeans, DBSCAN +from sklearn.decomposition import PCA +from sklearn.manifold import TSNE +from umap.umap_ import UMAP +from hdbscan import HDBSCAN +from kmapper import KeplerMapper, Cover +from dyneusr import DyNeuGraph + +def check_estimator(estimator): + """Check estimator and process if not valid. + """ + if isinstance(estimator, str): + try: + estimator = eval(estimator) + except NameError as e: + # TOOD: show use a list of valid estimators + print('valid projections: PCA, TSNE, UMAP') + print('valid scalers: MinMaxScaler, StandardScaler') + print('valid clusterers: KMeans, DBSCAN, HDBSCAN') + raise e + return estimator + + +class DyNeuSR(object): + + def init(self): + return self + + def load_data(self, X=None, y=None): + """Load the data. + + Parameters + ---------- + X : str + Filename of data matrix to load. + + y : str, optional + Filename of meta data to load. + + """ + # Helper functions + def check_array_from_file(fp): + print("Loading data from file:", fp) + d = None + if str(fp).endswith('.npy'): + d = np.load(fp) + elif str(fp).endswith('.npz'): + d = np.loadz(fp) + d = d[list(d.keys())[0]] + elif str(fp).endswith('.tsv'): + d = pd.read_table(fp) + elif str(fp).endswith('.csv'): + d = pd.read_csv(fp) + elif str(fp).endswith('.txt'): + d = np.genfromtxt(fp) + else: + print('Data format not recognized ...') + print('Please use an accepted format:') + print('\t.npy') + print('\t.npz') + print('\t.tsv') + print('\t.csv') + print('\t.txt') + return d + + # Load the data from a file. + X = check_array_from_file(X) + y = check_array_from_file(y) + dataset = Bunch(data=X, target=y) + + # Store as variables + self.dataset = dataset + self.X = X + self.y = y + return self + + + def load_example(self, size=100): + """Load the data. + + TODO + ---- + - generalize to load any dataset supplied by the user + + """ + # Generate synthetic dataset (for now) + from dyneusr.datasets import make_trefoil + dataset = make_trefoil(size=size) + X = dataset.data + y = dataset.target + + # Store variables + self.dataset = dataset + self.X = X + self.y = y + return self + + + def run_mapper(self, + projection=TSNE(2), + scaler=MinMaxScaler(), + resolution=6, gain=0.2, + clusterer=KMeans(2), + verbose=1): + """Run KeplerMapper. + """ + # Generate shape graph using KeplerMapper + mapper = KeplerMapper(verbose=verbose) + + # Check estimators + self._projection = check_estimator(projection) + self._scaler = check_estimator(scaler) + self._cover = Cover(resolution, gain) + self._clusterer = check_estimator(clusterer) + + # Run kmapper + lens = mapper.fit_transform( + self.X, + projection=self._projection, + scaler=self._scaler + ) + graph = mapper.map( + lens, self.X, + cover=self._cover, + clusterer=self._cluster + ) + + # Store results + self.lens = lens + self.graph = graph + return self + + + def visualize(self, + save_as='dyneusr_output.html', + template=None, + static=True, + show=True, + port=None): + """Visualize the graph using DyNeuSR + """ + # Visualize the shape graph using DyNeuSR's DyNeuGraph + dG = DyNeuGraph(G=self.graph, y=self.y) + dG.visualize( + save_as, + template=template, + static=static, + show=show, + port=port + ) + + # Store the results + self.dG = dG + return self + + + +if __name__=='__main__': + import fire + fire.Fire(DyNeuSR) diff --git a/setup.py b/setup.py index 5a115c7..6f8c8b7 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ from setuptools import find_packages, setup import re +import os # parse dyneusr/_version.py try: @@ -25,6 +26,7 @@ setup( name='dyneusr', version=version, + scripts=[os.path.join('scripts/dyneusr-fire')], description='Dynamical Neural Spatiotemporal Representations.', long_description=long_description, long_description_content_type="text/markdown",