diff --git a/README.md b/README.md index b0522b4..998a5f4 100644 --- a/README.md +++ b/README.md @@ -239,5 +239,10 @@ if __name__ == '__main__': ``` +## Version History + +v. 0.1. 2/26/2018. Initial public release + + diff --git a/prism/__init__.py b/prism/__init__.py index ccaf8f6..7d3c0ad 100755 --- a/prism/__init__.py +++ b/prism/__init__.py @@ -17,8 +17,9 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism -__version__ = '0.0.21' +__version__ = '0.1' #----------------------------------------------------------------------------- # Imports diff --git a/prism/common_funcs.py b/prism/common_funcs.py index 98e4310..c3c11ec 100644 --- a/prism/common_funcs.py +++ b/prism/common_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- from __future__ import division @@ -24,7 +25,7 @@ ##------------------------------------------------------------- def get_X(img, Lc): """ - This function ... + This function computes distributions of backscatter according to each unique substrate """ D = [] counter = 0 @@ -51,7 +52,10 @@ def get_X(img, Lc): ##------------------------------------------------------------- def get_sparse_labels(bs, bed, buff): """ - This function ... + This function generates a sparse label map by assigning + unique numeric codes to portions of a matrix of identical + size to the backscatter inputs, according to the locations + of bed observations and a buffer distance """ ## make sparse labels Lc = np.zeros(np.shape(bs[0]['bs']))+99 diff --git a/prism/crf_funcs.py b/prism/crf_funcs.py index 3a819fc..703a4f4 100644 --- a/prism/crf_funcs.py +++ b/prism/crf_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- from __future__ import division @@ -28,7 +29,7 @@ ##------------------------------------------------------------- def set_unary_from_labels(fp, lp, prob, labels): """ - This function ... + This function sets unary potentials according to the label matrix """ H = fp.shape[0] W = fp.shape[1] @@ -43,7 +44,8 @@ def set_unary_from_labels(fp, lp, prob, labels): ##------------------------------------------------------------- def set_feats_both(d, fp, scol, compat_col, sspat, compat_spat): """ - This function ... + This function generates features according to both spatial and + amplitude kernels """ d = set_feats_spat(d, sspat, compat_spat, mode) @@ -54,7 +56,7 @@ def set_feats_both(d, fp, scol, compat_col, sspat, compat_spat): ##------------------------------------------------------------- def set_feats_spat(d, sspat, compat_spat): """ - This function ... + This function generates features according to spatial kernel """ d.addPairwiseGaussian(sxy=sspat, compat=compat_spat) @@ -64,7 +66,7 @@ def set_feats_spat(d, sspat, compat_spat): ##------------------------------------------------------------- def set_feats_col(fp, d, scol, compat_col): """ - This function ... + This function generates features according to amplitude kernel """ scale = 1 @@ -88,7 +90,10 @@ def set_feats_col(fp, d, scol, compat_col): ##------------------------------------------------------------- def inference(d, n_iter, H, W, labels): """ - This function ... + This function carries out the CRF inference, generating a MAP + substrate matrix, a conservative probabilistic map based on + frequentist principles, and a probability per substrate based on + the CRF inference """ R = [] ; Q, tmp1, tmp2 = d.startInference() @@ -115,7 +120,7 @@ def inference(d, n_iter, H, W, labels): ##------------------------------------------------------------- def apply_CRF(fp, lp, labels, n_iter, prob_thres, scol, compat_col): """ - This function ... + This function generates CRF-derived substrate map and probability map """ prob = 0.51 # initial probability of unary labels diff --git a/prism/data/README.md b/prism/data/README.md new file mode 100644 index 0000000..3327adf --- /dev/null +++ b/prism/data/README.md @@ -0,0 +1,6 @@ +Two data sets are provided with the toolbox for users to experiment with. The data come from 1) Patricia Bay, British Columbia, Canada, and 2) lower Portsmouth Harbor, New Hampshire, USA. All example backscatter data (.tiff files) originate from data collected by R2Sonic and distributed for use as part of the R2Sonic 2017 Multispectral Backscatter competition. Bed observation data from Patricia Bay are digitized from data presented in: + +B. Biffard. Seabed remote sensing by single-beam echosounder: models, methods and applications. Doctoral dissertation, University of Victoria, Canada, 2011. +Bed observation data from Portsmouth (NEWBEX) are digitized from data presented in: + +T. Weber, and L. Ward. Observations of backscatter from sand and gravel seafloors between 170 and 250 kHz. Journal of the Acoustical Society of America, vol. 138, no. 4, pp. 2169 - 2180, 2015. diff --git a/prism/eval_funcs.py b/prism/eval_funcs.py index ad66a40..fa84dd3 100644 --- a/prism/eval_funcs.py +++ b/prism/eval_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- import matplotlib.pyplot as plt @@ -66,7 +67,7 @@ def plot_confusion_matrix(cm, classes, ##------------------------------------------------------------- def plot_confmatGMM(y_pred, Lc, bed, prefix): """ - This function ... + This function generates and plots a confusion matrix for GMM model """ #base = '..'+os.sep+'outputs'+os.sep+prefix+'_' @@ -112,7 +113,7 @@ def plot_confmatGMM(y_pred, Lc, bed, prefix): ##------------------------------------------------------------- def plot_confmatCRF(y_pred, Lc, bed, prefix): """ - This function ... + This function generates and plots a confusion matrix for CRF model """ #base = '..'+os.sep+'outputs'+os.sep+prefix+'_' diff --git a/prism/gmm_funcs.py b/prism/gmm_funcs.py index ff4f36e..65e394f 100644 --- a/prism/gmm_funcs.py +++ b/prism/gmm_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- from __future__ import division @@ -31,7 +32,8 @@ ##------------------------------------------------------------- def fit_GMM(img, Lc, test_size, covariance, tol): """ - This function ... + This function fits a simple GMM model to the backscatter data + and associated labels """ D, l = get_X(img, Lc) @@ -55,8 +57,10 @@ def fit_GMM(img, Lc, test_size, covariance, tol): ##------------------------------------------------------------- def apply_GMM(g, img, prob_thres): """ - This function ... + This function fits applies a GMM model to generate a substrate and + associated probability map """ + print('Estimating substrates ...') if np.ndim(img)>2: #multispectral diff --git a/prism/gui_funcs.py b/prism/gui_funcs.py index 9a05a6d..e9d0b65 100644 --- a/prism/gui_funcs.py +++ b/prism/gui_funcs.py @@ -17,7 +17,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| - +# https://github.com/dbuscombe-usgs/prism # general from __future__ import division @@ -70,7 +70,9 @@ ##------------------------------------------------------------- def gui(): - + """ + This function creates the GUI + """ #======================= # NOTE: Frame will make a top-level window if one doesn't already exist which # can then be accessed via the frame's master attribute @@ -241,7 +243,7 @@ def gui(): #======================= def _proc(self): """ - this function ... + this function allows the user read the data in """ infiles = self.DATfilename.get().split() input = [] @@ -290,7 +292,7 @@ def _proc(self): #======================= def _get_DAT(master, v): """ - this function ... + this function allows the user to select backscatter file(s) """ self.DATfile = askopenfilename(filetypes=[("Backscatter data files","*.tif *.tiff *.TIF *.TIFF")], multiple=True) @@ -303,7 +305,7 @@ def _get_DAT(master, v): #======================= def _get_BED(master, v): """ - this function ... + this function allows the user to select reference (bed observations) file """ self.bedfile = askopenfilename(filetypes=[("Bed data files","*.shp *.csv")], multiple=False) @@ -397,7 +399,7 @@ def _get_BED(master, v): #======================= def _procGMM(self): """ - this function ... + this function runs the GMM model """ if self.covvar.get()==1: cov = 'full' @@ -506,7 +508,7 @@ def _procGMM(self): #======================= def _procCRF(self): """ - this function ... + this function runs the CRF model """ print('Iterations: %g' % self.nvar.get()) print('Prob. threshold: %g' % self.pvar.get()) @@ -659,7 +661,7 @@ def _procCRF(self): # must press enter to set def _OnPressEnter1(self): """ - sets prefix for file names on Enter press + this function sets prefix for file names on Enter press """ self.prefix.set( self.prefix.get() ) self.prefix_entry.focus_set() @@ -669,6 +671,9 @@ def _OnPressEnter1(self): #======================= def _get_cmap(self): + """ + this function generates a colormap based on the number of unique labels + """ cmap = plt.get_cmap('tab20b',len(self.bed['labels'])-1).colors cmap1 = [] @@ -680,7 +685,7 @@ def _get_cmap(self): #======================= def _pick_cmap(self): """ - this function ... + this function allows the user to pick a color map for each substrate """ labs = self.bed['labels'] #['1', '2', '3', '4'] # @@ -701,7 +706,7 @@ def _pick_cmap(self): #======================= def _plot_gmm(self): """ - this function ... + this function makes plots of GMM results """ if hasattr(self, 'cmap'): @@ -733,7 +738,7 @@ def _plot_gmm(self): #======================= def _plot_crf(self): """ - this function ... + this function makes plots of CRF results """ if hasattr(self, 'cmap'): @@ -761,11 +766,10 @@ def _plot_crf(self): tkMessageBox.showinfo("Done!", "Plot made") - #======================= def _plot_gmm_image(self): """ - this function ... + this function makes plots of GMM results with underlying image (requires basemap) """ if hasattr(self, 'cmap'): @@ -796,7 +800,7 @@ def _plot_gmm_image(self): #======================= def _plot_crf_image(self): """ - this function ... + this function makes plots of CRF results with underlying image (requires basemap) """ if hasattr(self, 'cmap'): in1 = self.y_pred_crf.copy() @@ -826,7 +830,7 @@ def _plot_crf_image(self): #======================= def _plot_gmm_crf(self): """ - this function ... + this function makes plots of GMM and CRF results side by side """ if hasattr(self, 'y_pred_gmm') and hasattr(self, 'y_pred_crf'): in1 = self.y_pred_gmm.copy() @@ -859,7 +863,7 @@ def _plot_gmm_crf(self): #======================= def _plot_gmm_crf_images(self): """ - this function ... + this function makes plots of GMM and CRF results side by side with underlying image (requires basemap) """ if hasattr(self, 'y_pred_gmm') and hasattr(self, 'y_pred_crf'): @@ -893,7 +897,7 @@ def _plot_gmm_crf_images(self): #======================= def _plot_dists_per_sed(self): """ - this function ... + this function plots the distributions of backscatter per substrate """ if hasattr(self, 'cmap'): plot_dists_per_sed(self.Lc.copy(), self.img, self.bed, self.cmap, self.prefix.get()) @@ -914,7 +918,7 @@ def _plot_dists_per_sed(self): #======================= def _plot_bs(self): """ - this function ... + this function plots backscatter maps """ if hasattr(self, 'cmap'): plot_bs_maps(self.img, self.bed, self.bs, self.cmap, self.prefix.get()) @@ -934,7 +938,7 @@ def _plot_bs(self): #======================= def _plot_cm_gmm(self): """ - this function ... + this function plots GMM confusion matrix """ if hasattr(self, 'y_pred_gmm'): @@ -955,7 +959,7 @@ def _plot_cm_gmm(self): #======================= def _plot_cm_crf(self): """ - this function ... + this function plots CRF confusion matrix """ if hasattr(self, 'y_pred_crf'): @@ -1054,7 +1058,9 @@ def _plot_cm_crf(self): #======================= def _export1(self): - + """ + this function exports both CRF and GMM substrate maps + """ if hasattr(self, 'y_pred_gmm') and hasattr(self, 'y_pred_crf'): in1 = self.y_pred_gmm.copy() @@ -1076,6 +1082,10 @@ def _export1(self): #======================= def _export2(self): + """ + this function exports both CRF and GMM substrate maps and all + bed observation data + """ if hasattr(self, 'y_pred_gmm') and hasattr(self, 'y_pred_crf'): in1 = self.y_pred_gmm.copy() @@ -1100,6 +1110,9 @@ def _export2(self): #======================= def _export3(self): + """ + this function exports GMM substrate maps + """ if hasattr(self, 'y_pred_gmm'): in1 = self.y_pred_gmm.copy() @@ -1116,7 +1129,9 @@ def _export3(self): #======================= def _export4(self): - + """ + this function exports CRF substrate maps + """ if hasattr(self, 'y_pred_crf'): in1 = self.y_pred_crf.copy() @@ -1133,7 +1148,9 @@ def _export4(self): #======================= def _export5(self): - + """ + this function exports bed observation data + """ if hasattr(self, 'bed'): export_bed_data(self.bed, self.prefix.get()) diff --git a/prism/plot_funcs.py b/prism/plot_funcs.py index 265b846..ed95be6 100644 --- a/prism/plot_funcs.py +++ b/prism/plot_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- from __future__ import division @@ -37,7 +38,7 @@ ##------------------------------------------------------------- def plot_bs_maps(img, bed, bs, cmap, prefix): """ - This function ... + This function plots backscatter maps """ lonmin = bs[0]['lonmin'] @@ -104,7 +105,7 @@ def plot_bs_maps(img, bed, bs, cmap, prefix): ##------------------------------------------------------------- def plot_dists_per_sed(Lc, img, bed, cmap, prefix): """ - This function ... + This function plots the distributions of backscatter per substrate """ #base = '..'+os.sep+'outputs'+os.sep+prefix+'_' @@ -197,7 +198,7 @@ def plot_dists_per_sed(Lc, img, bed, cmap, prefix): ##------------------------------------------------------------- def plot_gmm(mask, y_pred, y_prob, bs, bed, cmap, prefix): """ - This function ... + This function makes plots of GMM results """ y_prob[mask==1] = np.nan @@ -305,7 +306,7 @@ def plot_gmm(mask, y_pred, y_prob, bs, bed, cmap, prefix): ##------------------------------------------------------------- def plot_gmm_image(mask, y_pred, y_prob, bs, bed, cmap, prefix): """ - This function ... + This function makes plots of GMM results with underlying image (requires basemap) """ y_prob[mask==1] = np.nan @@ -427,7 +428,7 @@ def plot_gmm_image(mask, y_pred, y_prob, bs, bed, cmap, prefix): ##------------------------------------------------------------- def plot_crf(mask, y_pred, y_prob, bs, bed, cmap, prefix): """ - This function ... + This function makes plots of CRF results """ y_prob[mask==1] = np.nan @@ -535,7 +536,7 @@ def plot_crf(mask, y_pred, y_prob, bs, bed, cmap, prefix): ##------------------------------------------------------------- def plot_crf_image(mask, y_pred, y_prob, bs, bed, cmap, prefix): """ - This function ... + This function makes plots of CRF results with underlying image (requires basemap) """ y_prob[mask==1] = np.nan y_pred[mask==1] = np.nan @@ -656,7 +657,7 @@ def plot_crf_image(mask, y_pred, y_prob, bs, bed, cmap, prefix): ##------------------------------------------------------------- def plot_gmm_crf(mask, y_pred_gmm, y_prob_gmm, y_pred_crf, y_prob_crf, bs, bed, cmap, prefix): """ - This function ... + This function makes plots of GMM and CRF results side by side """ y_prob_gmm[mask==1] = np.nan y_pred_gmm[mask==1] = np.nan @@ -844,7 +845,7 @@ def plot_gmm_crf(mask, y_pred_gmm, y_prob_gmm, y_pred_crf, y_prob_crf, bs, bed, ##------------------------------------------------------------- def plot_gmm_crf_images(mask, y_pred_gmm, y_prob_gmm, y_pred_crf, y_prob_crf, bs, bed, cmap, prefix): """ - This function ... + This function makes plots of GMM and CRF results side by side with underlying image (requires basemap) """ y_prob_gmm[mask==1] = np.nan y_pred_gmm[mask==1] = np.nan diff --git a/prism/read_funcs.py b/prism/read_funcs.py index c0b742d..025725f 100644 --- a/prism/read_funcs.py +++ b/prism/read_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- from __future__ import division @@ -31,7 +32,7 @@ ##------------------------------------------------------------- def read_csvfile(refs_file, bs): """ - This function ... + This function reads bed observations from a csv file. Fields must be X, Y, ID """ dat = np.genfromtxt(refs_file, delimiter=',', names=True, dtype=[float, float, float, "|S10"] ) @@ -103,7 +104,7 @@ def read_csvfile(refs_file, bs): ##------------------------------------------------------------- def read_shpfile(refs_file, bs): """ - This function ... + This function reads bed observations from a shapefile (.shp) file. """ print('Reading and filtering bed observation data ...') @@ -191,7 +192,9 @@ def read_shpfile(refs_file, bs): ##------------------------------------------------------------- def read_geotiff(input, gridres, chambolle): """ - This function ... + This function reads backscatter in GeoTIFF format. For monospectral data, + this is a single .tiff file containing a 2D grid. For multispectral data, + this is multiple .tiff files, each containing a 2D grid """ ## input = list of strings of filenames ## output gridres = grd resolution in m diff --git a/prism/test.py b/prism/test.py index dc643da..b6e885e 100644 --- a/prism/test.py +++ b/prism/test.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- # general @@ -42,6 +43,10 @@ import errno def dircopy(src, dest): + """ + This function copies data files to a directory accessible by the program (and the user) + which is the home diirectory of the user + """ try: shutil.copytree(src, dest) except OSError as e: @@ -58,7 +63,12 @@ def dircopy(src, dest): ##------------------------------------------------------------- def dotest(): - + """ + This function carries out a suite of tests of the program + on NEWBEX and Patricia Bay data, illustrating the full + functionality of the program as an API + Commented plotting functions require basemap and an internet connection + """ # copy files over to somewhere read/writeable dircopy(prism.__path__[0], os.path.expanduser("~")+os.sep+'prism_test') diff --git a/prism/write_funcs.py b/prism/write_funcs.py index 0b18f8e..75d1b1c 100644 --- a/prism/write_funcs.py +++ b/prism/write_funcs.py @@ -16,6 +16,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism ##------------------------------------------------------------- from osgeo import gdal,ogr,osr @@ -29,7 +30,8 @@ ##------------------------------------------------------------- def export_bed_data(bed, prefix): """ - This function ... + This function writes bed observations from within the surveyed extent + to a csv file, and shapefile with associated proj projection """ #base = '..'+os.sep+'outputs'+os.sep+prefix+'_' @@ -67,7 +69,8 @@ def export_bed_data(bed, prefix): ##------------------------------------------------------------- def export_crf_gtiff(mask, y_pred, y_prob, bs, prefix): """ - This function ... + This function writes the CRF substrate and probability maps + to GeoTIFF format """ prob = y_prob.copy() @@ -138,7 +141,8 @@ def export_crf_gtiff(mask, y_pred, y_prob, bs, prefix): ##------------------------------------------------------------- def export_gmm_gtiff(mask, y_pred, y_prob, bs, prefix): """ - This function ... + This function writes the GMM substrate and probability maps + to GeoTIFF format """ prob = y_prob.copy() pred = y_pred.copy() diff --git a/setup.py b/setup.py index 9605358..870650d 100755 --- a/setup.py +++ b/setup.py @@ -18,6 +18,7 @@ # |b|y| |D|a|n|i|e|l| |B|u|s|c|o|m|b|e| # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # |d|a|n|i|e|l|.|b|u|s|c|o|m|b|e|@|n|a|u|.|e|d|u| +# https://github.com/dbuscombe-usgs/prism #----------------------------------------------------------------------------- # Imports @@ -48,6 +49,9 @@ ] #'basemap', 'pydensecrf', 'GDAL' def setupPackage(): + """ + This function installs the package + """ setup(name='prism_mbes', version=__version__, description='Buscombe, D., 2017',