diff --git a/.gitignore b/.gitignore index 0de9cb9..65a86c9 100644 --- a/.gitignore +++ b/.gitignore @@ -49,7 +49,11 @@ htmlcov/ .cache nosetests.xml coverage.xml +<<<<<<< HEAD +.pytest_cache/ +======= .pytest_cache/* +>>>>>>> master # Translations *.mo @@ -59,8 +63,7 @@ coverage.xml *.log # Sphinx documentation -# */_sources/* -# *.rst.txt +docs/build/ # PyBuilder target/ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..3279f80 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +This software was developed by employees of the National Institute of Standards +and Technology (NIST), an agency of the Federal Government. Pursuant to +[title 17 United States Code Section 105](http://www.copyright.gov/title17/92chap1.html#105), +works of NIST employees are not subject to copyright protection in the United States and are +considered to be in the public domain. Permission to freely use, copy, modify, +and distribute this software and its documentation without fee is hereby granted, +provided that this notice and disclaimer of warranty appears in all copies. + +THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER +EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY +THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, +AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY +WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NIST BE LIABLE +FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR +CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED +WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT, OR +OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR +OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE +RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. \ No newline at end of file diff --git a/NONLICENSE.md b/NONLICENSE.md deleted file mode 100644 index 1d4b574..0000000 --- a/NONLICENSE.md +++ /dev/null @@ -1,12 +0,0 @@ -This software was developed at the National Institute of Standards and Technology (NIST) by -employees of the Federal Government in the course of their official duties. Pursuant to -[Title 17 Section 105 of the United States Code](http://www.copyright.gov/title17/92chap1.html#105), -this software is not subject to copyright protection and is in the public domain. -NIST assumes no responsibility whatsoever for use by other parties of its source code, -and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. - -Specific software products identified in this open source project were used in order -to perform technology transfer and collaboration. In no case does such identification imply -recommendation or endorsement by the National Institute of Standards and Technology, nor -does it imply that the products identified are necessarily the best available for the -purpose. \ No newline at end of file diff --git a/README.md b/README.md index 7c91728..9cf429b 100644 --- a/README.md +++ b/README.md @@ -27,26 +27,17 @@ Note: These are the developmental system specs. Older versions of certain packages may work. * python >= 3.4 - * Tested with 3.4.4, 3.5.2, 3.6.1 -* SciPlot-PyQt >= 0.1.3 (>=0.1.4 for MPL2) + * Tested with 3.4.4, 3.5.2, 3.6.1, 3.7.2 +* NumPy +* PyQT5 + +* CVXOPT +* LazyHDF5 >= 0.2.1 + * Requires H5Py (>= 2.6) +* SciPlot-PyQt >= 0.2.2 * https://github.com/CCampJr/SciPlot-PyQt/releases -* numpy (1.9.3) - * Tested with 1.11.3+mkl -* PyQT5 (5.5.* or 5.6.*) - * Tested with 5.6, 5.8.1 -* matplotlib (1.5.0rc3, 2.0.0) (see below for MPL2) - * Tested with 1.5.2, 2.0.0 -* cvxopt (1.1.7) - * Tested with 1.1.7, 1.1.9 -* h5py (2.5) - * Tested with 2.6, 2.7 -* Sphinx (1.5.2) (Only for building documentation) - * Tested with 1.4.5, 1.6.4 - -### IMPORTANT: For Matplotlib 2 ### -You will need to use SciPlot-PyQT v0.1.4 -* Matplotlib 2 made numerous changes and deprecations that are being resolved -* See the installation instruction in the README.md file at https://github.com/CCampJr/SciPlot-PyQt + * Requires Matplotlib (v1.*, 2.*, or 3.*) +* Sphinx (only to build docs locally) ### IMPORTANT: For Python 3.4 ### You will need to manually install PyQt5 and Qt5 or get it through a distribution @@ -63,9 +54,6 @@ There is a bug in PyQt 5.7.* that will prevent SciPlot's tables from showing the * As WinPython 3.5.2.3Qt5 and 3.5.2.2Qt5 use PyQt 5.7.*, it is advised to use WinPython 3.5.2.1Qt5 or 3.4.4.5Qt5 until the matter is sorted out. * Alternatively, one can uninstall pyqt5.7.* and force an install of <= 5.6.*. -## SciPlot-PyQt ## -Currently, SciPlot >= 0.1.3 is not available through pip. You can however clone the repository from github. -(see https://github.com/CCampJr/SciPlot-PyQt) ## Installation ## ### Option 1: Easily updatable through git (dynamic copy)### diff --git a/TODO.md b/TODO.md index e52ce56..a2e246a 100644 --- a/TODO.md +++ b/TODO.md @@ -3,14 +3,16 @@ * Implement logging * Continue development of out-of-core analysis package * Carryover database package from SW into standalone and integrate +* GUI adjusts to screen resolution appropriately # Adjustment for External Package Updates -* Enhance ~~Implement~~ MPL2 testing and API (such as ax.hold deprecation) +* ~~Enhance ~~Implement~~ MPL2 testing and API (such as ax.hold deprecation)~~ # Enhancements * Carryover SVD auto-selection tools from SW package * Add rng functionality to all fcns * Move from ALS-only to ALS/ArPLS detrending +* Select sub-set of dark and NRB spectra # Minor updates * Fix model to use way less memory (and test 64 vs 128-bit complex) @@ -22,4 +24,29 @@ for now * ~~Minimum in qt_GrayScaleImgInfoBar is set to 0 -- needs to allow negative~~ * Undo also resets freq window (ie track frequency window settings) -* Re-evaluate how poisson noise is added to model inline. Very math-operation-order dependent. \ No newline at end of file +* Re-evaluate how poisson noise is added to model inline. Very math-operation-order dependent. + +# TODO +* ~~Tab describing history of processing steps~~ +* Create a set of feature-finding/selecting classes to take a lot of the computation out of the dialogSVD UI +* ~~Dark mean and fill-between~~ +* ~~NRB, L/R-NRB mean and fill-between~~ +* Delete linked plots (Delete all in-family) +* ~~Loading spectra/hsi into a spectrum averages~~ + * ~~Move from io.hdf5 to data.spectrum~~ +* Testing of spectrum, spectra, hsi when op_range defined +* Calculate Anscombe parameters +* Check bugs in SVD script text +* ~~When loading Dark or NRB, auto-open same HDF file as HSI. Cancel reverts to fileview~~ +* ~~Rename load file GUI title to whatever is being loaded (NRB, Dark, etc)~~ +* ~~Tab to view already performed tasks~~ + + +# REFACTORS +* ~~io.hdf5~~ + +# Known bugs +* spectrum, spectra, and hsi may only work properly when the spectral axis is -1 + * Test files only check axis = -1 case +* ~~subtract dark doesn't work when dark is multiple spectra~~ +* Calibration not correctly loaded from files that were later calibrated \ No newline at end of file diff --git a/crikit/CRIkitUI.py b/crikit/CRIkitUI.py index d095c40..83e098a 100644 --- a/crikit/CRIkitUI.py +++ b/crikit/CRIkitUI.py @@ -1,6 +1,6 @@ """ CRIKit2: Hyperspectral imaging toolkit -============================================================== +====================================== CRIKit2, formerly the Coherent Raman Imaging toolKit, is a hyperspectral imaging (HSI) platform (user interface, UI). @@ -32,9 +32,9 @@ import sys as _sys import webbrowser as _webbrowser -import h5py as _h5py import matplotlib as _mpl import numpy as _np +import h5py as _h5py import PyQt5.QtCore as _QtCore @@ -45,25 +45,30 @@ from PyQt5.QtWidgets import QMainWindow as _QMainWindow from PyQt5.QtWidgets import QMessageBox as _QMessageBox from PyQt5.QtWidgets import QWidget as _QWidget +from PyQt5.QtWidgets import QTableWidgetItem as _QTableWidgetItem + from scipy.signal import savgol_filter as _sg -from crikit.cri.error_correction import \ - PhaseErrCorrectALS as _PhaseErrCorrectALS +from crikit.cri.error_correction import (PhaseErrCorrectALS as _PhaseErrCorrectALS) from crikit.cri.error_correction import ScaleErrCorrectSG as _ScaleErrCorrectSG from crikit.cri.kk import KramersKronig from crikit.cri.merge_nrbs import MergeNRBs as _MergeNRBs -from crikit.data.frequency import calib_pix_wn as _calib_pix_wn +from crikit.data.frequency import (calib_pix_wn as _calib_pix_wn, + calib_pix_wl as _calib_pix_wl) from crikit.data.hsi import Hsi from crikit.data.spectra import Spectra from crikit.data.spectrum import Spectrum from crikit.datasets.model import Model as _Model -from crikit.io.hdf5 import hdf_is_valid_dsets from crikit.io.macros import import_csv_nist_special1 as io_nist_dlm from crikit.io.macros import import_hdf_nist_special as io_nist +from crikit.io.macros import import_hdf_nist_special_ooc as io_nist_ooc + +# from crikit.io.meta_configs import special_nist_bcars2 as _snb2 +# from crikit.io.meta_process import meta_process as _meta_process import crikit.measurement.peakamps as _peakamps @@ -80,11 +85,12 @@ from crikit.ui.dialog_kkOptions import DialogKKOptions from crikit.ui.dialog_model import DialogModel from crikit.ui.dialog_ploteffect import \ - DialogPlotEffectFuture as _DialogPlotEffect + DialogPlotEffect as _DialogPlotEffect from crikit.ui.dialog_save import DialogSave from crikit.ui.dialog_varstabAnscombeOptions import DialogAnscombeOptions from crikit.ui.qt_CRIkit import Ui_MainWindow -from crikit.ui.subui_hdf_load import SubUiHDFLoad +from crikit.ui.main_Mosaic import MainWindowMosaic + from crikit.ui.utils.roi import roimask as _roimask from crikit.ui.widget_Calibrate import widgetCalibrate as _widgetCalibrate from crikit.ui.widget_DeTrending import widgetALS as _widgetALS @@ -96,11 +102,12 @@ from crikit.ui.widget_SG import widgetSG as _widgetSG from crikit.utils.breadcrumb import BCPre as _BCPre -from crikit.utils.general import find_nearest, mean_nd_to_1d +from crikit.utils.general import find_nearest, mean_nd_to_1d, std_nd_to_1d from sciplot.sciplotUI import SciPlotUI as _SciPlotUI -_h5py.get_config().complex_names = ('Re', 'Im') +import lazy5 +from lazy5.ui.QtHdfLoad import HdfLoad force_not_sw = False @@ -133,8 +140,8 @@ print('No appropriate Jupyter/IPython installation found. Console will not be available') jupyter_flag = -1 -help_index = _os.path.abspath(_os.path.join(_os.path.dirname(__file__), - '../docs/build/html/index.html')) +str_doc = '../docs/build/html/index.html' +help_index = _os.path.abspath(_os.path.join(_os.path.dirname(__file__), str_doc)) if _os.path.exists(help_index): pass @@ -160,18 +167,19 @@ def __init__(self, **kwargs): parent = kwargs.get('parent') super(CRIkitUI_process, self).__init__(parent) ### EDIT ### - + self.parent = parent self.filename = kwargs.get('filename') self.path = kwargs.get('path') self.dataset_name = kwargs.get('dataset_name') + self.fid = None self.hsi = kwargs.get('hsi') if not isinstance(self.hsi, Hsi): self.hsi = Hsi() - + self.bcpre = _BCPre() self.dark = Spectra() @@ -181,6 +189,11 @@ def __init__(self, **kwargs): self.overlays = [] self.show_overlays = True + # ROI's to plot instead of random spectra + # Primarily affects dialogPlotEffect activities + # Also affected by setting actionUseSet + self.preview_rois = None + # Piecewise NRB's (not always used) self.nrb_left = Spectra() self.nrb_right = Spectra() @@ -190,7 +203,7 @@ def __init__(self, **kwargs): self.plotter = _SciPlotUI(show=False, parent=self.parent) - self._mpl_v2 = self.plotter._mpl_v2 + self._mpl_v1 = self.plotter._mpl_v1 self.ui = Ui_MainWindow() ### EDIT ### @@ -207,8 +220,12 @@ def __init__(self, **kwargs): self.img_BW.ui.spinBoxMax.setValue(self.img_BW.data.maxer) self.img_BW.ui.spinBoxMin.setValue(self.img_BW.data.minner) - self.ui.sweeperVL.insertWidget(0, self.img_BW) - self.img_BW.mpl.fig.tight_layout(pad=2) + self.ui.sweeperVL.insertWidget(0, self.img_BW, stretch=1, alignment=_QtCore.Qt.AlignHCenter) + try: + self.img_BW.mpl.fig.tight_layout(pad=2) + except: + print('tight_layout failed (CrikitUI: 1') + # ID used for matplotlib to connect to a figure self.cid = None @@ -231,7 +248,7 @@ def __init__(self, **kwargs): rgb_img.popimage.ui.pushButtonSpectrum.setEnabled(False) self.ui.tabColors.addTab(rgb_img, 'Color ' + str(count)) - + rgb_img.math.ui.pushButtonBasicMath.setEnabled(False) rgb_img.math.ui.pushButtonScripting.setEnabled(False) @@ -248,7 +265,7 @@ def __init__(self, **kwargs): rgb_img.math.ui.pushButtonBasicMath.pressed.connect(self.doMath) rgb_img.ui.spinBoxMax.editingFinished.connect(self.doComposite) rgb_img.ui.spinBoxMin.editingFinished.connect(self.doComposite) - rgb_img.math.ui.spinBoxGain.valueChanged.connect(self.doComposite) + rgb_img.math.ui.spinBoxGain.editingFinished.connect(self.doComposite) self.img_Composite = widgetCompositeColor(self.img_RGB_list, @@ -258,7 +275,7 @@ def __init__(self, **kwargs): self.ui.tabColors.addTab(self.img_Composite, 'Composite Image') - self.ui.sweeperVL_2.insertWidget(0, self.img_Composite2) + self.ui.sweeperVL_2.insertWidget(0, self.img_Composite2, stretch=1, alignment=_QtCore.Qt.AlignHCenter) self.ui.tabColors.currentChanged.connect(self.checkCompositeUpdate) @@ -267,6 +284,8 @@ def __init__(self, **kwargs): # Load Data self.ui.actionOpenHDFNIST.triggered.connect(self.fileOpenHDFNIST) + self.ui.actionOpenHDFNISTOOC.triggered.connect(self.fileOpenHDFNISTOOC) + self.ui.actionLoadNRB.triggered.connect(self.loadNRB) self.ui.actionLoadDark.triggered.connect(self.loadDark) @@ -285,6 +304,8 @@ def __init__(self, **kwargs): self.ui.actionMergeNRBs.triggered.connect(self.mergeNRBs) + self.ui.actionCreateMosaic.triggered.connect(self.mosaicTool) + # Settings self.ui.actionSettings.triggered.connect(self.settings) @@ -311,6 +332,7 @@ def __init__(self, **kwargs): # Calibrate Wavenumber self.ui.actionCalibrate.triggered.connect(self.calibrate) self.ui.actionResetCalibration.triggered.connect(self.calibrationReset) + self.ui.actionEstCalibration.triggered.connect(self.specialEstCalibration1) # Perform KK self.ui.actionKramersKronig.triggered.connect(self.doKK) @@ -332,6 +354,12 @@ def __init__(self, **kwargs): self.ui.actionAmpErrorCorrection.triggered.connect(self.errorCorrectAmp) self.ui.actionSubtractROI.triggered.connect(self.subtractROIStart) + # Preview ROIs + self.ui.actionSetPreviewROI.triggered.connect(self.set_preview_rois) + self.ui.actionDeletePreviewROI.triggered.connect(self.delete_preview_rois) + self.ui.actionShowPreviewROI.triggered.connect(self.changeSlider) + self.ui.actionShowPreviewROILegend.triggered.connect(self.changeSlider) + # SAVE self.ui.actionSave.triggered.connect(self.save) @@ -365,6 +393,9 @@ def __init__(self, **kwargs): self.ui.lineEditPix.setVisible(False) self.ui.labelFreqPixel.setVisible(False) + # Settings + self.ui.actionUseImagData.triggered.connect(self.changeSlider) + # Help if help_index is not None: self.ui.actionHelpManual.triggered.connect(lambda: _webbrowser.open('file:///' + help_index, new=1)) @@ -378,8 +409,8 @@ def __init__(self, **kwargs): if jupyter_flag == 1: try: - self.jupyterConsole = QJupyterWidget(customBanner='Welcome to the ' - 'embedded ipython console\n\n') + str_banner = 'Welcome to the embedded ipython console\n\n' + self.jupyterConsole = QJupyterWidget(customBanner=str_banner) except: print('Error loading embedded IPython Notebook') else: @@ -406,8 +437,10 @@ def __init__(self, **kwargs): # COMMAND LINE INTERPRETATION # file and dset info provided - if hdf_is_valid_dsets(self.path, self.filename, self.dataset_name): - self.fileOpenHDFNIST(dialog=False) + if (self.filename is not None) & (self.dataset_name is not None): + if lazy5.inspect.valid_dsets(filename=self.filename, + dset_list=self.dataset_name, pth=self.path): + self.fileOpenHDFNIST(dialog=False) # Hsi provided temp = kwargs.get('hsi') @@ -428,7 +461,7 @@ def __init__(self, **kwargs): except: print('Error in input x-array') self.hsi.x = None - + # y-array provided temp = kwargs.get('y') if temp is not None: @@ -461,6 +494,18 @@ def __init__(self, **kwargs): print('Error in input data') self.hsi = Hsi() + def mosaicTool(self): + win = MainWindowMosaic(parent=self) + win.show() + + def updateHistory(self): + self.ui.tableWidgetHistory.clearContents() + self.ui.tableWidgetHistory.setRowCount(len(self.bcpre.attr_dict)) + for num, q in enumerate(self.bcpre.attr_dict): + self.ui.tableWidgetHistory.setItem(num, 0, _QTableWidgetItem(q)) + self.ui.tableWidgetHistory.setItem(num, 1, + _QTableWidgetItem(str(self.bcpre.attr_dict[q]))) + def plotter_show(self): self.plotter.show() self.plotter.raise_() @@ -500,22 +545,24 @@ def toolbarSetting(self): self.ui.toolBar.addAction(self.ui.actionUndo) self.ui.toolBar.addSeparator() + # self.ui.toolBar.addActions([self.ui.actionLoadDark, + # self.ui.actionLoadNRB]) self.ui.toolBar.addActions([self.ui.actionLoadDark, - self.ui.actionLoadNRB]) + self.ui.actionLoad_NRB_Right_Side]) self.ui.toolBar.addSeparator() self.ui.toolBar.addActions([self.ui.actionDarkSubtract, - self.ui.actionResidualSubtract, + self.ui.actionEstCalibration, self.ui.actionFreqWindow, self.ui.actionAnscombe, self.ui.actionDeNoise, self.ui.actionInverseAnscombe, + self.ui.actionNRB_from_ROI_Left_Side, + self.ui.actionMergeNRBs, self.ui.actionKramersKronig, self.ui.actionPhaseErrorCorrection, self.ui.actionScaleErrorCorrection, - self.ui.actionSubtractROI, - self.ui.actionCalibrate, - self.ui.actionAmpErrorCorrection]) + self.ui.actionCalibrate]) elif sndr == self.ui.actionToolBarNIST1: self.ui.actionToolBarNIST2.setChecked(True) @@ -549,62 +596,40 @@ def toolbarSetting(self): def save(self): suffix = self.bcpre.dset_name_suffix - try: - ret = DialogSave.dialogSave(parent=self, - current_filename=self.filename, - current_path=self.path, - current_dataset_name=self.dataset_name[0], - suffix=suffix) - if ret is None: - pass # Save canceled - else: - self.save_filename = ret[0] - self.save_path = ret[1] - self.save_dataset_name = ret[2] - - self.save_grp = self.save_dataset_name.rpartition('/')[0] - self.save_dataset_name_no_grp = self.save_dataset_name.rpartition('/')[-1] - - - - try: - f_out = _h5py.File(self.save_path + self.save_filename, 'a') - loc = f_out.require_group(self.save_grp) - dset = loc.create_dataset(self.save_dataset_name_no_grp, data=self.hsi.data) - - meta = self.hsi.meta - for attr_key in meta: - val = meta[attr_key] - if isinstance(val, str): - dset.attrs[attr_key] = val - else: - try: - dset.attrs.create(attr_key, self.hsi.meta[attr_key]) - except: - print('Error in HSI attributes: {}'.format(attr_key)) + ret = DialogSave.dialogSave(parent=self, + current_filename=self.filename, + current_path=self.path, + current_dataset_name=self.dataset_name[0], + suffix=suffix) + if ret is None: + pass # Save canceled + else: + self.save_filename = ret[0] + self.save_path = ret[1] + self.save_dataset_name = ret[2] - bc_attr_dict = self.bcpre.attr_dict + self.save_grp = self.save_dataset_name.rpartition('/')[0] + self.save_dataset_name_no_grp = self.save_dataset_name.rpartition('/')[-1] - for attr_key in bc_attr_dict: - val = bc_attr_dict[attr_key] - if isinstance(val, str): - dset.attrs[attr_key] = val - else: - try: - dset.attrs.create(attr_key, bc_attr_dict[attr_key]) - except: - print('Could not create attribute') + if isinstance(self.hsi.meta, dict): + attr_dict = _copy.deepcopy(self.hsi.meta) + else: + print('Meta data (hsi.meta) is not a dictionary') + attr_dict = {} - except: - print('Something went wrong while saving') - else: - print('Saved without issues') - finally: - f_out.close() - self.setWindowTitle('{} -> {}'.format(self.windowTitle(), self.save_filename)) + attr_dict.update(self.bcpre.attr_dict) - except: - print('Couldn\'t open save dialog') + try: + ret_save = lazy5.create.save(self.save_filename, self.save_dataset_name, + self.hsi._data, pth=self.save_path, + attr_dict= attr_dict, sort_attrs=True, + chunks=True, verbose=True) + except: + print('Something went wrong saving...') + else: + print('Save succeeded with no errors.') + if ret_save: + self.setWindowTitle('{} -> {}'.format(self.windowTitle(), self.save_filename)) def tabMainChange(self): if self.ui.tabMain.currentIndex() == 4: # Jupyter console @@ -631,6 +656,15 @@ def closeEvent(self, event): else: print('Did not delete pickle file cut list... Something went wrong') + if self.fid: + print('Closing HDF File') + try: + self.fid.close() + except: + print('Something failed in closing the file') + else: + print('Successfully closed HDF File') + def fileOpenHDFNIST(self, *args, dialog=True): """ Open and load HDF5 File @@ -641,10 +675,14 @@ def fileOpenHDFNIST(self, *args, dialog=True): # Get data and load into CRI_HSI class # This will need to change to accomodate multiple-file selection - + if dialog: try: - to_open = SubUiHDFLoad.getFileDataSets(self.path) + if (self.filename is not None) & (self.path is not None): + to_open = HdfLoad.getFileDataSets(_os.path.join(self.path, self.filename), parent=self) + else: + to_open = HdfLoad.getFileDataSets(self.path, parent=self) + print('to_open: {}'.format(to_open)) if to_open is not None: self.path, self.filename, self.dataset_name = to_open @@ -655,6 +693,8 @@ def fileOpenHDFNIST(self, *args, dialog=True): self.hsi = Hsi() success = io_nist(self.path, self.filename, self.dataset_name, self.hsi) + print('Was successful: {}'.format(success)) + print('HSI shape: {}'.format(self.hsi.shape)) self.fileOpenSuccess(success) else: self.hsi = Hsi() @@ -662,6 +702,42 @@ def fileOpenHDFNIST(self, *args, dialog=True): self.hsi) self.fileOpenSuccess(success) + def fileOpenHDFNISTOOC(self, *args): + """ + Open and load HDF5 File OUT-OF-CORE + + dialog : bool + Present a gui for file and dataset selection + """ + + # Get data and load into CRI_HSI class + # This will need to change to accomodate multiple-file selection + + try: + if (self.filename is not None) & (self.path is not None): + to_open = HdfLoad.getFileDataSets(_os.path.join(self.path, self.filename), parent=self) + else: + to_open = HdfLoad.getFileDataSets(self.path, parent=self) + + print('to_open: {}'.format(to_open)) + if to_open is not None: + self.path, self.filename, self.dataset_name = to_open + self.dataset_name = self.dataset_name[0] + except: + print('Could not open file. Corrupt or not appropriate file format.') + else: + if to_open is not None: + self.hsi = Hsi() + success_fid = io_nist_ooc(self.path, self.filename, self.dataset_name, + self.hsi) + if success_fid: + self.fid = success_fid + print('HSI shape: {}'.format(self.hsi.shape)) + self.ui.actionUndo_Backup_Enabled.setChecked(False) + self.ui.actionUndo_Backup_Enabled.setEnabled(False) + + self.fileOpenSuccess(True) + def fileOpenDLMNIST(self): """ Open and load DLM File @@ -695,6 +771,11 @@ def fileOpenSuccess(self, success): activates or deactivates action (buttons) """ if success: + # * If HSI is integer dtype, convert to float + if (self.hsi.data.dtype.kind == 'i') & isinstance(self.hsi.data, _np.ndarray): + print('Converting HSI from int to float') + self.hsi.data = 1.0*self.hsi.data + self.setWindowTitle('{}: {}'.format(self.windowTitle(), self.filename)) # FILE self.ui.actionSave.setEnabled(True) @@ -711,6 +792,8 @@ def fileOpenSuccess(self, success): # VIEW self.ui.actionPointSpectrum.setEnabled(True) self.ui.actionROISpectrum.setEnabled(True) + self.ui.actionSetPreviewROI.setEnabled(True) + self.ui.actionDeletePreviewROI.setEnabled(True) # IMPORT/LOAD self.ui.actionLoadDark.setEnabled(True) @@ -731,8 +814,8 @@ def fileOpenSuccess(self, success): self.ui.actionNRB_from_ROI.setEnabled(True) self.ui.menuVariance_Stabilize.setEnabled(True) - # ANALYSIS - + # NIST SPECIAL + self.ui.actionEstCalibration.setEnabled(True) is_complex = _np.iscomplexobj(self.hsi.data) if is_complex: @@ -748,12 +831,16 @@ def fileOpenSuccess(self, success): # Backup for Undo self.bcpre.add_step(['Raw']) - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() + self.updateHistory() + + if self.ui.actionUndo_Backup_Enabled.isChecked(): + try: + _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) + except: + print('Error in pickle backup (Undo functionality)') + else: + self.bcpre.backed_up() + # Set frequency slider and associated displays self.ui.freqSlider.setMinimum(self.hsi.freq.op_range_pix[0]) @@ -764,10 +851,18 @@ def fileOpenSuccess(self, success): self.ui.lineEditFreq.setText(str(round(self.hsi.f[0], 2))) # Set BW Class Data self.img_BW.initData() - self.img_BW.data.grayscaleimage = self.hsi.data_imag_over_real[:, :, pos] + + if _np.iscomplexobj(self.hsi.data): + if self.ui.actionUseImagData.isChecked(): + self.img_BW.data.grayscaleimage = _np.imag(self.hsi.data[:, :, pos]) + val_extrema = _np.max(_np.abs(self.img_BW.data.grayscaleimage)) + else: + self.img_BW.data.grayscaleimage = _np.real(self.hsi.data[:, :, pos]) + val_extrema = _np.max(_np.abs(self.img_BW.data.grayscaleimage)) + else: + self.img_BW.data.grayscaleimage = self.hsi.data[:, :, pos] + val_extrema = _np.max(_np.abs(self.img_BW.data.grayscaleimage)) - val_extrema = _np.max([_np.abs(self.hsi.data_imag_over_real.max()), - _np.abs(self.hsi.data_imag_over_real.min())]) self.img_BW.ui.spinBoxMin.setMinimum(-1.1*val_extrema) self.img_BW.ui.spinBoxMin.setMaximum(1.1*val_extrema) self.img_BW.ui.spinBoxMax.setMinimum(-1.1*val_extrema) @@ -813,7 +908,7 @@ def fileOpenSuccess(self, success): rgb_img.data.grayscaleimage = temp rgb_img.data.set_x(self.hsi.x, xlabel) rgb_img.data.set_y(self.hsi.y, ylabel) - + color_str = rgb_img.colormode.ui.comboBoxFGColor.itemText(num) rgb_img.data.colormap = _mpl.colors.colorConverter.to_rgb(_mpl.colors.cnames[color_str]) rgb_img.colormode.ui.comboBoxFGColor.setCurrentIndex(num) @@ -841,7 +936,7 @@ def fileOpenSuccess(self, success): rgb_img.gsinfo.ui.spinBoxMin.setMaximum(1.1*val_extrema) rgb_img.gsinfo.ui.spinBoxMax.setMinimum(-1.1*val_extrema) rgb_img.gsinfo.ui.spinBoxMax.setMaximum(1.1*val_extrema) - + # Set X- and Y- scales, labels, etc for composite color images self.img_Composite.data.set_x(self.hsi.x, xlabel) self.img_Composite.data.set_y(self.hsi.y, ylabel) @@ -853,7 +948,10 @@ def loadDark(self): Open HDF file and load dark spectrum(a) """ - to_open = SubUiHDFLoad.getFileDataSets(self.path) + if (self.filename is not None) & (self.path is not None): + to_open = HdfLoad.getFileDataSets(_os.path.join(self.path, self.filename), parent=self) + else: + to_open = HdfLoad.getFileDataSets(self.path, parent=self) print('To_open: {}'.format(to_open)) if to_open is not None: @@ -861,6 +959,11 @@ def loadDark(self): success = io_nist(pth, filename, datasets, self.dark) if success: + # If Dark is integer dtype, convert to float + if self.dark.data.dtype.kind == 'i': + print('Converting Dark from int to float') + self.dark.data = 1.0*self.dark.data + if self.dark.shape[-1] == self.hsi.freq.size: self.ui.actionDarkSubtract.setEnabled(True) self.ui.actionDarkSpectrum.setEnabled(True) @@ -899,6 +1002,11 @@ def loadDarkDLM(self): if success: + # If Dark is integer dtype, convert to float + if self.dark.data.dtype.kind == 'i': + print('Converting Dark from int to float') + self.dark.data = 1.0*self.dark.data + if self.dark.shape[-1] == self.hsi.freq.size: self.ui.actionDarkSubtract.setEnabled(True) self.ui.actionDarkSpectrum.setEnabled(True) @@ -926,12 +1034,21 @@ def loadNRB(self): nrb = self.nrb_right - to_open = SubUiHDFLoad.getFileDataSets(self.path) + if (self.filename is not None) & (self.path is not None): + to_open = HdfLoad.getFileDataSets(_os.path.join(self.path, self.filename), parent=self) + else: + to_open = HdfLoad.getFileDataSets(self.path, parent=self) + if to_open is not None: pth, filename, datasets = to_open success = io_nist(pth, filename, datasets, nrb) if success: + # If NRB is integer dtype, convert to float + if nrb.data.dtype.kind == 'i': + print('Converting NRB from int to float') + nrb.data = 1.0*nrb.data + if nrb.shape[-1] == self.hsi.freq.size: if sender == self.ui.actionLoadNRB: self.ui.menuCoherent_Raman_Imaging.setEnabled(True) @@ -1000,6 +1117,142 @@ def loadNRBDLM(self): self.ui.actionNRBSpectrum.setEnabled(False) self.ui.actionDeNoiseNRB.setEnabled(False) + def get_preview_spectra(self, full=False): + """ If self.preview_rois is set, output the mean spectra from thos regions """ + if full: + rng = self.hsi.freq.pix_vec + else: + rng = self.hsi.freq.op_range_pix + + if self.preview_rois: + prev_spectra = [] + + for prx, pry in self.preview_rois: + + mask, path = _roimask(self.hsi.x, self.hsi.y, prx, pry) + + mask_hits = _np.sum(mask) + if mask_hits > 0: # Len(mask) > 0 + temp = self.hsi.data[..., rng][mask == 1] + + + if mask_hits > 1: + prev_spectra.append(_np.mean(temp, axis=0)) + else: + prev_spectra.append(temp[self.hsi.freq.op_range_pix]) + return _np.array(prev_spectra) + + else: + return self.hsi.get_rand_spectra(2, pt_sz=3, quads=True) + + def set_preview_rois(self): + """ Set the preview ROIs. NOTE: this function just sets the signal for the MPL window """ + if self.cid is None: + # Updated by _roiClick + self.preview_rois = [] + self.x_loc_list = [] + self.y_loc_list = [] + + self.cid = self.img_BW.mpl.mpl_connect('button_press_event', + lambda event: self._roiPreviewClick(event)) + + self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) + self.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) + pass + + def showPreviewRois(self): + lines = [] + if self.preview_rois: + for num, (prx, pry) in enumerate(self.preview_rois): + temp, = self.img_BW.mpl.ax.plot(prx, pry, label='Preview ROI {}'.format(num), + linestyle=':', color='C{}'.format(num % 10)) + lines.append(temp) + + if self.ui.actionShowPreviewROILegend.isChecked(): + # lg = self.img_BW.mpl.ax.legend(handles=lines, loc='lower left', mode='expand', + # bbox_to_anchor=(0.01, 1.02, 1., 0.2), + # ncol=2, fontsize=9) + lg = self.img_BW.mpl.ax.legend(handles=lines, loc='best', + ncol=2, fontsize=9) + self.img_BW.mpl.ax.add_artist(lg) + try: + self.img_BW.mpl.fig.tight_layout(pad=1) + except: + print('tight_layout failed (CrikitUI: 2') + self.img_BW.mpl.draw() + + def _roiPreviewClick(self, event, *args): + """ + Capture region-of-interest mouse click locations in MPL window. + """ + + getx = self.img_BW.mpl.ax.get_xlim() + gety = self.img_BW.mpl.ax.get_ylim() + + if event.button == 1: + if event.inaxes == self.img_BW.mpl.ax: + + self.x_loc_list.append(event.xdata) + self.y_loc_list.append(event.ydata) + + if len(self.x_loc_list) == 1: + self.img_BW.mpl.ax.plot(self.x_loc_list, self.y_loc_list, + markerfacecolor=[.9, .9, 0], + markeredgecolor=[.9, .9, 0], + marker='+', + markersize=10, + linestyle='None') + self.img_BW.mpl.ax.set_xlim(getx) + self.img_BW.mpl.ax.set_ylim(gety) + self.img_BW.mpl.draw() + else: + self.img_BW.mpl.ax.plot(self.x_loc_list[-2:], + self.y_loc_list[-2:], + linewidth=2, + marker='+', + markersize=10, + color=[.9, .9, 0], + markerfacecolor=[.9, .9, 0], + markeredgecolor=[.9, .9, 0]) + self.img_BW.mpl.ax.set_xlim(getx) + self.img_BW.mpl.ax.set_ylim(gety) + + self.img_BW.mpl.draw() + else: + if len(self.x_loc_list) > 0: # Insure at least 1 vertex + self.x_loc_list.append(self.x_loc_list[0]) + self.y_loc_list.append(self.y_loc_list[0]) + + self.img_BW.mpl.ax.plot(self.x_loc_list[-2:], + self.y_loc_list[-2:], + linewidth=2, + marker='+', + markersize=10, + color=[.9, .9, 0], + markerfacecolor=[.9, .9, 0], + markeredgecolor=[.9, .9, 0]) + self.img_BW.mpl.ax.set_xlim(getx) + self.img_BW.mpl.ax.set_ylim(gety) + self.img_BW.mpl.draw() + + self.preview_rois.append([self.x_loc_list, self.y_loc_list]) + + self.x_loc_list = [] + self.y_loc_list = [] + else: + del self.x_loc_list + del self.y_loc_list + + self.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) + self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) + self.img_BW.mpl.mpl_disconnect(self.cid) + self.cid = None + self.changeSlider() + + def delete_preview_rois(self): + self.preview_rois = None + self.changeSlider() + def mergeNRBs(self): """ Interactive merge of the left- and right-side NRB @@ -1007,13 +1260,18 @@ def mergeNRBs(self): if self.nrb_left is not None and self.nrb_right is not None: rng = self.hsi.freq.op_range_pix + if (self.preview_rois is None) | (not self.ui.actionUsePreviewROI.isChecked()): + preview_spectra = self.hsi.get_rand_spectra(2, pt_sz=3, quads=True) + else: + preview_spectra = self.get_preview_spectra(full=False) - rand_spectra = self.hsi.get_rand_spectra(2, pt_sz=3, quads=True) + if _np.iscomplexobj(preview_spectra): + preview_spectra = preview_spectra.imag plugin = _widgetMergeNRBs(wn_vec=self.hsi.f, nrb_left=self.nrb_left.mean()[rng], nrb_right=self.nrb_right.mean()[rng]) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(data=rand_spectra, + winPlotEffect = _DialogPlotEffect.dialogPlotEffect(data=preview_spectra, x=self.hsi.f, plugin=plugin) @@ -1050,6 +1308,7 @@ def mergeNRBs(self): winPlotEffect.parameters['wn_switchpt'], 'scale_left', winPlotEffect.parameters['scale_left']]) + self.updateHistory() else: pass @@ -1066,12 +1325,16 @@ def calibrate(self): Calibrate spectra """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, full=True) - if _np.iscomplexobj(rand_spectra): - rand_spectra = rand_spectra.imag + if (self.preview_rois is None) | (not self.ui.actionUsePreviewROI.isChecked()): + preview_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, full=True) + else: + preview_spectra = self.get_preview_spectra(full=True) + + if _np.iscomplexobj(preview_spectra): + preview_spectra = preview_spectra.imag plugin = _widgetCalibrate(calib_dict=self.hsi.freq.calib) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, + winPlotEffect = _DialogPlotEffect.dialogPlotEffect(preview_spectra, x=self.hsi.f_full, plugin=plugin, parent=self) @@ -1091,6 +1354,26 @@ def calibrationReset(self): self.hsi.freq.update() self.changeSlider() + def specialEstCalibration1(self): + """ + For NIST BCARS 2, maximum raw spectrum occurs at approximately + 745.8 nm (18/07/11) + """ + msg = _QMessageBox(self) + msg.setIcon(_QMessageBox.Warning) + msg.setText('Estimate calibration for NIST BCARS2?') + msg.setWindowTitle('Confirm estimation of calibration') + msg.setInformativeText('This should only be applied to RAW BCARS2 data from NIST.') + msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) + msg.setDefaultButton(_QMessageBox.Ok) + out = msg.exec() + + if out == _QMessageBox.Ok: + nm_diff = 745.8 - _calib_pix_wl(self.hsi.freq.calib)[0][self.hsi.mean().argmax()] + self.hsi.freq.calib['a_vec'][-1] = self.hsi.freq.calib['a_vec'][-1] + nm_diff + self.hsi.freq.update() + self.changeSlider() + def plotDarkSpectrum(self): """ Plot dark spectrum @@ -1098,8 +1381,18 @@ def plotDarkSpectrum(self): if self.dark.data is None: pass else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.dark.data), - label='Mean Dark Spectrum') + meaner = mean_nd_to_1d(self.dark.data) + self.plotter.plot(self.hsi.f_full, meaner, + label='Mean Dark Spectrum ({})'.format(self.dark.n_pix)) + + if self.dark.n_pix > 1: + stder = std_nd_to_1d(self.dark.data) + color = self.plotter.list_all[-1].style_dict['color'] + std_label = r'Dark Spectrum $\pm$1 Std. Dev. ({})'.format(self.dark.n_pix) + self.plotter.fill_between(self.hsi.f_full, meaner - stder, + meaner + stder, color=color, + alpha=0.25, + label=std_label) self.plotter.show() self.plotter.raise_() @@ -1111,8 +1404,21 @@ def plotNRBSpectrum(self): if self.nrb.data is None: pass else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb.data), - label='Mean NRB Spectrum') + meaner = mean_nd_to_1d(self.nrb.data) + self.plotter.plot(self.hsi.f_full, meaner, + label='Mean NRB Spectrum ({})'.format(self.nrb.n_pix)) + + if self.nrb.n_pix > 1: + stder = std_nd_to_1d(self.nrb.data) + color = self.plotter.list_all[-1].style_dict['color'] + std_label = r'NRB Spectrum $\pm$1 Std. Dev. ({})'.format(self.nrb.n_pix) + self.plotter.fill_between(self.hsi.f_full, meaner - stder, + meaner + stder, color=color, + alpha=0.25, + label=std_label) + + # self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb.data), + # label='Mean NRB Spectrum') self.plotter.show() self.plotter.raise_() @@ -1124,8 +1430,21 @@ def plotLeftNRBSpectrum(self): if self.nrb_left.data is None: pass else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb_left.data), - label='Mean Left-Side NRB Spectrum') + meaner = mean_nd_to_1d(self.nrb_left.data) + self.plotter.plot(self.hsi.f_full, meaner, + label='Mean Left-Side NRB Spectrum ({})'.format(self.nrb_left.n_pix)) + + if self.nrb_left.n_pix > 1: + stder = std_nd_to_1d(self.nrb_left.data) + color = self.plotter.list_all[-1].style_dict['color'] + std_label = r'Left-Side NRB Spectrum $\pm$1 Std. Dev. ({})'.format(self.nrb_left.n_pix) + self.plotter.fill_between(self.hsi.f_full, meaner - stder, + meaner + stder, color=color, + alpha=0.25, + label=std_label) + + # self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb_left.data), + # label='Mean Left-Side NRB Spectrum') self.plotter.show() self.plotter.raise_() @@ -1137,8 +1456,18 @@ def plotRightNRBSpectrum(self): if self.nrb_right.data is None: pass else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb_right.data), - label='Mean Right-Side NRB Spectrum') + meaner = mean_nd_to_1d(self.nrb_right.data) + self.plotter.plot(self.hsi.f_full, meaner, + label='Mean Right-Side NRB Spectrum ({})'.format(self.nrb_right.n_pix)) + + if self.nrb_right.n_pix > 1: + stder = std_nd_to_1d(self.nrb_right.data) + color = self.plotter.list_all[-1].style_dict['color'] + std_label = r'Right-Side NRB Spectrum $\pm$1 Std. Dev. ({})'.format(self.nrb_right.n_pix) + self.plotter.fill_between(self.hsi.f_full, meaner - stder, + meaner + stder, color=color, + alpha=0.25, + label=std_label) self.plotter.show() self.plotter.raise_() @@ -1175,7 +1504,7 @@ def subtractROIStart(self): self.y_loc_list = [] - self.cid = self.img_BW.mpl.mpl_connect('button_press_event', + self.cid = self.img_BW.mpl.mpl_connect('button_press_event', lambda event: self._roiClick(event, self._roiSubtract)) self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) @@ -1205,7 +1534,7 @@ def _roiSubtract(self, locs): if mask_hits > 1: spectrum = _np.mean(spectra, axis=0) else: - spectrum = spectra + spectrum = _np.squeeze(spectra) spectrum = spectrum.astype(self.hsi.data.dtype) self.hsi.data -= spectrum[..., :] self.changeSlider() @@ -1213,6 +1542,7 @@ def _roiSubtract(self, locs): # Backup for Undo self.bcpre.add_step(['SubtractROI', 'Spectrum', spectrum]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) @@ -1254,7 +1584,7 @@ def nrbFromROI(self): # Need to send sender as the text name as the actual object # will change if self.cid is None: - self.cid = self.img_BW.mpl.mpl_connect('button_press_event', + self.cid = self.img_BW.mpl.mpl_connect('button_press_event', lambda event: self._roiClick(event, self._roiNRB, sender)) self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) @@ -1283,16 +1613,25 @@ def _roiNRB(self, locs, sender): mask_hits = _np.sum(mask) if mask_hits > 0: # Len(mask) > 0 - spectra = self.hsi.data_imag_over_real[mask == 1] + if isinstance(self.hsi.data, _h5py.Dataset): + spectra = self.hsi.data[_np.repeat(mask[...,None], + self.hsi.data.shape[-1], axis=-1) == 1] + else: + spectra = self.hsi.data[mask == 1] + + if _np.iscomplexobj(spectra) & self.ui.actionUseImagData.isChecked(): + spectra = spectra.imag + else: + spectra = spectra.real if mask_hits > 1: spectrum = _np.mean(spectra, axis=0) else: - spectrum = spectra + spectrum = _np.squeeze(spectra) spectrum = spectrum.astype(self.hsi.data.dtype) if sender == 'actionNRB_from_ROI': - self.nrb.data = spectrum + self.nrb.data = spectra self.ui.actionKramersKronig.setEnabled(True) self.ui.actionKKSpeedTest.setEnabled(True) self.ui.actionNRBSpectrum.setEnabled(True) @@ -1300,13 +1639,13 @@ def _roiNRB(self, locs, sender): elif sender == 'actionAppend_NRB_from_ROI': if self.nrb.size == 0: - self.nrb.data = spectrum + self.nrb.data = spectra else: self.nrb.data = (self.nrb.data + spectrum)/2 self.ui.actionKramersKronig.setEnabled(True) self.ui.actionNRBSpectrum.setEnabled(True) elif sender == 'actionNRB_from_ROI_Left_Side': - self.nrb_left.data = spectrum + self.nrb_left.data = spectra self.ui.actionLeftSideNRBSpect.setEnabled(True) if ((self.nrb_left.data is not None) and (self.nrb_right.data is not None)): @@ -1314,7 +1653,7 @@ def _roiNRB(self, locs, sender): self.ui.actionMergeNRBs.setEnabled(True) elif sender == 'actionNRB_from_ROI_Right_Side': - self.nrb_right.data = spectrum + self.nrb_right.data = spectra self.ui.actionRightSideNRBSpect.setEnabled(True) if ((self.nrb_left.data is not None) and (self.nrb_right.data is not None)): @@ -1399,9 +1738,14 @@ def _pointSpectrumPlot(self, locs): meta = {'x': x_loc, 'y': y_loc, 'x_pix': x_pix, 'y_pix': y_pix, 'overlay': True} - self.plotter.plot(self.hsi.f, - self.hsi.data_imag_over_real[y_pix, x_pix, rng], - label=label, meta=meta) + if _np.iscomplexobj(self.hsi.data) & self.ui.actionUseImagData.isChecked(): + self.plotter.plot(self.hsi.f, + self.hsi.data[y_pix, x_pix, rng].imag, + label=label, meta=meta) + else: + self.plotter.plot(self.hsi.f, + self.hsi.data[y_pix, x_pix, rng].real, + label=label, meta=meta) self.plotter.show() @@ -1426,13 +1770,31 @@ def _roiSpectrumPlot(self, locs): if mask_hits > 0: # Len(mask) > 0 rng = self.hsi.freq.op_range_pix - spectra = self.hsi.data_imag_over_real[mask == 1] + if isinstance(self.hsi.data, _h5py.Dataset): + + # * Can't do fancy boolean indexing with HDF + # * Make a square bounding box + m,n = _np.where(mask == 1) + rmin = m.min() + rmax = m.max()+1 + cmin = n.min() + cmax = n.max()+1 + + spectra = self.hsi.data[rmin:rmax, cmin:cmax,:][mask[rmin:rmax, cmin:cmax]==1] + + else: + spectra = self.hsi.data[mask == 1] + + if _np.iscomplexobj(spectra) & self.ui.actionUseImagData.isChecked(): + spectra = spectra.imag + else: + spectra = spectra.real if mask_hits > 1: spectrum = _np.mean(spectra[..., rng], axis=0) stddev = _np.std(spectra[..., rng], axis=0) else: - spectrum = spectra[..., rng] + spectrum = _np.squeeze(spectra[..., rng]) plot_num = self.plotter.n_lines @@ -1533,7 +1895,7 @@ def freqWindow(self): """ text, ok = _QInputDialog.getText(None, 'Frequency Window', 'Range Tuple (cm-1): ', - text='(500, 3400)') + text='(500, 3800)') if ok: text_str_list = text.strip('(').strip(')').strip().split(',') freqwin = [float(q) for q in text_str_list] @@ -1578,7 +1940,7 @@ def zeroFirstColumn(self): self.zc.transform(self.hsi.data) # Adjust mask - self.hsi._mask[:, self.zc.zero_col] *= 0 + # self.hsi._mask[:, self.zc.zero_col] *= 0 self.changeSlider() @@ -1591,7 +1953,7 @@ def zeroFirstRow(self): self.zr.transform(self.hsi.data) # Adjust mask - self.hsi._mask[self.zr.zero_row, :] *= 0 + # self.hsi._mask[self.zr.zero_row, :] *= 0 self.changeSlider() @@ -1604,7 +1966,7 @@ def zeroLastColumn(self): self.zc.transform(self.hsi.data) # Adjust mask - self.hsi._mask[:, self.zc.zero_col] *= 0 + # self.hsi._mask[:, self.zc.zero_col] *= 0 self.changeSlider() @@ -1617,7 +1979,7 @@ def zeroLastRow(self): self.zr.transform(self.hsi.data) # Adjust mask - self.hsi._mask[self.zr.zero_row, :] *= 0 + # self.hsi._mask[self.zr.zero_row, :] *= 0 self.changeSlider() @@ -1675,8 +2037,13 @@ def doKK(self): the Kramers-Kronig phase retrieval algorithm. """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) + if (self.preview_rois is None) | (not self.ui.actionUsePreviewROI.isChecked()): + preview_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, + full=False) + + else: + preview_spectra = self.get_preview_spectra(full=False) + nrb = self.nrb.mean() # Range of pixels to perform-over @@ -1684,7 +2051,7 @@ def doKK(self): out = DialogKKOptions.dialogKKOptions(data=[self.hsi.f, nrb[..., rng], - rand_spectra], parent=self) + preview_spectra], parent=self) if out is not None: cars_amp_offset = out['cars_amp'] @@ -1709,6 +2076,7 @@ def doKK(self): self.bcpre.add_step(['KK', 'CARSAmp', cars_amp_offset, 'NRBAmp', nrb_amp_offset, 'Phase', phase_offset, 'Norm', norm_to_nrb]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) @@ -1742,6 +2110,7 @@ def deNoiseNRB(self): self.bcpre.add_step(['DenoiseNrbSG', 'Win_size', win_size, 'Order', order]) + self.updateHistory() self.changeSlider() @@ -1770,7 +2139,7 @@ def deNoiseDark(self): self.bcpre.add_step(['DenoiseDarkSG', 'Win_size', win_size, 'Order', order]) - + self.updateHistory() self.changeSlider() @@ -1807,6 +2176,7 @@ def deNoise(self): # Backup for Undo self.bcpre.add_step(['SVD', 'SVs', svs]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: @@ -1821,62 +2191,62 @@ def errorCorrectPhase(self): """ Error Correction: Phase """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - if _np.iscomplexobj(rand_spectra): - rand_spectra = _np.angle(rand_spectra) + + if (self.preview_rois is None) | (not self.ui.actionUsePreviewROI.isChecked()): + preview_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, + full=True) + else: + preview_spectra = self.get_preview_spectra(full=True) + + if _np.iscomplexobj(preview_spectra): + preview_spectra = _np.angle(preview_spectra) rng = self.hsi.freq.op_range_pix - plugin = _widgetALS() - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, - x=self.hsi.f, + plugin = _widgetALS(x=self.hsi.f_full, rng=rng) + winPlotEffect = _DialogPlotEffect.dialogPlotEffect(preview_spectra, + x=self.hsi.f_full, plugin=plugin, parent=self) if winPlotEffect is not None: - asym_param = winPlotEffect.parameters['asym_param'] - smoothness_param = winPlotEffect.parameters['smoothness_param'] - redux_factor = winPlotEffect.parameters['redux'] - fix_end_points = winPlotEffect.parameters['fix_end_points'] - max_iter = winPlotEffect.parameters['max_iter'] - min_diff = winPlotEffect.parameters['min_diff'] - - phase_err_correct_als = _PhaseErrCorrectALS(smoothness_param=smoothness_param, - asym_param=asym_param, - redux=redux_factor, - order=2, - rng=rng, - fix_end_points=fix_end_points, - max_iter=max_iter, - min_diff=min_diff, - verbose=False) + # asym_param = winPlotEffect.parameters['asym_param'] + # smoothness_param = winPlotEffect.parameters['smoothness_param'] + # redux_factor = winPlotEffect.parameters['redux'] + # fix_end_points = winPlotEffect.parameters['fix_end_points'] + # max_iter = winPlotEffect.parameters['max_iter'] + # min_diff = winPlotEffect.parameters['min_diff'] + + phase_err_correct_als = _PhaseErrCorrectALS(**winPlotEffect.parameters) phase_err_correct_als.transform(self.hsi.data) + temp = ['PhaseErrorCorrectALS'] + [temp.extend(q) for q in winPlotEffect.parameters.items()] + self.bcpre.add_step(temp) # Backup for Undo - - if _np.size(asym_param) == 1: - self.bcpre.add_step(['PhaseErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param', asym_param, - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - else: - self.bcpre.add_step(['PhaseErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param_start', - winPlotEffect.parameters['asym_param_start'], - 'asym_param_end', - winPlotEffect.parameters['asym_param_end'], - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - + # if _np.size(asym_param) == 1: + # self.bcpre.add_step(['PhaseErrorCorrectALS', + # 'smoothness_param', smoothness_param, + # 'asym_param', asym_param, + # 'redux', redux_factor, + # 'order', 2, + # 'fix_end_points', fix_end_points, + # 'max_iter', max_iter, + # 'min_diff', min_diff]) + + # else: + # self.bcpre.add_step(['PhaseErrorCorrectALS', + # 'smoothness_param', smoothness_param, + # 'asym_param_start', + # winPlotEffect.parameters['asym_param_start'], + # 'asym_param_end', + # winPlotEffect.parameters['asym_param_end'], + # 'redux', redux_factor, + # 'order', 2, + # 'fix_end_points', fix_end_points, + # 'max_iter', max_iter, + # 'min_diff', min_diff]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) @@ -1891,15 +2261,20 @@ def errorCorrectScale(self): """ Error Correction: Scale """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - if _np.iscomplexobj(rand_spectra): - rand_spectra = rand_spectra.real + + if (self.preview_rois is None) | (not self.ui.actionUsePreviewROI.isChecked()): + preview_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, + full=False) + else: + preview_spectra = self.get_preview_spectra(full=False) + + if _np.iscomplexobj(preview_spectra): + preview_spectra = preview_spectra.real rng = self.hsi.freq.op_range_pix plugin = _widgetSG(window_length=601, polyorder=2) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, + winPlotEffect = _DialogPlotEffect.dialogPlotEffect(preview_spectra, x=self.hsi.f, plugin=plugin, parent=self) @@ -1916,6 +2291,7 @@ def errorCorrectScale(self): self.bcpre.add_step(['ScaleErrorCorrectSG', 'win_size', win_size, 'order', order]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: @@ -1935,61 +2311,62 @@ def errorCorrectAmp(self): If data is complex, amplitude detrending occurs on and only on the \ imaginary portion """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - if _np.iscomplexobj(rand_spectra): - rand_spectra = rand_spectra.imag + + if (self.preview_rois is None) | (not self.ui.actionUsePreviewROI.isChecked()): + preview_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, + full=True) + else: + preview_spectra = self.get_preview_spectra(full=True) + + if _np.iscomplexobj(preview_spectra): + preview_spectra = preview_spectra.imag rng = self.hsi.freq.op_range_pix - plugin = _widgetALS() - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, - x=self.hsi.f, + plugin = _widgetALS(x=self.hsi.f_full, rng=rng) + winPlotEffect = _DialogPlotEffect.dialogPlotEffect(preview_spectra, + x=self.hsi.f_full, plugin=plugin, parent=self) if winPlotEffect is not None: - asym_param = winPlotEffect.parameters['asym_param'] - smoothness_param = winPlotEffect.parameters['smoothness_param'] - redux_factor = winPlotEffect.parameters['redux'] - fix_end_points = winPlotEffect.parameters['fix_end_points'] - max_iter = winPlotEffect.parameters['max_iter'] - min_diff = winPlotEffect.parameters['min_diff'] - - - baseline_detrend = _SubtractBaselineALS(smoothness_param=smoothness_param, - asym_param=asym_param, - redux=redux_factor, - order=2, - rng=rng, - fix_end_points=fix_end_points, - max_iter=max_iter, - min_diff=min_diff, - verbose=False) + # asym_param = winPlotEffect.parameters['asym_param'] + # smoothness_param = winPlotEffect.parameters['smoothness_param'] + # redux_factor = winPlotEffect.parameters['redux'] + # fix_end_points = winPlotEffect.parameters['fix_end_points'] + # max_iter = winPlotEffect.parameters['max_iter'] + # min_diff = winPlotEffect.parameters['min_diff'] + + temp = ['AmpErrorCorrectALS'] + [temp.extend(q) for q in winPlotEffect.parameters.items()] + self.bcpre.add_step(temp) + + baseline_detrend = _SubtractBaselineALS(**winPlotEffect.parameters) + baseline_detrend.transform(self.hsi.data) # Backup for Undo - if _np.size(asym_param) == 1: - self.bcpre.add_step(['AmpErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param', asym_param, - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - else: - self.bcpre.add_step(['AmpErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param_start', - winPlotEffect.parameters['asym_param_start'], - 'asym_param_end', - winPlotEffect.parameters['asym_param_end'], - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - + # if _np.size(asym_param) == 1: + # self.bcpre.add_step(['AmpErrorCorrectALS', + # 'smoothness_param', smoothness_param, + # 'asym_param', asym_param, + # 'redux', redux_factor, + # 'order', 2, + # 'fix_end_points', fix_end_points, + # 'max_iter', max_iter, + # 'min_diff', min_diff]) + # else: + # self.bcpre.add_step(['AmpErrorCorrectALS', + # 'smoothness_param', smoothness_param, + # 'asym_param_start', + # winPlotEffect.parameters['asym_param_start'], + # 'asym_param_end', + # winPlotEffect.parameters['asym_param_end'], + # 'redux', redux_factor, + # 'order', 2, + # 'fix_end_points', fix_end_points, + # 'max_iter', max_iter, + # 'min_diff', min_diff]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: @@ -2007,6 +2384,8 @@ def doUndo(self): """ self.bcpre.pop_to_last() self.hsi = _BCPre.load_pickle(self.bcpre.id_list[-1]) + self.updateHistory() + del_flag = 0 for count in self.bcpre.cut_list: @@ -2053,6 +2432,17 @@ def subDark(self): if out == _QMessageBox.Ok: sub_dark.transform(self.hsi.data) + # Backup for Undo + self.bcpre.add_step(['SubDark']) + self.updateHistory() + if self.ui.actionUndo_Backup_Enabled.isChecked(): + try: + _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) + except: + print('Error in pickle backup (Undo functionality)') + else: + self.bcpre.backed_up() + if nrbloaded: msg = _QMessageBox(self) msg.setIcon(_QMessageBox.Question) @@ -2089,18 +2479,6 @@ def subDark(self): if out == _QMessageBox.Ok: sub_dark.transform(self.nrb_right.data) - - # Backup for Undo - if darkloaded or nrbloaded: - self.bcpre.add_step(['SubDark']) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - self.changeSlider() else: msg = _QMessageBox(self) @@ -2191,6 +2569,7 @@ def subResidual(self): self.bcpre.add_step(['SubResidual','RangeStart', freqwin[0], 'RangeEnd', freqwin[1]]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) @@ -2226,6 +2605,7 @@ def anscombe(self): self.bcpre.add_step(['Anscombe','Gauss_mean', 0.0, 'Gauss_std', out['stddev'], 'Poisson_multi', out['gain']]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) @@ -2257,6 +2637,7 @@ def inverseAnscombe(self): self.bcpre.add_step(['InvAnscombe','Gauss_mean', 0.0, 'Gauss_std', out['stddev'], 'Poisson_multi', out['gain']]) + self.updateHistory() if self.ui.actionUndo_Backup_Enabled.isChecked(): try: _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) @@ -2325,36 +2706,43 @@ def doMath(self): Mask = 1 else: if (operation_text == '') or (operation_text == ' '): # Return just a plane - Mask = _peakamps.MeasurePeak.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeak.measure(self.hsi.data, condloc1) elif operation_text == '+': # Addition - Mask = _peakamps.MeasurePeakAdd.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeakAdd.measure(self.hsi.data, condloc1, condloc2) elif operation_text == '-': # Subtraction - Mask = _peakamps.MeasurePeakMinus.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeakMinus.measure(self.hsi.data, condloc1, condloc2) elif operation_text == '*': # Multiplication - Mask = _peakamps.MeasurePeakMultiply.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeakMultiply.measure(self.hsi.data, condloc1, condloc2) elif operation_text == '/': # Division - Mask = _peakamps.MeasurePeakDivide.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeakDivide.measure(self.hsi.data, condloc1, condloc2) elif operation_text == 'SUM': # Summation over range - Mask = _peakamps.MeasurePeakSummation.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeakSummation.measure(self.hsi.data, condloc1, condloc2) elif operation_text == 'Peak b/w troughs': # Peak between troughs - Mask = _peakamps.MeasurePeakBWTroughs.measure(self.hsi.data_imag_over_real, + Mask = _peakamps.MeasurePeakBWTroughs.measure(self.hsi.data, condloc1, condloc2, condloc3) else: pass + if Mask is not None: + if _np.iscomplexobj(self.hsi.data) & self.ui.actionUseImagData.isChecked(): + Mask = Mask.imag + else: + Mask = Mask.real + + if cond_set is True: inequality_text = self.img_RGB_list[rgbnum].math.ui.comboBoxCondInEquality.currentText() inequality_val = self.img_RGB_list[rgbnum].math.ui.spinBoxInEquality.value() @@ -2418,50 +2806,58 @@ def doMath(self): if freq_set == True: if (operation_text == '') or (operation_text == ' '): # Return just a plane self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeak.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeak.measure(self.hsi.data, oploc1) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() elif operation_text == '+': # Addition self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakAdd.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeakAdd.measure(self.hsi.data, oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() elif operation_text == '-': # Subtraction self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakMinus.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeakMinus.measure(self.hsi.data, oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() elif operation_text == '*': # Multiplication self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakMultiply.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeakMultiply.measure(self.hsi.data, oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() elif operation_text == '/': # Division self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakDivide.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeakDivide.measure(self.hsi.data, oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() elif operation_text == 'SUM': # Division self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakSummation.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeakSummation.measure(self.hsi.data, oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() elif operation_text == 'Peak b/w troughs': # Division self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakBWTroughs.measure(self.hsi.data_imag_over_real, + _peakamps.MeasurePeakBWTroughs.measure(self.hsi.data, oploc1, oploc2, - oploc3) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() + oploc3) else: pass + + if (_np.iscomplexobj(self.img_RGB_list[rgbnum].data.grayscaleimage) & + self.ui.actionUseImagData.isChecked()): + + self.img_RGB_list[rgbnum].data.grayscaleimage = self.img_RGB_list[rgbnum].data.grayscaleimage.imag + else: + self.img_RGB_list[rgbnum].data.grayscaleimage = self.img_RGB_list[rgbnum].data.grayscaleimage.real + + + minner = self.img_RGB_list[rgbnum].data.grayscaleimage.min() + minner = _np.sign(minner)*(1.1*_np.abs(minner)) + + maxer = self.img_RGB_list[rgbnum].data.grayscaleimage.max() + maxer = _np.sign(maxer)*(1.1*_np.abs(maxer)) + + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMin.setMinimum(minner) + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMin.setMaximum(maxer) + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMax.setMinimum(minner) + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMax.setMaximum(maxer) + + self.img_RGB_list[rgbnum].changeColor() + else: pass self.doComposite() @@ -2478,6 +2874,18 @@ def setOpFreq1(self): self.img_RGB_list[rgbnum].data.opfreq1 = currentfreq self.img_RGB_list[rgbnum].math.ui.pushButtonOpFreq1.setText(str(round(currentfreq, 1))) self.img_RGB_list[rgbnum].data.grayscaleimage = self.img_BW.data.grayscaleimage + + minner = self.img_RGB_list[rgbnum].data.grayscaleimage.min() + minner = _np.sign(minner)*(1.1*_np.abs(minner)) + + maxer = self.img_RGB_list[rgbnum].data.grayscaleimage.max() + maxer = _np.sign(maxer)*(1.1*_np.abs(maxer)) + + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMin.setMinimum(minner) + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMin.setMaximum(maxer) + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMax.setMinimum(minner) + self.img_RGB_list[rgbnum].gsinfo.ui.spinBoxMax.setMaximum(maxer) + self.img_RGB_list[rgbnum].changeColor() self.img_RGB_list[rgbnum].mpl.draw() @@ -2588,32 +2996,51 @@ def spectrumColorImg(self): mloc, nloc = _np.where(Mask) - if mask_hits > 1: - mean_spect = self.hsi.data_imag_over_real[mloc, nloc, :][:, self.hsi.freq.op_range_pix].mean(axis=0) - std_spect = self.hsi.data_imag_over_real[mloc, nloc, :][:, self.hsi.freq.op_range_pix].std(axis=0) - self.plotter.plot(self.hsi.f, mean_spect, label='Mean spectrum ({})'.format(mask_hits)) - elif mask_hits == 1: - mean_spect = _np.squeeze(self.hsi.data_imag_over_real[mloc,nloc,:])[self.hsi.freq.op_range_pix] + if mask_hits > 0: + rng = self.hsi.freq.op_range_pix - std_spect = 0 - # Plot spectrum + if isinstance(self.hsi.data, _h5py.Dataset): - self.plotter.plot(self.hsi.f, mean_spect, label='Spectrum ({})'.format(mask_hits)) + # * Can't do fancy boolean indexing with HDF + # * Make a square bounding box + rmin = mloc.min() + rmax = mloc.max()+1 + cmin = nloc.min() + cmax = nloc.max()+1 - # Check color of line b/c uses color cycler-- for fill_b/w - color = self.plotter.list_all[-1].style_dict['color'] + spectra = self.hsi.data[rmin:rmax, cmin:cmax,:][Mask[rmin:rmax, cmin:cmax]==1] + + else: + spectra = self.hsi.data[Mask == 1] + + if _np.iscomplexobj(spectra) & self.ui.actionUseImagData.isChecked(): + spectra = spectra.imag + else: + spectra = spectra.real - # Alternative - #color = self.plotter.modelLine._model_data[-1]['color'] + if mask_hits > 1: + spectrum = _np.mean(spectra[..., rng], axis=0) + stddev = _np.std(spectra[..., rng], axis=0) + else: + spectrum = _np.squeeze(spectra[..., rng]) + stddev = 0 + + self.plotter.plot(self.hsi.f, spectrum, label='Mean spectrum ({})'.format(mask_hits)) + + # Check color of line b/c uses color cycler-- for fill_b/w + color = self.plotter.list_all[-1].style_dict['color'] - # Plot +-1 std. dev. - if mask_hits > 1: - self.plotter.fill_between(self.hsi.f, mean_spect - std_spect, - mean_spect + std_spect, - color=color, - alpha=0.25, - label=r'$\pm$1 Std. Dev. ({})'.format(mask_hits)) + # Alternative + #color = self.plotter.modelLine._model_data[-1]['color'] + + # Plot +-1 std. dev. + if mask_hits > 1: + self.plotter.fill_between(self.hsi.f, spectrum - stddev, + spectrum + stddev, + color=color, + alpha=0.25, + label=r'$\pm$1 Std. Dev. ({})'.format(mask_hits)) self.plotter.show() @@ -2629,7 +3056,7 @@ def createImgBW(self, img): self.img_BW.createImg(img=img, xunits=xunits, yunits=yunits, - extent=extent, + extent=extent, cmap=self.img_BW.colormode.ui.comboBoxColormap.currentText()) if self.img_BW.ui.checkBoxFixed.checkState()==0: @@ -2659,7 +3086,18 @@ def changeSlider(self): self.ui.lineEditFreq.setText(str(round(self.hsi.f[pos],2))) # Set BW Class Data - self.img_BW.data.grayscaleimage = self.hsi.data_imag_over_real[:, :, pos+offset] + self.img_BW.data.grayscaleimage = self.hsi.data[:, :, pos+offset] + if _np.iscomplexobj(self.img_BW.data.grayscaleimage) & self.ui.actionUseImagData.isChecked(): + self.img_BW.data.grayscaleimage = self.img_BW.data.grayscaleimage.imag + else: + self.img_BW.data.grayscaleimage = self.img_BW.data.grayscaleimage.real + + val_extrema = _np.max(_np.abs(self.img_BW.data.grayscaleimage)) + + self.img_BW.ui.spinBoxMin.setMinimum(-1.1*val_extrema) + self.img_BW.ui.spinBoxMin.setMaximum(1.1*val_extrema) + self.img_BW.ui.spinBoxMax.setMinimum(-1.1*val_extrema) + self.img_BW.ui.spinBoxMax.setMaximum(1.1*val_extrema) xlabel = '' if isinstance(self.hsi.x_rep.label, str): @@ -2685,11 +3123,11 @@ def changeSlider(self): # if self.img_BW.ui.checkBoxFixed.checkState() == 0: # self.img_BW.data.setmax = None # self.img_BW.data.setmin = None - + # Set axis to original limits self.img_BW.mpl.ax.axis(orig_axis_lims) - if not self._mpl_v2: + if self._mpl_v1: self.img_BW.mpl.ax.hold(True) except: @@ -2723,16 +3161,29 @@ def changeSlider(self): ls=ls, ms=ms, alpha=a, label=label) - if self.ui.actionShowOverlayLegend.isChecked(): + if self.ui.actionShowOverlayLegend.isChecked(): + if self.overlays: try: - self.img_BW.mpl.ax.legend(loc='best') + # self.img_BW.mpl.ax.legend(loc='best') + lg = self.img_BW.mpl.ax.legend(loc='lower left', + mode='expand', + bbox_to_anchor=(0.01, 1.02, 1., 0.2), + ncol=2, fontsize=9) + self.img_BW.mpl.ax.add_artist(lg) + try: + self.img_BW.mpl.fig.tight_layout(pad=1) + except: + print('tight_layout failed (CrikitUI: 3') except: - pass + print('Error in showing overlay legend') except: print('Error in changeSlider: display overlays') self.img_BW.mpl.draw() + if self.ui.actionShowPreviewROI.isChecked(): + self.showPreviewRois() + if self.bcpre.backed_flag.count(True) > 1: self.ui.actionUndo.setEnabled(True) else: @@ -2793,7 +3244,7 @@ def doComposite(self): self.img_Composite2.initData(self.img_RGB_list) self.img_Composite2.changeMode() - + self.img_Composite2.data.set_x(self.hsi.x, xlabel) self.img_Composite2.data.set_y(self.hsi.y, ylabel) self.img_Composite2.createImg(img=self.img_Composite2.data.image, @@ -2831,7 +3282,7 @@ def makeRamanPhantom(self): dialog = DialogModel.dialogModel(cplx=cplx, parent=self) if dialog is not None: model = _Model(subsample=dialog['subsample']) - + wn_start = dialog['wn_start'] wn_end = dialog['wn_end'] @@ -2842,23 +3293,23 @@ def makeRamanPhantom(self): lam_end *= 1e9 # nm lam_ctr = (lam_start + lam_end) / 2 # nm - + n_pix = _np.ceil((lam_end-lam_start) / dialog['wl_slope']) # Make a properly linear frequency-vector and polyfit f = dialog['wl_slope'] * _np.arange(n_pix) # Temporary frequency vec f -= f.mean() f += lam_ctr - + a_vec = _np.polyfit(_np.arange(n_pix), f, 1) - + calib = {'a_vec': a_vec, 'ctr_wl': lam_ctr, 'ctr_wl0': lam_ctr, 'n_pix': n_pix, 'probe': dialog['probe'], 'units': 'nm'} - + f = _calib_pix_wn(calib)[0] model.make_hsi(f=f) @@ -2929,8 +3380,8 @@ def makeRamanPhantom(self): self.changeSlider() else: pass - - + + def makeBCARSPhantom(self): """ Generate a numerical phantom for BCARS @@ -2940,7 +3391,7 @@ def makeBCARSPhantom(self): dialog = DialogModel.dialogModel(cplx=cplx, parent=self) if dialog is not None: model = _Model(subsample=dialog['subsample']) - + wn_start = dialog['wn_start'] wn_end = dialog['wn_end'] @@ -2951,23 +3402,23 @@ def makeBCARSPhantom(self): lam_end *= 1e9 # nm lam_ctr = (lam_start + lam_end) / 2 # nm - + n_pix = _np.ceil((lam_end-lam_start) / dialog['wl_slope']) # Make a properly linear frequency-vector and polyfit f = dialog['wl_slope'] * _np.arange(n_pix) # Temporary frequency vec f -= f.mean() f += lam_ctr - + a_vec = _np.polyfit(_np.arange(n_pix), f, 1) - + calib = {'a_vec': a_vec, 'ctr_wl': lam_ctr, 'ctr_wl0': lam_ctr, 'n_pix': n_pix, 'probe': dialog['probe'], 'units': 'nm'} - + f = _calib_pix_wn(calib)[0] model.make_hsi(f=f) @@ -2990,7 +3441,7 @@ def makeBCARSPhantom(self): self.nrb.data = _np.abs(source*nrb)**2 self.nrb.freq = self.hsi.freq - + add_gnoise = dialog['gnoise_bool'] # AWGN (Gaussian) add_pnoise = dialog['pnoise_bool'] # Poisson noise add_dark = dialog['dark_bool'] # Dark background -- just a constant @@ -3054,13 +3505,13 @@ def makeBCARSPhantom(self): self.changeSlider() else: pass - + def crikit_launch(**kwargs): """ Command line launching of CRIkitUI. Input kwargs (Optional) - ------------ + ------------------------ hsi : crikit.data.Hsi Hsi instance @@ -3115,7 +3566,7 @@ def crikit_launch(**kwargs): obj = _QWidget() else: obj = parent - + kwargs['parent'] = obj # print('Kwargs: {}'.format(kwargs)) win = CRIkitUI_process(**kwargs) ### EDIT ### diff --git a/crikit/cri/algorithms/kk.py b/crikit/cri/algorithms/kk.py index b7a294b..2f79c1b 100644 --- a/crikit/cri/algorithms/kk.py +++ b/crikit/cri/algorithms/kk.py @@ -18,6 +18,8 @@ import numpy as _np from scipy import fftpack as _fftpack +from crikit.utils.general import pad as _pad + __all__ = ['kkrelation', 'hilbertfft'] _DEFAULT_THREADS = 1 @@ -119,7 +121,6 @@ def kkrelation(bg, cri, phase_offset=0.0, norm_by_bg=True, pad_factor=1): return out # return _ne.evaluate('sqrt(cri)*exp(1j*phase_offset + 1j*h)') - def hilbertfft(spectra, pad_factor=1, use_pyfftw=True): """ Compute the one-dimensional Hilbert Transform. @@ -158,18 +159,16 @@ def hilbertfft(spectra, pad_factor=1, use_pyfftw=True): freq_len = spectra.shape[-1] freq_pad_len = freq_len*(2*pad_factor+1) - pad_len = freq_len*(pad_factor) time_vec = _np.fft.fftfreq(freq_pad_len) if pad_factor > 0: - pad_left = _np.dot(spectra[..., 0][..., None], _np.ones((1, pad_len))) - pad_right = _np.dot(spectra[..., -1][..., None], _np.ones((1, pad_len))) - padded = _np.concatenate((pad_left, spectra, pad_right), axis=-1) + padded, window = _pad(spectra, pad_factor*spectra.shape[-1], 'edge') else: padded = spectra + window = None padded = padded.astype(_np.complex) - + # Use pyFFTW (supposed optimal) library or Scipy # Note (although not obvious with pyFFTW) these functions overwrite # the input variable-- saves memory and increases speed @@ -197,7 +196,10 @@ def hilbertfft(spectra, pad_factor=1, use_pyfftw=True): padded[_np.isnan(padded)] = 1e-8 padded[_np.isinf(padded)] = 1e-8 - return _np.real(padded[..., pad_len:pad_len + freq_len]) + if window is not None: + return padded[..., window == 1].real + else: + return padded.real if __name__ == '__main__': # pragma: no cover import timeit as _timeit diff --git a/crikit/cri/error_correction.py b/crikit/cri/error_correction.py index 5170c4b..a4a523d 100644 --- a/crikit/cri/error_correction.py +++ b/crikit/cri/error_correction.py @@ -27,7 +27,7 @@ class PhaseErrCorrectALS: def __init__(self, smoothness_param=1, asym_param=1e-2, redux=10, order=2, rng=None, fix_end_points=False, fix_rng=None, fix_const=1, max_iter=100, min_diff=1e-5, - **kwargs): + verbose=True, **kwargs): self.rng = _rng_is_pix_vec(rng) @@ -42,7 +42,8 @@ def __init__(self, smoothness_param=1, asym_param=1e-2, 'fix_rng' : fix_rng, 'fix_const' : fix_const, 'max_iter' : max_iter, - 'min_diff' : min_diff}) + 'min_diff' : min_diff, + 'verbose' : verbose}) def _calc(self, data, ret_obj, **kwargs): @@ -59,7 +60,8 @@ def _calc(self, data, ret_obj, **kwargs): counter = 1 for idx in _np.ndindex(shp): - print('Detrended iteration {} / {}'.format(counter, total_num)) + if self._k['verbose']: + print('Detrended iteration {} / {}'.format(counter, total_num)) ph = _np.unwrap(_np.angle(data[idx])) # if self.rng is None: err_phase = self._inst_als.calculate(ph) diff --git a/crikit/cri/tests/__init__.py b/crikit/cri/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/crikit/cri/tests/test_hilbert.py b/crikit/cri/tests/test_hilbert.py index 367a17e..659d0b2 100644 --- a/crikit/cri/tests/test_hilbert.py +++ b/crikit/cri/tests/test_hilbert.py @@ -16,6 +16,7 @@ def test_pyfftw_hilbert_no_pad(): y = 2/(2**2 + x**2) hilb_y = hilbertfft(y, pad_factor=0, use_pyfftw=True) hilb_y_analytical = x/(2**2 + x**2) + print(hilb_y.shape) assert_array_almost_equal(hilb_y_analytical, hilb_y, decimal=2) def test_pyfftw_hilbert_pad(): diff --git a/crikit/data/frequency.py b/crikit/data/frequency.py index 1132707..426e3d7 100644 --- a/crikit/data/frequency.py +++ b/crikit/data/frequency.py @@ -87,7 +87,7 @@ class Frequency: are items of interest or a large dynamic range across a spectrum. - For functions, methods, etc. that take into account _list_ \ - parameters, they should default to op_list_ if plot_list_ are set to \ + parameters, they should default to op_list_* if plot_list_* are set to \ None. """ @@ -214,7 +214,7 @@ def update(self): else: self.calib = self._calib_orig - self.data, self.units = self.calib_fcn(self.calib) + self.data, self.units = self.calib_fcn(self.calib) # pylint: disable=not-callable @property def op_list_pix(self): @@ -227,6 +227,7 @@ def op_list_pix(self,value): value = list(value) value.sort() self._op_list_pix = value + # if self.data is not None: # ! Allow setting without freq or not? self._op_list_freq = self.get_closest_freq(value) self._op_list_freq.sort() elif len(value) != 2 and _np.mod(len(value),2) == 0 and len(value) != 0: @@ -427,13 +428,17 @@ def calib_pix_wn(calib_obj): if 'units' not in calib: calib['units'] = 'nm' - factor = 1e7 - elif calib['units'] == 'nm': + elif isinstance(calib['units'], bytes): + calib['units'] = calib['units'].decode() + + if calib['units'] == 'nm': factor = 1e7 elif calib['units'] == 'um': factor = 1e4 else: - raise ValueError('Only nanometer (\'nm\') and micrometer (\'um\') units accepted') + errstr1 = 'Only nanometer (\'nm\') and micrometer (\'um\') units accepted. ' + errstr2 = '{} provided of type {}.'.format(calib['units'], type(calib['units'])) + raise ValueError(errstr1 + errstr2) wl_vec, _ = calib_pix_wl(calib_obj) wn_vec = factor/wl_vec - factor/calib['probe'] return (wn_vec, 'cm$^{-1}$') diff --git a/crikit/data/hsi.py b/crikit/data/hsi.py index 1716a68..16c190b 100644 --- a/crikit/data/hsi.py +++ b/crikit/data/hsi.py @@ -54,12 +54,6 @@ class Hsi(_Spectrum): Attributes ---------- - data_imag_over_real : ndarray (3D) - If data is complex, return the imaginary portion - - data_real_over_imag : ndarray (3D) - If data is complex, return the real portion - shape : tuple, read-only Shape of data @@ -81,12 +75,16 @@ class Hsi(_Spectrum): Notes ----- - * freq object contains some useful parameters such as op_range_\* and \ - plot_range_\*, which define spectral regions-of-interest. (It's debatable \ + * freq object contains some useful parameters such as op_range_* and \ + plot_range_*, which define spectral regions-of-interest. (It's debatable \ as to whether those parameters should be in Frequency or Spectrum classes) """ + # Configurations + config = {} + config['nd_axis'] = -1 + def __init__(self, data=None, freq=None, x=None, y=None, x_rep=None, y_rep=None, label=None, units=None, meta=None): @@ -103,6 +101,42 @@ def __init__(self, data=None, freq=None, x=None, y=None, x_rep=None, if y is None and y_rep is not None: self.y_rep = _copy.deepcopy(y_rep) + @staticmethod + def _mean_axes(*args, **kwargs): + """ Inhereted from Spectrum """ + raise NotImplementedError('Only applicable to Spectrum class.') + + @staticmethod + def _reshape_axes(shape, spectral_axis): + """ + Parameters + ---------- + shape : tuple + Input data shape + + spectral_axis : int + Spectral axis + + Returns + ------- + Reshape vector + """ + ndim = len(shape) + + if ndim == 1: + out = [1, 1, 1] + out[spectral_axis] = shape[0] + elif ndim == 2: # ! Super-wonky + out = [1, shape[0], shape[1]] + elif ndim == 3: + out = shape + elif ndim > 3: + out = [-1, shape[-2], shape[-1]] + else: + raise ValueError('Shape error') + + return tuple(out) + @property def mask(self): return self._mask @@ -152,35 +186,28 @@ def data(self): @data.setter def data(self, value): - if isinstance(value, _np.ndarray): - if value.ndim == 3: - if self.freq is None or self.freq.op_list_pix is None: - self._data = value - self._mask = _np.ones((self._data.shape[0], - self._data.shape[1]), - dtype=_np.int) - else: - if value.shape[-1] == self.freq.op_range_pix.size: - temp = _np.zeros((self._data.shape),dtype=value.dtype) - temp[:,:,self.freq.op_range_pix] = value - self._data = temp - self._mask = _np.ones((self._data.shape[0], - self._data.shape[1]), - dtype=_np.int) - elif value.shape[-1] == self._data.shape[-1]: - self._data = value - self._mask = _np.ones((self._data.shape[0], - self._data.shape[1]), - dtype=_np.int) - else: - #raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) - raise TypeError('pre-data: {}, value: {}'.format(self._data.shape,value.shape)) - else: - raise TypeError('data must be 3D') - else: - print('Assigning non-ndarray to data. Not shape checking') - self._data = value + if not isinstance(value, _np.ndarray): + raise TypeError('data must be of type ndarray') + + ax_rs = self._reshape_axes(value.shape, self.config['nd_axis']) + # self._mask = _np.ones(tuple([n for n in range(3) if n != self.config['nd_axis']]), + # dtype=_np.int) + + if self.freq is None or self.freq.op_list_pix is None: + self._data = value.reshape(ax_rs) + else: + if value.shape[self.config['nd_axis']] == self.freq.op_range_pix.size: + temp = _np.zeros((self._data.shape),dtype=value.dtype) + temp[:,:,self.freq.op_range_pix] = value.reshape(ax_rs) + self._data = 1*temp + del temp + elif value.shape[self.config['nd_axis']] == self._data.shape[self.config['nd_axis']]: + temp = _np.zeros((self._data.shape),dtype=value.dtype) + temp[..., self.freq.op_range_pix] = value.reshape(ax_rs)[..., self.freq.op_range_pix] + self._data = 1*temp + del temp + def check(self): """ Check x, y, and freq to make sure the dimensions agree with data diff --git a/crikit/data/mosaic.py b/crikit/data/mosaic.py new file mode 100644 index 0000000..747b8da --- /dev/null +++ b/crikit/data/mosaic.py @@ -0,0 +1,376 @@ +import numpy as _np +import h5py as _h5py + +class Mosaic: + """ + Mosaic Class + + Notes + ----- + + - input objects mts be ndarray + - input objects must be 2D/3D # ! Higher-D? + - For 3D objects, assumed to be Y, X, Color + + """ + def __init__(self): + self._data = None + + self.parameters = {} + self.parameters['StartC'] = 0 + self.parameters['StartR'] = 0 + self.parameters['EndC'] = -0 + self.parameters['EndR'] = -0 + self.parameters['Transpose'] = False + self.parameters['FlipVertical'] = False + self.parameters['FlipHorizontally'] = False + self.parameters['Order'] = 'R' + self.parameters['Compress'] = False + self.parameters['Shape'] = [1, 1] + + def __repr__(self): # pragma: no cover + if self._data: + return 'Mosaic contains {} component(s)'.format(self.size) + else: + return 'Empty Collection' + + def attr_dict(self, prefix='Mosaic.'): + temp = {} + for k in self.parameters: + temp.update({prefix+k:self.parameters[k]}) + return temp + + @property + def shape(self): + if self._data: + return tuple([q.shape for q in self._data]) + + @property + def size(self): + if isinstance(self._data, list): + return len(self._data) + + def append(self, obj): + """ Append new object to data. Check dimensions """ + if not (isinstance(obj, _np.ndarray) | isinstance(obj, _h5py.Dataset)): + raise TypeError('Appended object must be a numpy array') + if not ((obj.ndim > 1) & (obj.ndim <= 3)): + raise TypeError('Appended object must be a numpy array with ndim 2 or 3') + + if not self._data: + self._data = [] + + if self._data: + if not _np.unique([q.ndim for q in self._data])[0] == obj.ndim: + err_str1 = 'New component ndim must match existing ndim' + err_str2 = ' ({})'.format(self._data[0].ndim) + raise TypeError(err_str1 + err_str2) + + self._data.append(obj) + + @property + def issamedim(self): + if self._data: + return _np.unique([q.ndim for q in self._data]).size == 1 + + @property + def is2d(self): + if self._data: + if not self.issamedim: + raise TypeError('Not every component is of the same dimension') + return len(self.unitshape) == 2 + + @property + def is3d(self): + if self._data: + if not self.issamedim: + raise TypeError('Not every component is of the same dimension') + return len(self.unitshape) == 3 + + + @property + def unitshape(self): + if self.parameters['EndR'] > 0: + raise ValueError('parameter EndR must be <= 0') + if self.parameters['EndC'] > 0: + raise ValueError('parameter EndC must be <= 0') + + if self._data: + temp = list(self.unitshape_orig) + + sr = self.parameters['StartR'] + er = self.parameters['EndR'] + sc = self.parameters['StartC'] + ec = self.parameters['EndC'] + + temp[0] -= (sr - er) + temp[1] -= (sc - ec) + + return tuple(temp) + + @property + def unitshape_orig(self): + if self._data: + return tuple(_np.array(self.shape).max(axis=0).tolist()) + + + @property + def dtype(self): + """ Return the highest dtype """ + if self._data: + dt = [q.dtype.kind for q in self._data] + + if dt.count('c') > 0: + return _np.complex + elif dt.count('f') > 0: + return _np.float + elif dt.count('i') > 0: + return _np.int + + + def mosaic_shape(self, shape=None, idx=None): + """ Return the shape of a would-be mosaic """ + if shape is None: + shape = self.parameters['Shape'] + else: + self.parameters['Shape'] = shape + + if self._data: + if not len(shape) == 2: + raise ValueError('Shape must be a tuple/list with 2 entries (Y, X)') + + if _np.prod(shape) < self.size: + raise ValueError('The total number of subimages (shape) need be >= number of components ({})'.format(self.size)) + + us = list(self.unitshape) + + if self.parameters['Transpose']: + temp = 1*us[0] + us[0] = us[1] + us[1] = temp + + if (len(us) == 3): + if idx is None: + out_is2d = False + else: + out_is2d = True + else: + out_is2d = True + + if out_is2d: + return (shape[0]*us[0], shape[1]*us[1]) + else: + return (shape[0]*us[0], shape[1]*us[1], us[2]) + + def _mosaic(self, shape=None, idx=None, out=None, mask=False): + """ Mosaic super method """ + if shape is None: + shape = self.parameters['Shape'] + else: + self.parameters['Shape'] = shape + + compress = self.parameters['Compress'] + + if self._data: + if mask: + idx = 0 + + if not len(shape) == 2: + raise ValueError('Shape must be a tuple/list with 2 entries (Y, X)') + + if _np.prod(shape) < self.size: + raise ValueError('The total number of subimages (shape) need be >= number of components ({})'.format(self.size)) + + if out is None: + if not mask: + out = _np.zeros(self.mosaic_shape(shape=shape, idx=idx), + dtype=self.dtype) + else: + # For mask, start at -1 + out = -1 + _np.zeros(self.mosaic_shape(shape=shape, idx=idx), + dtype=self.dtype) + out_provided = False + else: + out_provided = True + + sr = 1*self.parameters['StartR'] + sc = 1*self.parameters['StartC'] + er = 1*self.parameters['EndR'] + ec = 1*self.parameters['EndC'] + if sr == 0: + sr = None + if sc == 0: + sc = None + if er == 0: + er = None + if ec == 0: + ec = None + + # Slice to take on each sub-image + slice_sub_r = slice(sr, er, 1) + slice_sub_c = slice(sc, ec, 1) + + sub_img_counter = 0 + num_components = self.size + + order = self.parameters['Order'] + + if order == 'C': + sh_outter = shape[0] + sh_inner = shape[1] + else: # Order == 'R' + sh_outter = shape[1] + sh_inner = shape[0] + + # * h5 write_direct has strict limitations + cannot_write_direct = (self.parameters['Transpose'] | + self.parameters['FlipVertical'] | + self.parameters['FlipHorizontally']) + + # * Only used by out matrix + us = list(self.unitshape) + if self.parameters['Transpose']: + temp = 1*us[0] + us[0] = us[1] + us[1] = temp + + for num_outter in range(sh_outter): + for num_inner in range(sh_inner): + if order == 'C': + numR = num_outter + numC = num_inner + else: # Order == 'R' + numC = num_outter + numR = num_inner + + if sub_img_counter < num_components: + if mask: + data = sub_img_counter * \ + _np.ones(self._data[sub_img_counter][slice_sub_r, + slice_sub_c].shape[0:2], + dtype=_np.int) + elif idx is None: + data = self._data[sub_img_counter][slice_sub_r, slice_sub_c] + else: + data = self._data[sub_img_counter][slice_sub_r, slice_sub_c, idx] + + data_is2d = (data.ndim == 2) + + if self.parameters['FlipHorizontally']: + data = _np.flip(data, axis=1) + if self.parameters['FlipVertical']: + data = _np.flip(data, axis=0) + if self.parameters['Transpose']: + if data_is2d: + data = data.T + else: + data = _np.transpose(data, axes=(1,0,2)) + + # * Using this in case m/ndata is smaller than u[0/1] + mdata, ndata = data.shape[0], data.shape[1] + + if isinstance(out, _h5py.Dataset) & (not cannot_write_direct): + out.write_direct(source=data, + dest_sel=_np.s_[(numR*us[0]):(numR*us[0] + mdata), + (numC*us[1]):(numC*us[1] + ndata)]) + else: + out[(numR*us[0]):(numR*us[0] + mdata), + (numC*us[1]):(numC*us[1] + ndata)] = 1*data + sub_img_counter += 1 + + if not out_provided: + if not compress: + return out + else: + if mask: # Cute trick since first ROI is +0 and blank is -1 + out += 1 + + if out.ndim == 3: + out = out[:, (out.sum(axis=0)[:, 0] != 0), :] + out = out[(out.sum(axis=1)[:, 0] != 0), :, :] + + else: # 2D + out = out[:, (out.sum(axis=0) != 0)] + out = out[(out.sum(axis=1) != 0), :] + if mask: # Cute trick since first ROI is +0 and blank is -1 + out -= 1 + return out + + def mosaic2d(self, shape=None, idx=None, out=None): + """ Return 2D mosaic image""" + + if self._data: + if (self.is3d & (idx is None)): + raise ValueError('With 3D components, idx must be provided') + + return self._mosaic(shape=shape, idx=idx, out=out) + + def mosaic_mask(self, shape=None, out=None): + """ Returns a 2D mosaic image with integer values for which img is where """ + + return self._mosaic(shape=shape, out=out, mask=True) + + def mosaicfull(self, shape=None, out=None): + """ Return full mosaic """ + + if self._data: + return self._mosaic(shape=shape, idx=None, out=out) + +if __name__ == '__main__': + mos = Mosaic() + mos.parameters['StartR'] = 1 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + mos.parameters['Transpose'] = True + mos.parameters['FlipVertical'] = True + mos.parameters['FlipHorizontally'] = True + + m_obj = 3 + n_obj = 4 + p_obj = 5 + + # MANUALLY SET BASED ON PARAMS ABOVE + m_obj_crop = m_obj - 2 + n_obj_crop = n_obj - 2 + p_obj_crop = p_obj + + new_obj = _np.ones((m_obj, n_obj, p_obj)) + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + # NOT AFFECTED BY START* END* + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == _np.float + + # AFFECTED BY START* END* + assert mos.unitshape == (m_obj_crop, n_obj_crop, p_obj_crop) + assert mos.unitshape_orig == (m_obj, n_obj, p_obj) + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side), idx=0).T.shape == (m_side * m_obj_crop, + n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, + n_side))[:-1] + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side), idx=0).T.shape == (m_side * m_obj_crop, + n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + + mos.parameters['Order'] = 'R' + assert mos.mosaicfull((m_side, n_side)).transpose(1,0,2).shape == (m_side * m_obj_crop, + n_side * n_obj_crop, p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaicfull((m_side, n_side)).transpose(1,0,2).shape == (m_side * m_obj_crop, + n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) \ No newline at end of file diff --git a/crikit/data/spectra.py b/crikit/data/spectra.py index 0f7dc4b..3d15340 100644 --- a/crikit/data/spectra.py +++ b/crikit/data/spectra.py @@ -62,43 +62,77 @@ class Spectra(_Spectrum): Notes ----- - * freq object contains some useful parameters such as op_range_\* and \ - plot_range_\*, which define spectral regions-of-interest. (It's debatable \ + * freq object contains some useful parameters such as op_range* and \ + plot_range*, which define spectral regions-of-interest. (It's debatable \ as to whether those parameters should be in Frequency or Spectrum classes) """ + # Configurations + config = {} + config['nd_axis'] = -1 + def __init__(self, data=None, freq=None, label=None, units=None, meta=None): super().__init__(data, freq, label, units, meta) self._reps = _Replicate() + @staticmethod + def _mean_axes(*args, **kwargs): + """ Inhereted from Spectrum """ + raise NotImplementedError('Only applicable to Spectrum class.') + + @staticmethod + def _reshape_axes(shape, spectral_axis): + """ + Parameters + ---------- + shape : tuple + Input data shape + + spectral_axis : int + Spectral axis + + Returns + ------- + Reshape vector + """ + ndim = len(shape) + + if ndim >= 2: + out = [-1, -1] + else: + out = [1, 1] + + out[spectral_axis] = shape[spectral_axis] + return tuple(out) + @property def data(self): return self._data @data.setter def data(self, value): - if isinstance(value, _np.ndarray): - if self.freq.data is None or self.freq.op_list_pix is None: - if value.ndim == 1: - print('Spectra: converting data input from 1D to 2D ndarray') - self._data = value[None,:] - elif value.ndim == 2: - self._data = value - else: - print('Spectra: converting data input from {}D to 2D ndarray'.format(value.ndim)) - f_sh = value.shape[-1] - self._data = value.reshape((-1, f_sh)) - else: - if value.shape[-1] == self.freq.op_range_pix.size: - temp = _np.zeros((self._data.shape),dtype=value.dtype) - temp[:,self.freq.op_range_pix] = value - self._data = temp - else: - raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) + if not isinstance(value, _np.ndarray): + raise TypeError('data must be of type ndarray') + + if self.freq.data is None or self.freq.op_list_pix is None: + if value.ndim != 2: + print('Spectra: converting data input from {}D to 2D ndarray'.format(value.ndim)) + ax_rs = self._reshape_axes(value.shape, spectral_axis=self.config['nd_axis']) + self._data = value.reshape(ax_rs) else: - print('Assigning non-ndarray to data. Not shape checking') - self._data = value + if value.ndim != 2: + print('Spectra: converting data input from {}D to 2D ndarray'.format(value.ndim)) + if value.shape[-1] == self.freq.op_range_pix.size: + temp = _np.zeros((self._data.shape), dtype=value.dtype) + temp[:,self.freq.op_range_pix] = value + self._data = temp + elif value.shape[-1] == self.freq.size: + temp = _np.zeros((self._data.shape), dtype=value.dtype) + temp[..., self.freq.op_range_pix] = value[..., self.freq.op_range_pix].reshape((-1, len(self.freq.op_range_pix))) + self._data = temp + else: + raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) @property def n_pix(self): diff --git a/crikit/data/spectrum.py b/crikit/data/spectrum.py index e46d070..4abc8d1 100644 --- a/crikit/data/spectrum.py +++ b/crikit/data/spectrum.py @@ -60,12 +60,17 @@ class Spectrum: Notes ----- - * freq object contains some useful parameters such as op_range_\* and \ - plot_range_\*, which define spectral regions-of-interest. (It's debatable \ + * freq object contains some useful parameters such as op_range* and \ + plot_range*, which define spectral regions-of-interest. (It's debatable \ as to whether those parameters should be in Frequency or Spectrum classes) """ + # Configurations + config = {} + config['nd_axis'] = -1 + config['nd_fcn'] = _np.mean + def __init__(self, data=None, freq=None, label=None, units=None, meta=None): self._data = None @@ -87,47 +92,68 @@ def __init__(self, data=None, freq=None, label=None, units=None, meta=None): if meta is not None: self._meta = _copy.deepcopy(meta) + @staticmethod + def _mean_axes(ndim, axis): + """ + Parameters + ---------- + ndim : int + Number of dimensions of input data (target is 1D spectrum) + + axis : int + For ND data, axis is remaining axis + + Returns + ------- + Vector that describes what axes to operate (using a mean or similar method) with + axis parameter + """ + if axis < 0: + axis2 = ndim + axis + else: + axis2 = axis + return tuple([n for n in range(ndim) if n != axis2]) + @property def data(self): return self._data @data.setter def data(self, value): - if isinstance(value, _np.ndarray): - if value.ndim == 1: - if self.freq is not None and self.freq.op_list_pix is not None: - if value.shape[-1] == self.freq.op_range_pix.size: - temp = _np.zeros((self.freq.size),dtype=value.dtype) - temp[self.freq.op_range_pix] = value - self._data = temp - else: - raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) + if not isinstance(value, _np.ndarray): + raise TypeError('data must be of type ndarray') + + # If sub-range of operation is defined. Only perform action over op_range_pix + if self.freq is not None and self.freq.op_list_pix is not None: + if value.shape[self.config['nd_axis']] == self.freq.op_range_pix.size: + temp = _np.zeros((self.freq.size), dtype=value.dtype) + if value.ndim == 1: + temp[self.freq.op_range_pix] = value else: - self._data = value - else: - raise TypeError('data must be a 1D ndarray') - else: - raise TypeError('data must be a 1D ndarray') + print('Input data is {}-dim. Performing {}'.format(value.ndim, self.config['nd_fcn'].__name__)) + nd_ax = self._mean_axes(value.ndim, axis=self.config['nd_axis']) + temp[self.freq.op_range_pix] = self.config['nd_fcn'](value, axis=nd_ax) + elif value.shape[self.config['nd_axis']] == self.freq.size: + temp = _np.zeros((self.freq.size), dtype=value.dtype) + if value.ndim == 1: + temp[self.freq.op_range_pix] = value[self.freq.op_range_pix] + else: + print('Input data is {}-dim. Performing {}'.format(value.ndim, self.config['nd_fcn'].__name__)) + nd_ax = self._mean_axes(value.ndim, axis=self.config['nd_axis']) + temp[self.freq.op_range_pix] = self.config['nd_fcn'](value, axis=nd_ax)[self.freq.op_range_pix] - @property - def data_imag_over_real(self): - if _np.iscomplexobj(self._data): - if isinstance(self._data, _np.ndarray): - return self._data.imag else: - return _np.imag(self._data) + raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) + self._data = 1*temp + del temp else: - return self._data - - @property - def data_real_over_imag(self): - if _np.iscomplexobj(self._data): - if isinstance(self._data, _np.ndarray): - return self._data.real + if value.ndim == 1: + self._data = value else: - return _np.real(self._data) - else: - return self._data + print('Input data is {}-dim. Performing {}'.format(value.ndim, self.config['nd_fcn'].__name__)) + nd_ax = self._mean_axes(value.ndim, axis=self.config['nd_axis']) + self._data = self.config['nd_fcn'](value, axis=nd_ax) + @property def freq(self): @@ -364,10 +390,3 @@ def __sub__(self, spectrum): sp.data[200:500] tmr -= _timeit.default_timer() print(-tmr) - - tmr = _timeit.default_timer() - locs = _np.arange(sp.freq.get_index_of_closest_freq(500), - sp.freq.get_index_of_closest_freq(600)) - sp.data_imag_over_real[locs] - tmr -= _timeit.default_timer() - print(-tmr) diff --git a/crikit/data/tests/test_hsi.py b/crikit/data/tests/test_hsi.py new file mode 100644 index 0000000..13e9437 --- /dev/null +++ b/crikit/data/tests/test_hsi.py @@ -0,0 +1,121 @@ +import os +import numpy as np +import numpy.testing + +import pytest +import lazy5 + +from crikit.io.hdf5 import hdf_import_data +from crikit.data.spectrum import Spectrum +from crikit.data.spectra import Spectra +from crikit.data.hsi import Hsi + +@pytest.fixture(scope="function") +def make_datasets(): + """ Setups and tears down a series of datasets """ + + data_m, data_n, data_p = [20, 22, 24] + spectrum = np.random.randn(data_p)**2 + 1 + spectra = np.random.randn(data_n, data_p)**2 + 1 + hsi = np.random.randn(data_m, data_n, data_p)**2 + 1 + + return spectrum, spectra, hsi, np.array([data_m, data_n, data_p]) + +def test_mean_axes_static(): + """ Ensure mean_axes_static raises an error""" + + with pytest.raises(NotImplementedError): + Hsi._mean_axes() + +def test_reshape_axes_static(make_datasets): + """ Test reshape axes static method """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + Hsi._reshape_axes(shape=hsi.shape, spectral_axis=-1) == (-1, hsi.shape[-1]) + Hsi._reshape_axes(shape=spectra.shape, spectral_axis=-1) == (-1, spectra.shape[-1]) + Hsi._reshape_axes(shape=spectrum.shape, spectral_axis=-1) == (-1, spectrum.shape[-1]) + +def test_hsi_to_hsi(make_datasets): + """ Import an hsi into an hsi """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Hsi() + new_dataset.data = hsi + + assert new_dataset.size == hsi.size + np.testing.assert_array_equal(new_dataset.data, hsi) + +def test_hsi_to_hsi_rng(make_datasets): + """ Import an hsi into an hsi -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Hsi() + new_dataset.freq.data = np.arange(hsi.shape[-1]) + new_dataset.data = hsi + new_dataset.freq.op_list_pix = rng + new_dataset.data = hsi + + assert new_dataset.size == hsi.size + assert (new_dataset.data != 0).sum() == len(rng)*np.prod(hsi.shape[:-1]) + np.testing.assert_almost_equal(new_dataset.data[..., rng], hsi[..., rng]) + +def test_spectrum_to_hsi(make_datasets): + """ Import a spectrum into an hsi """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Hsi() + new_dataset.data = spectrum + + assert new_dataset.size == spectrum.size + np.testing.assert_array_equal(np.squeeze(new_dataset.data), spectrum) + +def test_spectrum_to_hsi_rng(make_datasets): + """ Import a spectrum into an hsi -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Hsi() + new_dataset.freq.data = np.arange(hsi.shape[-1]) + new_dataset.data = spectrum + new_dataset.freq.op_list_pix = rng + new_dataset.data = spectrum + + assert new_dataset.size == spectrum.size + assert (new_dataset.data != 0).sum() == len(rng) + np.testing.assert_almost_equal(np.squeeze(new_dataset.data[..., rng]), spectrum[rng]) + +def test_spectra_to_hsi(make_datasets): + """ Import spectra into an hsi """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Hsi() + new_dataset.data = spectra + + assert new_dataset.size == spectra.size + np.testing.assert_array_equal(np.squeeze(new_dataset.data), spectra) + +def test_spectra_to_hsi_rng(make_datasets): + """ Import spectra into an hsi -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Hsi() + new_dataset.freq.data = np.arange(hsi.shape[-1]) + new_dataset.data = spectra + new_dataset.freq.op_list_pix = rng + new_dataset.data = spectra + + assert new_dataset.size == spectra.size + assert (new_dataset.data != 0).sum() == len(rng)*spectra.shape[0] + np.testing.assert_almost_equal(np.squeeze(new_dataset.data[..., rng]), spectra[..., rng]) diff --git a/crikit/data/tests/test_mosaic.py b/crikit/data/tests/test_mosaic.py new file mode 100644 index 0000000..639aa44 --- /dev/null +++ b/crikit/data/tests/test_mosaic.py @@ -0,0 +1,469 @@ +import numpy as np +import pytest + +from crikit.data.mosaic import Mosaic + +def test_blank(): + mos = Mosaic() + assert mos.shape is None + assert mos.size is None + assert mos.issamedim is None + assert mos.issamedim is None + assert mos.dtype is None + assert mos.mosaic_shape((2,2)) is None + assert mos.mosaic2d((2,2)) is None + assert mos.mosaicfull((2,2)) is None + +def test_crop_2D(): + """ Test a 2D dataset with cropped rows and columns """ + mos = Mosaic() + mos.parameters['StartR'] = 1 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + + m_obj = 3 + n_obj = 4 + + # MANUALLY SET BASED ON PARAMS ABOVE + m_obj_crop = m_obj - 2 + n_obj_crop = n_obj - 2 + + new_obj = np.ones((m_obj, n_obj)) + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + # NOT AFFECTED BY START* END* + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == np.float + + # AFFECTED BY START* END* + assert mos.unitshape == (m_obj_crop, n_obj_crop) + assert mos.unitshape_orig == (m_obj, n_obj) + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side)).shape == (m_side * m_obj_crop, n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj_crop, n_side * n_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side)).shape == (m_side * m_obj_crop, n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj_crop, n_side * n_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + +def test_crop_3D(): + """ Test a 2D dataset with cropped rows and columns """ + mos = Mosaic() + mos.parameters['StartR'] = 1 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + + m_obj = 3 + n_obj = 4 + p_obj = 5 + + # MANUALLY SET BASED ON PARAMS ABOVE + m_obj_crop = m_obj - 2 + n_obj_crop = n_obj - 2 + p_obj_crop = p_obj + + new_obj = np.ones((m_obj, n_obj, p_obj)) + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + # NOT AFFECTED BY START* END* + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == np.float + + # AFFECTED BY START* END* + assert mos.unitshape == (m_obj_crop, n_obj_crop, p_obj_crop) + assert mos.unitshape_orig == (m_obj, n_obj, p_obj) + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side), idx=0).shape == (m_side * m_obj_crop, n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj_crop, n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side), idx=0).shape == (m_side * m_obj_crop, n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj_crop, n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + +def test_3D_crop_transpose_flips(): + """ Test a 2D dataset with cropped rows and columns """ + mos = Mosaic() + mos.parameters['StartR'] = 1 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + mos.parameters['Transpose'] = True + mos.parameters['FlipVertical'] = True + mos.parameters['FlipHorizontally'] = True + + m_obj = 3 + n_obj = 4 + p_obj = 5 + + # MANUALLY SET BASED ON PARAMS ABOVE + m_obj_crop = m_obj - 2 + n_obj_crop = n_obj - 2 + p_obj_crop = p_obj + + new_obj = np.ones((m_obj, n_obj, p_obj)) + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + # NOT AFFECTED BY START* END* + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == np.float + + # AFFECTED BY START* END* + assert mos.unitshape == (m_obj_crop, n_obj_crop, p_obj_crop) + assert mos.unitshape_orig == (m_obj, n_obj, p_obj) + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side), idx=0).T.shape == (m_side * m_obj_crop, + n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + assert mos.mosaicfull((m_side, n_side)).transpose(1,0,2).shape == (m_side * m_obj_crop, + n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side), idx=0).T.shape == (m_side * m_obj_crop, + n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + assert mos.mosaicfull((m_side, n_side)).transpose(1,0,2).shape == (m_side * m_obj_crop, + n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + +def test_3D_crop_transpose_flips_2(): + """ Test a 2D dataset with cropped rows and columns (asymmetrically) """ + mos = Mosaic() + mos.parameters['StartR'] = 2 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + mos.parameters['Transpose'] = True + mos.parameters['FlipVertical'] = True + mos.parameters['FlipHorizontally'] = True + + m_obj = 5 + n_obj = 6 + p_obj = 7 + + # MANUALLY SET BASED ON PARAMS ABOVE + m_obj_crop = m_obj - 3 + n_obj_crop = n_obj - 2 + p_obj_crop = p_obj + + new_obj = np.ones((m_obj, n_obj, p_obj)) + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + # NOT AFFECTED BY START* END* + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == np.float + + # AFFECTED BY START* END* + assert mos.unitshape == (m_obj_crop, n_obj_crop, p_obj_crop) + assert mos.unitshape_orig == (m_obj, n_obj, p_obj) + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side), idx=0).T.shape == (m_side * m_obj_crop, + n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + assert mos.mosaicfull((m_side, n_side)).transpose(1,0,2).shape == (m_side * m_obj_crop, + n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side), idx=0).T.shape == (m_side * m_obj_crop, + n_side * n_obj_crop) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side))[:-1] + assert mos.mosaicfull((m_side, n_side)).transpose(1,0,2).shape == (m_side * m_obj_crop, + n_side * n_obj_crop, + p_obj_crop) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + +def test_2D_uniform_obj(): + mos = Mosaic() + + m_obj = 3 + n_obj = 4 + + new_obj = np.ones((m_obj, n_obj)) + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == np.float + assert mos.unitshape == (m_obj, n_obj) + assert mos.unitshape_orig == (m_obj, n_obj) + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side)).shape == (m_side * m_obj, n_side * n_obj) + assert mos.mosaic2d((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj, n_side * n_obj) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side)).shape == (m_side * m_obj, n_side * n_obj) + assert mos.mosaic2d((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj, n_side * n_obj) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + +def test_3D_uniform_obj(): + mos = Mosaic() + + m_obj = 3 + n_obj = 4 + p_obj = 2 + + new_obj = np.ones((m_obj, n_obj, p_obj)) + + m_side = 2 + n_side = 2 + + n = m_side * n_side + + for ct in range(n): + mos.append(new_obj) + + assert mos.shape == tuple(n*[new_obj.shape]) + assert mos.size == n + assert mos.issamedim + assert mos.dtype == np.float + with pytest.raises(ValueError): + mos.mosaic2d((m_side, n_side)).shape + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((m_side, n_side), idx=0).shape == (m_side * m_obj, n_side * n_obj) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side), idx=0) + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj, n_side * n_obj, p_obj) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((m_side, n_side), idx=0).shape == (m_side * m_obj, n_side * n_obj) + assert mos.mosaic2d((m_side, n_side), idx=0).shape == mos.mosaic_shape((m_side, n_side), idx=0) + assert mos.mosaicfull((m_side, n_side)).shape == (m_side * m_obj, n_side * n_obj, p_obj) + assert mos.mosaicfull((m_side, n_side)).shape == mos.mosaic_shape((m_side, n_side)) + +def test_err_wrong_dim(): + mos = Mosaic() + + with pytest.raises(TypeError): + mos.append(np.random.randn(5)) + + with pytest.raises(TypeError): + mos.append(np.random.randn(2,2,2,2)) + +def test_err_wrong_dim_append(): + + # Start with 2D + mos = Mosaic() + mos.append(np.random.randn(3,4)) + + with pytest.raises(TypeError): + mos.append(np.random.randn(5)) + + with pytest.raises(TypeError): + mos.append(np.random.randn(3,4,5)) + + # Start with 3D + mos = Mosaic() + mos.append(np.random.randn(3,4,2)) + + with pytest.raises(TypeError): + mos.append(np.random.randn(5)) + + with pytest.raises(TypeError): + mos.append(np.random.randn(3,5)) + +def test_big_to_small_2d(): + orig_data = np.random.randn(40,5) + + mos = Mosaic() + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data.shape[0]//m_unit_size + n_ct = orig_data.shape[1]//n_unit_size + + for ct in range(m_ct): + mos.append(orig_data[ct*m_unit_size:(ct+1)*m_unit_size,:]) + + mos.parameters['Order'] = 'R' + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct)), orig_data) + assert np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + + mos.parameters['Order'] = 'C' + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct)), orig_data) + assert np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + +def test_big_to_small_2d_2(): + orig_data = np.random.randn(40,10) + + mos = Mosaic() + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data.shape[0]//m_unit_size + n_ct = orig_data.shape[1]//n_unit_size + + for ni in range(n_ct): + for mi in range(m_ct): + mos.append(orig_data[mi*m_unit_size:(mi+1)*m_unit_size, + ni*n_unit_size:(ni+1)*n_unit_size]) + + mos.parameters['Order'] = 'R' + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct)), orig_data) + assert np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + + mos.parameters['Order'] = 'C' + assert not np.allclose(mos.mosaic2d(shape=(m_ct, n_ct)), orig_data) + assert not np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + +def test_big_to_small_3d(): + orig_data = np.random.randn(40,5,3) + + mos = Mosaic() + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data.shape[0]//m_unit_size + n_ct = orig_data.shape[1]//n_unit_size + + for ct in range(m_ct): + mos.append(orig_data[ct*m_unit_size:(ct+1)*m_unit_size, ...]) + + mos.parameters['Order'] = 'R' + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=0), orig_data[...,0]) + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=1), orig_data[...,1]) + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=2), orig_data[...,2]) + assert np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + + mos.parameters['Order'] = 'C' + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=0), orig_data[...,0]) + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=1), orig_data[...,1]) + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=2), orig_data[...,2]) + assert np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + +def test_big_to_small_3d_2(): + orig_data = np.random.randn(40,10, 3) + + mos = Mosaic() + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data.shape[0]//m_unit_size + n_ct = orig_data.shape[1]//n_unit_size + + for ni in range(n_ct): + for mi in range(m_ct): + mos.append(orig_data[mi*m_unit_size:(mi+1)*m_unit_size, + ni*n_unit_size:(ni+1)*n_unit_size, :]) + + mos.parameters['Order'] = 'R' + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=0), orig_data[..., 0]) + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=1), orig_data[..., 1]) + assert np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=2), orig_data[..., 2]) + assert np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + + mos.parameters['Order'] = 'C' + assert not np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=0), orig_data[..., 0]) + assert not np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=1), orig_data[..., 1]) + assert not np.allclose(mos.mosaic2d(shape=(m_ct, n_ct), idx=2), orig_data[..., 2]) + assert not np.allclose(mos.mosaicfull(shape=(m_ct, n_ct)), orig_data) + + +def test_big_to_small_3d_output_given(): + orig_data = np.random.randn(40,10, 3) + + mos = Mosaic() + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data.shape[0]//m_unit_size + n_ct = orig_data.shape[1]//n_unit_size + + for ni in range(n_ct): + for mi in range(m_ct): + mos.append(orig_data[mi*m_unit_size:(mi+1)*m_unit_size, + ni*n_unit_size:(ni+1)*n_unit_size, :]) + + output_data = np.zeros(orig_data.shape[:-1], dtype=orig_data.dtype) + id_in = id(output_data) + + mos.parameters['Order'] = 'R' + mos.mosaic2d(shape=(m_ct, n_ct), idx=0, out=output_data) + id_out = id(output_data) + assert np.allclose(output_data, orig_data[..., 0]) + assert id_in == id_out + + output_data = np.zeros(orig_data.shape[:-1], dtype=orig_data.dtype) + mos.mosaic2d(shape=(m_ct, n_ct), idx=1, out=output_data) + assert np.allclose(output_data, orig_data[..., 1]) + + output_data = np.zeros(orig_data.shape[:-1], dtype=orig_data.dtype) + mos.mosaic2d(shape=(m_ct, n_ct), idx=2, out=output_data) + assert np.allclose(output_data, orig_data[..., 2]) + + output_data = np.zeros(orig_data.shape, dtype=orig_data.dtype) + mos.mosaicfull(shape=(m_ct, n_ct), out=output_data) + assert np.allclose(output_data, orig_data) + + mos.parameters['Order'] = 'C' + output_data = np.zeros(orig_data.shape, dtype=orig_data.dtype) + mos.mosaicfull(shape=(m_ct, n_ct), out=output_data) + assert not np.allclose(output_data, orig_data) diff --git a/crikit/data/tests/test_mosaic_hdf.py b/crikit/data/tests/test_mosaic_hdf.py new file mode 100644 index 0000000..3f685f8 --- /dev/null +++ b/crikit/data/tests/test_mosaic_hdf.py @@ -0,0 +1,254 @@ +import os +import time + +import numpy as np +import pytest +import h5py + +import lazy5 + +from crikit.data.mosaic import Mosaic + +@pytest.fixture(scope="module") +def hdf_dataset2(): + """ Setups and tears down a sample HDF5 file """ + filename = 'temp_test.h5' + fid = h5py.File(filename, 'w') + # data_m, data_n, data_p = [3, 4, 24] + data_m, data_n = [3, 4] + data = np.random.randn(data_m, data_n) + + N = 10 + for n in range(N): + fid.create_dataset('img_z{}'.format(n), data=data) + + yield filename, fid + + # Tear-down + if lazy5.utils.hdf_is_open(fid): + fid.close() + + time.sleep(1) + try: + os.remove(filename) + except: + print('Could not delete {}'.format(filename)) + +def test_hdf2(hdf_dataset2): + filename, fid = hdf_dataset2 + + dset_list = lazy5.inspect.get_datasets(fid) + mos = Mosaic() + for n in range(10): + mos.append(fid[dset_list[n]]) + + # assert mos.shape is None + assert mos.size == 10 + assert mos.issamedim + + mos.parameters['Order'] = 'R' + assert mos.mosaic2d((5, 2)).shape == (5*3, 2*4) + + mos.parameters['Order'] = 'C' + assert mos.mosaic2d((5, 2)).shape == (5*3, 2*4) + +def test_big_to_small_3d_output_given(): + orig_data_np = np.random.randn(40, 10, 3) + + filename_in = 'test_h5mosaic_in.h5' + dset_in_prefix = 'dset_' + fid_in = h5py.File(filename_in, 'w') + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data_np.shape[0]//m_unit_size + n_ct = orig_data_np.shape[1]//n_unit_size + + ct = 0 + for ni in range(n_ct): + for mi in range(m_ct): + temp = orig_data_np[mi*m_unit_size:(mi+1)*m_unit_size, + ni*n_unit_size:(ni+1)*n_unit_size, :] + fid_in.create_dataset(dset_in_prefix+'{}'.format(ct), shape=temp.shape, data=temp) + ct += 1 + + fid_in.close() + + fid_in = h5py.File(filename_in, 'r') + mos = Mosaic() + + ct = 0 + for ni in range(n_ct): + for mi in range(m_ct): + mos.append(fid_in[dset_in_prefix+'{}'.format(ct)]) + ct += 1 + + filename_out = 'test_h5mosaic_out.h5' + dset_out_name = 'dset' + + fid_out = h5py.File(filename_out, 'w') + fid_out.create_dataset(dset_out_name, shape=orig_data_np.shape, data=np.zeros(orig_data_np.shape)) + + mos.parameters['Order'] = 'R' + mos.mosaicfull((m_ct, n_ct), out=fid_out[dset_out_name]) + + assert np.allclose(fid_out[dset_out_name], orig_data_np) + + fid_in.close() + fid_out.close() + + time.sleep(1) + try: + os.remove(filename_in) + except: + print('Could not delete {}'.format(filename_in)) + + time.sleep(1) + try: + os.remove(filename_out) + except: + print('Could not delete {}'.format(filename_out)) + +def test_big_to_small_3d_output_given_crop(): + """ 3D big dataset, divied up into small chunks -- WITH CROPPING """ + orig_data_np = np.random.randn(40, 10, 3) + + filename_in = 'test_h5mosaic_in.h5' + dset_in_prefix = 'dset_' + fid_in = h5py.File(filename_in, 'w') + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data_np.shape[0]//m_unit_size + n_ct = orig_data_np.shape[1]//n_unit_size + + ct = 0 + for ni in range(n_ct): + for mi in range(m_ct): + temp = orig_data_np[mi*m_unit_size:(mi+1)*m_unit_size, + ni*n_unit_size:(ni+1)*n_unit_size, :] + fid_in.create_dataset(dset_in_prefix+'{}'.format(ct), shape=temp.shape, data=temp) + ct += 1 + + fid_in.close() + + fid_in = h5py.File(filename_in, 'r') + + mos = Mosaic() + mos.parameters['StartR'] = 1 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + + ct = 0 + for ni in range(n_ct): + for mi in range(m_ct): + mos.append(fid_in[dset_in_prefix+'{}'.format(ct)]) + ct += 1 + + filename_out = 'test_h5mosaic_out.h5' + dset_out_name = 'dset' + + fid_out = h5py.File(filename_out, 'w') + fid_out.create_dataset(dset_out_name, shape=mos.mosaic_shape((m_ct, n_ct)), + dtype=orig_data_np.dtype) + + mos.parameters['Order'] = 'R' + mos.mosaicfull((m_ct, n_ct), out=fid_out[dset_out_name]) + + assert np.allclose(fid_out[dset_out_name][0:3,0:3,:], + orig_data_np[1:4, 1:4, :]) + assert np.allclose(fid_out[dset_out_name][8:11, 0:3, :], + orig_data_np[11:14, 1:4, :]) + + assert np.allclose(fid_out[dset_out_name][0:3, 8:11, :], + orig_data_np[1:4, 11:14, :]) + + fid_in.close() + fid_out.close() + + time.sleep(1) + try: + os.remove(filename_in) + except: + print('Could not delete {}'.format(filename_in)) + + time.sleep(1) + try: + os.remove(filename_out) + except: + print('Could not delete {}'.format(filename_out)) + +def test_big_to_small_3d_output_given_crop_transpose_flips(): + """ + 3D big dataset, divied up into small chunks -- WITH CROPPING, TRANSPOSING + AND FLIPPING H & V + + Note: This test does not assert anything, but rather just ensures the methods + can run without raising errors + """ + orig_data_np = np.random.randn(40, 10, 3) + + filename_in = 'test_h5mosaic_in.h5' + dset_in_prefix = 'dset_' + fid_in = h5py.File(filename_in, 'w') + + m_unit_size = 10 + n_unit_size = 5 + + m_ct = orig_data_np.shape[0]//m_unit_size + n_ct = orig_data_np.shape[1]//n_unit_size + + ct = 0 + for ni in range(n_ct): + for mi in range(m_ct): + temp = orig_data_np[mi*m_unit_size:(mi+1)*m_unit_size, + ni*n_unit_size:(ni+1)*n_unit_size, :] + fid_in.create_dataset(dset_in_prefix+'{}'.format(ct), shape=temp.shape, data=temp) + ct += 1 + + fid_in.close() + + fid_in = h5py.File(filename_in, 'r') + + mos = Mosaic() + mos.parameters['StartR'] = 1 + mos.parameters['EndR'] = -1 + mos.parameters['StartC'] = 1 + mos.parameters['EndC'] = -1 + mos.parameters['Transpose'] = True + mos.parameters['FlipVertical'] = True + mos.parameters['FlipHorizontally'] = True + + ct = 0 + for ni in range(n_ct): + for mi in range(m_ct): + mos.append(fid_in[dset_in_prefix+'{}'.format(ct)]) + ct += 1 + + filename_out = 'test_h5mosaic_out.h5' + dset_out_name = 'dset' + + fid_out = h5py.File(filename_out, 'w') + fid_out.create_dataset(dset_out_name, shape=mos.mosaic_shape((m_ct, n_ct)), + dtype=orig_data_np.dtype) + + mos.parameters['Order'] = 'R' + mos.mosaicfull((m_ct, n_ct), out=fid_out[dset_out_name]) + + fid_in.close() + fid_out.close() + + time.sleep(1) + try: + os.remove(filename_in) + except: + print('Could not delete {}'.format(filename_in)) + + time.sleep(1) + try: + os.remove(filename_out) + except: + print('Could not delete {}'.format(filename_out)) diff --git a/crikit/data/tests/test_spectra.py b/crikit/data/tests/test_spectra.py new file mode 100644 index 0000000..61555d8 --- /dev/null +++ b/crikit/data/tests/test_spectra.py @@ -0,0 +1,121 @@ +import os +import numpy as np +import numpy.testing + +import pytest +import lazy5 + +from crikit.io.hdf5 import hdf_import_data +from crikit.data.spectrum import Spectrum +from crikit.data.spectra import Spectra +from crikit.data.hsi import Hsi + +@pytest.fixture(scope="function") +def make_datasets(): + """ Setups and tears down a series of datasets """ + + data_m, data_n, data_p = [20, 22, 24] + spectrum = np.random.randn(data_p)**2 + 1 + spectra = np.random.randn(data_n, data_p)**2 + 1 + hsi = np.random.randn(data_m, data_n, data_p)**2 + 1 + + return spectrum, spectra, hsi, np.array([data_m, data_n, data_p]) + +def test_mean_axes_static(): + """ Ensure mean_axes_static raises an error""" + + with pytest.raises(NotImplementedError): + Spectra._mean_axes() + +def test_reshape_axes_static(make_datasets): + """ Test reshape axes static method """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + Spectra._reshape_axes(shape=hsi.shape, spectral_axis=-1) == (-1, hsi.shape[-1]) + Spectra._reshape_axes(shape=spectra.shape, spectral_axis=-1) == (-1, spectra.shape[-1]) + Spectra._reshape_axes(shape=spectrum.shape, spectral_axis=-1) == (-1, spectrum.shape[-1]) + +def test_spectra_to_spectra(make_datasets): + """ Import a spectrum into a spectrum """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Spectra() + new_dataset.data = spectra + + assert new_dataset.size == spectra.size + np.testing.assert_array_equal(new_dataset.data, spectra) + +def test_spectra_to_spectra_rng(make_datasets): + """ Import spectra into spectra -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Spectra() + new_dataset.freq.data = np.arange(spectra.shape[-1]) + new_dataset.data = spectra + new_dataset.freq.op_list_pix = rng + new_dataset.data = spectra + + assert new_dataset.size == spectra.size + assert (new_dataset.data != 0).sum() == len(rng)*spectra.shape[0] + np.testing.assert_almost_equal(new_dataset.data[..., rng], spectra[..., rng]) + +def test_spectrum_to_spectra(make_datasets): + """ Import a spectrum into a spectrum """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Spectra() + new_dataset.data = spectrum + + assert new_dataset.size == spectrum.size + np.testing.assert_array_equal(np.squeeze(new_dataset.data), spectrum) + +def test_spectrum_to_spectra_rng(make_datasets): + """ Import spectrum into spectra -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Spectra() + new_dataset.freq.data = np.arange(spectra.shape[-1]) + new_dataset.data = spectrum + new_dataset.freq.op_list_pix = rng + new_dataset.data = spectrum + + assert new_dataset.size == spectrum.size + assert (new_dataset.data != 0).sum() == len(rng) + np.testing.assert_almost_equal(np.squeeze(new_dataset.data[..., rng]), spectrum[rng]) + +def test_hsi_to_spectra(make_datasets): + """ Import an hsi into spectra """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Spectra() + new_dataset.data = hsi + + assert new_dataset.size == hsi.size + np.testing.assert_array_equal(hsi.reshape((-1, hsi.shape[-1])), new_dataset.data) + +def test_hsi_to_spectra_rng(make_datasets): + """ Import an hsi into spectra -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Spectra() + new_dataset.freq.data = np.arange(spectra.shape[-1]) + new_dataset.data = hsi + new_dataset.freq.op_list_pix = rng + new_dataset.data = hsi + + assert new_dataset.size == hsi.size + assert (new_dataset.data != 0).sum() == len(rng)*np.prod(hsi.shape[:-1]) + np.testing.assert_almost_equal(new_dataset.data[..., rng], hsi[..., rng].reshape((-1, len(rng)))) diff --git a/crikit/data/tests/test_spectrum.py b/crikit/data/tests/test_spectrum.py new file mode 100644 index 0000000..7c0a68d --- /dev/null +++ b/crikit/data/tests/test_spectrum.py @@ -0,0 +1,115 @@ +import os +import numpy as np +import numpy.testing + +import pytest +import lazy5 + +from crikit.io.hdf5 import hdf_import_data +from crikit.data.spectrum import Spectrum +from crikit.data.spectra import Spectra +from crikit.data.hsi import Hsi + +@pytest.fixture(scope="function") +def make_datasets(): + """ Setups and tears down a series of datasets """ + + data_m, data_n, data_p = [20, 22, 24] + spectrum = np.random.randn(data_p)**2 + 1 + spectra = np.random.randn(data_n, data_p)**2 + 1 + hsi = np.random.randn(data_m, data_n, data_p)**2 + 1 + + return spectrum, spectra, hsi, np.array([data_m, data_n, data_p]) + +def test_mean_axes_static(make_datasets): + """ Import a spectrum into a spectrum """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + Spectrum._mean_axes(3, 2) == [0,1] + Spectrum._mean_axes(3, -1) == [0,1] + Spectrum._mean_axes(3, 0) == [1,2] + Spectrum._mean_axes(3, 1) == [0,2] + +def test_spectrum_to_spectrum(make_datasets): + """ Import a spectrum into a spectrum """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Spectrum() + new_dataset.data = spectrum + + assert new_dataset.size == spectrum.size + np.testing.assert_almost_equal(new_dataset.data, spectrum) + +def test_spectrum_to_spectrum_rng(make_datasets): + """ Import a spectrum into a spectrum -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Spectrum() + new_dataset.freq.data = np.arange(spectrum.size) + new_dataset.freq.op_list_pix = rng + new_dataset.data = spectrum + + assert new_dataset.size == spectrum.size + assert (new_dataset.data != 0).sum() == len(rng) + np.testing.assert_almost_equal(new_dataset.data[rng], spectrum[rng]) + +def test_spectra_to_spectrum(make_datasets): + """ Import spectra into a spectrum """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Spectrum() + new_dataset.data = spectra + + assert new_dataset.size == spectrum.size + np.testing.assert_almost_equal(new_dataset.data, spectra.mean(axis=0)) + +def test_spectra_to_spectrum_rng(make_datasets): + """ Import spectra into a spectrum -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Spectrum() + new_dataset.freq.data = np.arange(spectrum.size) + new_dataset.freq.op_list_pix = rng + new_dataset.data = spectra + + assert new_dataset.size == spectrum.size + assert (new_dataset.data != 0).sum() == len(rng) + np.testing.assert_almost_equal(new_dataset.data[rng], spectra[:,rng].mean(axis=0)) + +def test_hsi_to_spectrum(make_datasets): + """ Import hsi into a spectrum """ + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + new_dataset = Spectrum() + new_dataset.data = hsi + + assert new_dataset.size == spectrum.size + np.testing.assert_almost_equal(new_dataset.data, hsi.mean(axis=(0,1))) + +def test_hsi_to_spectrum_rng(make_datasets): + """ Import an hsi into a spectrum -- defined range""" + + spectrum, spectra, hsi, make_dataset_shape = make_datasets + + rng = [10,11] + + new_dataset = Spectrum() + new_dataset.freq.data = np.arange(spectrum.size) + new_dataset.freq.op_list_pix = rng + new_dataset.data = hsi + + assert new_dataset.size == spectrum.size + assert (new_dataset.data != 0).sum() == len(rng) + + print('A - B: {}'.format(new_dataset.data[rng] - hsi[..., rng].mean(axis=(0,1)))) + np.testing.assert_almost_equal(new_dataset.data[rng], hsi[..., rng].mean(axis=(0,1))) \ No newline at end of file diff --git a/crikit/io/hdf5.py b/crikit/io/hdf5.py index 0827193..9dd4235 100644 --- a/crikit/io/hdf5.py +++ b/crikit/io/hdf5.py @@ -9,146 +9,15 @@ import os as _os +import numpy as _np + from crikit.data.spectrum import Spectrum as _Spectrum from crikit.data.spectra import Spectra as _Spectra from crikit.data.hsi import Hsi as _Hsi +import lazy5 as _lazy5 -import h5py as _h5py -_h5py.get_config().complex_names = ('Re','Im') - -import numpy as _np - -__all__ = ['hdf_dset_list_rep','hdf_is_valid_dsets', - 'hdf_attr_to_dict','hdf_import_data'] - -def hdf_dset_list_rep(prefix,suffixes): - """ - Create a list of dataset names - """ - dset_list = [] - - assert isinstance(prefix,str) - - for sfx in suffixes: - dset_list.append(prefix + str(sfx)) - - return dset_list - -def hdf_is_valid_dsets(pth, filename, dset_list): - """ - Validate file and datasets exist. Return boolean as to whether valid - - """ - - isvalid = False - fileexists = False - - try: - # Join path and filename in an os-independant way - pfname = _os.path.normpath(_os.path.join(pth, filename)) - f = _h5py.File(pfname, 'r') - print('File exists: \'{}\''.format(pfname)) - fileexists = True - except OSError: - print('File does not exist: \'{}\''.format(pfname)) - fileexists = False - else: - if isinstance(dset_list, list): # List of dataset(s) - try: - for count in dset_list: - f[count] - except: - print('dataset: {} is invalid'.format(count)) - else: - print('All datasets are valid') - isvalid = True - elif isinstance(dset_list, str): # Single dataset string name - try: - f[dset_list] - except: - print('dataset {} is invalid'.format(count)) - else: - print('Dataset is valid') - isvalid = True - else: - print('dset_list is unrecognized type') - finally: - if fileexists: - f.close() - - return isvalid - -def _convert_to_np_dtype(dset): - """ - Given an HDF5 dataset, return the values in a numpy-builtin datatype - - Parameters - ---------- - dset : h5py.Dataset - HDF5 (h5py) dataset - - Returns - ------- - out : numpy.ndarray (dtype = numpy built-in) - - Notes - ----- - The software accounts for big-/little-endianness, and the inability of \ - hdf5 to natively store complex numbers. - - """ - assert isinstance(dset, _h5py.Dataset), 'Input is not of type h5py.Dataset' - # Single datatype - if len(dset.dtype) == 0: - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - if issubclass(converted.dtype.type, _np.integer): # Integer to float - converted = converted.astype(_np.float) - return converted - #Compound datatype of length 2-- assumed ('Re','Im') - elif len(dset.dtype) == 2: - print('Warning: h5py.complex_names set incorrectly using \'{}\' and \'{}\' \ -for Re and Im, respectively'.format(dset.dtype.names[0], dset.dtype.names[1])) - _h5py.get_config().complex_names = (dset.dtype.names[0],dset.dtype.names[1]) - dset = dset.file[dset.name] - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - # Unknown datatype - else: - print('Warning: Unknown datatype. Returning dataset values as is.') - return dset.value - return converted - -def hdf_attr_to_dict(attr): - """ - Convert from HDF attributes to valid dict - """ - - try: - output_dict = dict(attr) - except: - output_dict = {} - for count in attr: - try: - output_dict[count] = attr[count] - except: - print('Fail: {}'.format(count)) - - # String in HDF are treated as numpy bytes_ literals - # We want out instance in memeory to have Python Strings - # This does a simple conversion - # Also will check to see if a string is burried in an array - for k in output_dict: - if isinstance(output_dict[k], _np.bytes_): - output_dict[k] = output_dict[k].decode('UTF-8') - elif isinstance(output_dict[k], _np.ndarray): - if output_dict[k].dtype.kind == 'S': # String array - # This is a cute way of taking an array of charcters and merging - # them into a string. If just a single-element array, - # will also return a string - output_dict[k] = ''.join(output_dict[k].astype(_np.str)) - return output_dict +__all__ = ['hdf_import_data'] def hdf_import_data(pth, filename, dset_list, output_cls_instance=None): """ @@ -178,176 +47,194 @@ def hdf_import_data(pth, filename, dset_list, output_cls_instance=None): """ # Join path and filename in an os-independant way - pfname = _os.path.normpath(_os.path.join(pth, filename)) + pfname = _lazy5.utils.fullpath(filename, pth=pth) - if hdf_is_valid_dsets(pth, filename,dset_list) == False: - print('Invalid filename or dataset list') + if not _lazy5.inspect.valid_file(filename, pth=pth, verbose=True): + return False + elif not _lazy5.inspect.valid_dsets(filename, dset_list, pth=pth, verbose=True): return False else: - try: - f = _h5py.File(pfname,'r') - - if type(output_cls_instance) == _Hsi: - print('Type Hsi') - if isinstance(dset_list, str): - output_cls_instance.data = _convert_to_np_dtype(f[dset_list]) - output_cls_instance.meta = hdf_attr_to_dict(f[dset_list].attrs) - elif isinstance(dset_list, list): - if len(dset_list) > 1: - print('Cannot accept more than 1 HSI image at this time') - else: - for num, dname in enumerate(dset_list): - if num == 0: - output_cls_instance.data = _convert_to_np_dtype(f[dname]) - output_cls_instance.meta = hdf_attr_to_dict(f[dname].attrs) - else: - output_cls_instance.data = _np.vstack((output_cls_instance.data, _convert_to_np_dtype(f[dname]))) - ret = True - elif type(output_cls_instance) == _Spectra: - print('Type Spectra') - if isinstance(dset_list,str): - output_cls_instance.data = _convert_to_np_dtype(f[dset_list]) - output_cls_instance.meta = hdf_attr_to_dict(f[dset_list].attrs) - - elif isinstance(dset_list, list): + fof = _lazy5.utils.FidOrFile(pfname, mode='r') + fid = fof.fid + + if type(output_cls_instance) == _Hsi: + print('Type Hsi') + if isinstance(dset_list, str): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dset_list].dtype.newbyteorder('=') + dset_shp = fid[dset_list].shape + output_cls_instance.data = _np.zeros(dset_shp, dtype=dset_dtype_import) + fid[dset_list].read_direct(output_cls_instance.data) + + # output_cls_instance.data = fid[dset_list].value + output_cls_instance.meta = _lazy5.inspect.get_attrs_dset(fid, dset_list) + elif isinstance(dset_list, list): + if len(dset_list) > 1: + print('Cannot accept more than 1 HSI image at this time') + else: for num, dname in enumerate(dset_list): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dname].dtype.newbyteorder('=') + dset_shp = fid[dname].shape if num == 0: - output_cls_instance.data = _convert_to_np_dtype(f[dname]) - output_cls_instance.meta = hdf_attr_to_dict(f[dname].attrs) + output_cls_instance.data = _np.zeros(dset_shp, + dtype=dset_dtype_import) + fid[dname].read_direct(output_cls_instance.data) + + # output_cls_instance.data = fid[dname].value + output_cls_instance.meta = _lazy5.inspect.get_attrs_dset(fid, dname) else: - output_cls_instance.data = _np.vstack((output_cls_instance.data, _convert_to_np_dtype(f[dname]))) - ret = True - elif type(output_cls_instance) == _Spectrum: - print('Type Spectrum') - if isinstance(dset_list, str): - output_cls_instance.data = _convert_to_np_dtype(f[dset_list]) - output_cls_instance.meta = hdf_attr_to_dict(f[dset_list].attrs) - elif isinstance(dset_list, list): - if len > 1: - print('Will average spectra into a single spectrum') + output_cls_instance.data = _np.vstack((output_cls_instance.data, + fid[dname].value.astype(dset_dtype_import))) + ret = True + elif type(output_cls_instance) == _Spectra: + print('Type Spectra') + if isinstance(dset_list, str): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dset_list].dtype.newbyteorder('=') + if fid[dset_list].ndim == 2: # Compatible dimensions-- use read-direct + dset_shp = fid[dset_list].shape + output_cls_instance.data = _np.zeros(dset_shp, dtype=dset_dtype_import) + fid[dset_list].read_direct(output_cls_instance.data) + else: + output_cls_instance.data = fid[dset_list].value.astype(dset_dtype_import) + + # output_cls_instance.data = fid[dset_list].value + output_cls_instance.meta = _lazy5.inspect.get_attrs_dset(fid, dset_list) + + elif isinstance(dset_list, list): + for num, dname in enumerate(dset_list): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dname].dtype.newbyteorder('=') + if num == 0: + output_cls_instance.data = fid[dname].value.astype(dset_dtype_import) + output_cls_instance.meta = _lazy5.inspect.get_attrs_dset(fid, dname) else: - for num, dname in enumerate(dset_list): - if num == 0: - output_cls_instance.data = _convert_to_np_dtype(f[dname]) - output_cls_instance.meta = hdf_attr_to_dict(f[dname].attrs) - else: - output_cls_instance.data += _convert_to_np_dtype(f[dname]) - output_cls_instance.data /= num+1 - ret = True - elif output_cls_instance is None: - if isinstance(dset_list, str): - data = _convert_to_np_dtype(f[dset_list]) - meta = hdf_attr_to_dict(f[dset_list].attrs) - elif isinstance(dset_list, list): + output_cls_instance.data = _np.vstack((output_cls_instance.data, + fid[dname].value.astype(dset_dtype_import))) + ret = True + elif type(output_cls_instance) == _Spectrum: + print('Type Spectrum') + if isinstance(dset_list, str): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dset_list].dtype.newbyteorder('=') + dset_shp = fid[dset_list].shape + output_cls_instance.data = _np.zeros(dset_shp, dtype=dset_dtype_import) + fid[dset_list].read_direct(output_cls_instance.data) + + # output_cls_instance.data = fid[dset_list].value + output_cls_instance.meta = _lazy5.inspect.get_attrs_dset(fid, dset_list) + elif isinstance(dset_list, list): + if len > 1: + print('Will average spectra into a single spectrum') + else: for num, dname in enumerate(dset_list): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dname].dtype.newbyteorder('=') + dset_shp = fid[dname].shape if num == 0: - data = _convert_to_np_dtype(f[dname]) - meta = hdf_attr_to_dict(f[dname].attrs) + output_cls_instance.data = _np.zeros(dset_shp, + dtype=dset_dtype_import) + fid[dname].read_direct(output_cls_instance.data) + # output_cls_instance.data = fid[dname].value + output_cls_instance.meta = _lazy5.inspect.get_attrs_dset(fid, dname) else: - data = _np.vstack((data, _convert_to_np_dtype(f[dname]))) - ret = [data, meta] - else: - raise TypeError('output_cls must be Spectrum, Spectra, or Hsi') - except: - raise TypeError('Something failed in import_hdf_nist_special') - ret = False - - finally: - f.close() - return ret - -def hdf_export_data(self, output_cls_instance, pth, filename, dsetname): - """ + output_cls_instance.data += fid[dname].value.astype(dset_dtype_import) + output_cls_instance.data /= num+1 + ret = True + elif output_cls_instance is None: + if isinstance(dset_list, str): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dset_list].dtype.newbyteorder('=') + dset_shp = fid[dset_list].shape + data = _np.zeros(dset_shp, dtype=dset_dtype_import) + fid[dset_list].read_direct(data) + + # data = fid[dset_list].value + meta = _lazy5.inspect.get_attrs_dset(fid, dset_list) + elif isinstance(dset_list, list): + for num, dname in enumerate(dset_list): + # Convert to hardware-oriented dtype (endianess) + dset_dtype_import = fid[dname].dtype.newbyteorder('=') + dset_shp = fid[dname].shape + if num == 0: + data = _np.zeros(dset_shp, + dtype=dset_dtype_import) + fid[dname].read_direct(data) + # data = fid[dname].value + meta = _lazy5.inspect.get_attrs_dset(fid, dname) + else: + data = _np.vstack((data, fid[dname].value.astype(dset_dtype_import))) + ret = [data, meta] + else: + raise TypeError('output_cls must be Spectrum, Spectra, or Hsi') - """ - save_grp = dsetname.rpartition('/')[0] - save_dataset_name_no_grp = dsetname.rpartition('/')[-1] - - try: - # Join path and filename in an os-independant way - pfname_out = _os.path.normpath(_os.path.join(pth, filename)) - - f_out = _h5py.File(pfname_out, 'a') - loc = f_out.require_group(save_grp) - dset = loc.create_dataset(save_dataset_name_no_grp, data=output_cls_instance.data) - - for attr_key in output_cls_instance.meta: - try: - attribute = output_cls_instance.meta[attr_key] - if isinstance(attribute, str): - attribute = _np.array(attribute, dtype='S') - dset.attrs.create(attr_key,attribute) - except: - print('Error in attributes') - - # Breadcrumb attributes - bc_attr_dict = self.bcpre.attr_dict - for attr_key in bc_attr_dict: - try: - attribute = bc_attr_dict[attr_key] - if isinstance(attribute, str): - attribute = _np.array(attribute, dtype='S') - dset.attrs.create(attr_key,attribute) - except: - print('Error in attributes') - -# #print('Key: {}, Val: {}'.format(attr_key, bc_attr_dict[attr_key])) -# val = bc_attr_dict[attr_key] -# if isinstance(val, str): -# dset.attrs[attr_key] = val -# else: -# try: -# dset.attrs.create(attr_key,bc_attr_dict[attr_key]) -# except: -# print('Could not create attribute') - - except: - print('Something went wrong while saving') - else: - print('Saved without issues') - finally: - f_out.close() + fid.close() + return ret if __name__ == '__main__': # pragma: no cover - from crikit.io.meta_configs import (special_nist_bcars2 - as _snb) + from crikit.io.meta_configs import (special_nist_bcars2 as _snb) rosetta = _snb() - pth = '../../../' + pth = '../' filename = 'mP2_w_small.h5' - dset = '/Spectra/Dark_3_5ms_2' - tester = hdf_is_valid_dsets(pth, 'fake.h5','fake') - assert tester == False - tester = hdf_is_valid_dsets(pth, filename,'fake_dset') - assert tester == False + dset = '/Spectra/Dark_3_5ms_2' + tester = _lazy5.inspect.valid_dsets(pth=pth, file='fake.h5', dset_list='fake') + assert not tester - tester = hdf_is_valid_dsets(pth, filename,['fake_dset1','fake_dset2']) - assert tester == False + tester = _lazy5.inspect.valid_dsets(pth=pth, file='fake.h5', dset_list='fake_dset') + assert not tester - tester = hdf_is_valid_dsets(pth, filename,dset) - assert tester == True + tester = _lazy5.inspect.valid_dsets(pth=pth, file='fake.h5', + dset_list=['fake_dset1', 'fake_dset2']) + assert not tester - dset_list = hdf_dset_list_rep('/Spectra/Dark_3_5ms_',_np.arange(2)) - tester = hdf_is_valid_dsets(pth, filename,dset_list) - assert tester == True + print('Path: {}'.format(pth)) + tester = _lazy5.inspect.valid_dsets(pth=pth, file=filename, dset_list=dset, verbose=True) + assert tester print('--------------\n\n') spect_dark = _Spectra() - tester = hdf_is_valid_dsets(pth, filename,['/Spectra/Dark_3_5ms_2']) - hdf_import_data(pth, filename,'/Spectra/Dark_3_5ms_2',spect_dark) + tester = _lazy5.inspect.valid_dsets(pth=pth, file=filename, + dset_list=['/Spectra/Dark_3_5ms_2']) + hdf_import_data(pth, filename, '/Spectra/Dark_3_5ms_2', spect_dark) #hdf_process_attr(rosetta, spect_dark) print('Shape of dark spectra: {}'.format(spect_dark.shape)) print('Shape of dark spectra.mean(): {}'.format(spect_dark.mean().shape)) - + print('Dtype of dark spectra: {}'.format(spect_dark._data.dtype)) print('') img = _Hsi() - hdf_import_data(pth, filename,'/BCARSImage/mP2_3_5ms_Pos_2_0/mP2_3_5ms_Pos_2_0_small',img) + hdf_import_data(pth, filename, '/BCARSImage/mP2_3_5ms_Pos_2_0/mP2_3_5ms_Pos_2_0_small', img) print('Shape of img: {}'.format(img.shape)) print('Shape of img.mean(): {}'.format(img.mean().shape)) + print('Dtype of img: {}'.format(img._data.dtype)) + print('Dtype of img.mean(): {}'.format(img.mean().dtype)) + + print('--------------\n\n') + pth = 'C:/Users/chc/Documents/Data/2018/OliverJonas/180629/' + filename = 'L1d1_pos0.h5' + dsetname = '/BCARSImage/L1d1_pos0_0/NRB_Post_0' + spect_nrb = _Spectra() + tester = _lazy5.inspect.valid_dsets(pth=pth, file=filename, + dset_list=[dsetname]) + out = hdf_import_data(pth, filename, dsetname, spect_nrb) + print('HDF_import_data returned: {}'.format(out)) + # hdf_process_attr(rosetta, spect_nrb) + + # print('Shape of dark spectra: {}'.format(spect_dark.shape)) + # print('Shape of dark spectra.mean(): {}'.format(spect_dark.mean().shape)) + # print('Dtype of dark spectra: {}'.format(spect_dark._data.dtype)) + # print('') + # img = _Hsi() + # hdf_import_data(pth, filename, '/BCARSImage/mP2_3_5ms_Pos_2_0/mP2_3_5ms_Pos_2_0_small', img) + # print('Shape of img: {}'.format(img.shape)) + # print('Shape of img.mean(): {}'.format(img.mean().shape)) + # print('Dtype of img: {}'.format(img._data.dtype)) + # print('Dtype of img.mean(): {}'.format(img.mean().dtype)) \ No newline at end of file diff --git a/crikit/io/macros.py b/crikit/io/macros.py index dcab6e9..8c5eb0b 100644 --- a/crikit/io/macros.py +++ b/crikit/io/macros.py @@ -3,9 +3,9 @@ @author: chc """ +import os as _os -import h5py as _h5py -_h5py.get_config().complex_names = ('Re','Im') +import lazy5 from crikit.io.meta_configs import (special_nist_bcars2 as _snb, special_nist_bcars1_sample_scan as _snb1ss) @@ -13,7 +13,7 @@ from crikit.io.hdf5 import hdf_import_data as _hdf_import_data from crikit.io.csv_nist import csv_nist_import_data as _csv_nist_import_data -__all__ = [] +__all__ = ['import_hdf_nist_special', 'import_csv_nist_special1'] def import_hdf_nist_special(pth, filename, dset, output_cls_instance): @@ -27,17 +27,35 @@ def import_hdf_nist_special(pth, filename, dset, output_cls_instance): """ print('\n') + import_success = _hdf_import_data(pth, filename, dset, output_cls_instance) + if import_success is False: + raise ValueError('hdf_import_data failed') + return False + _meta_process(_snb(), output_cls_instance) + return True + +def import_hdf_nist_special_ooc(pth, filename, dset, output_cls_instance): + """ + Import data from HDF File (OUT-OF-CORE) as specified by NIST-specific settings + + Returns + ------- + Success : bool + Whether import was successful + """ + + print('\n') + try: - import_success = _hdf_import_data(pth, filename, dset, output_cls_instance) - if import_success is None or import_success is False: - raise ValueError('hdf_import_data returned None') + fid = lazy5.utils.FidOrFile(lazy5.utils.fullpath(filename, pth=pth)).fid + output_cls_instance._data = fid[dset] + output_cls_instance.meta = lazy5.inspect.get_attrs_dset(fid, dset) _meta_process(_snb(), output_cls_instance) except: - print('Something failed in import_hdf_nist_special') + raise ValueError('hdf_import_data failed') return False else: - print('\n') - return True + return fid def import_csv_nist_special1(pth, filename_header, filename_data, output_cls_instance): @@ -66,7 +84,7 @@ def import_csv_nist_special1(pth, filename_header, filename_data, from crikit.data.hsi import Hsi as _Hsi - pth = _os.path.abspath('../../../') + '/' + pth = '../' filename = 'mP2_w_small.h5' img = _Hsi() import_hdf_nist_special(pth, filename,'/BCARSImage/mP2_3_5ms_Pos_2_0/mP2_3_5ms_Pos_2_0_small',img) @@ -74,13 +92,13 @@ def import_csv_nist_special1(pth, filename_header, filename_data, print('Shape of img.mean(): {}'.format(img.mean().shape)) print(img.y_rep.data) - from crikit.data.spectrum import Spectrum as _Spectrum + # from crikit.data.spectrum import Spectrum as _Spectrum - sp = _Spectrum() - pth = '../../../Young_150617/' - filename_header = 'SH-03.h' - filename_data = 'base061715_152213_60ms.txt' + # sp = _Spectrum() + # pth = '../../../Young_150617/' + # filename_header = 'SH-03.h' + # filename_data = 'base061715_152213_60ms.txt' - import_csv_nist_special1(pth, filename_header, filename_data, - output_cls_instance=sp) + # import_csv_nist_special1(pth, filename_header, filename_data, + # output_cls_instance=sp) \ No newline at end of file diff --git a/crikit/io/meta_configs.py b/crikit/io/meta_configs.py index ea45397..bcb9e85 100644 --- a/crikit/io/meta_configs.py +++ b/crikit/io/meta_configs.py @@ -16,7 +16,7 @@ def special_nist_bcars2(): rosetta = {} rosetta['XPixelSize'] = ['RasterScanParams.FastAxisStepSize', - 'Raster.Fast.StepSize'] + 'Raster.Fast.StepSize','!',1] rosetta['XStart'] = ['RasterScanParams.FastAxisStart', 'Raster.Fast.Start'] rosetta['XStop'] = ['RasterScanParams.FastAxisStop', 'Raster.Fast.Stop'] rosetta['XLength'] = ['RasterScanParams.FastAxisSteps', 'Raster.Fast.Steps'] @@ -24,7 +24,7 @@ def special_nist_bcars2(): rosetta['XUnits'] = ['RasterScanParams.FastAxisUnits','!','$\\mu$m'] rosetta['YPixelSize'] = ['RasterScanParams.SlowAxisStepSize', - 'Raster.Slow.StepSize'] + 'Raster.Slow.StepSize','!',1] rosetta['YStart'] = ['RasterScanParams.SlowAxisStart', 'Raster.Slow.Start'] rosetta['YStop'] = ['RasterScanParams.SlowAxisStop', 'Raster.Slow.Stop'] rosetta['YLength'] = ['RasterScanParams.SlowAxisSteps', 'Raster.Slow.Steps'] diff --git a/crikit/io/meta_process.py b/crikit/io/meta_process.py index abff806..f6b8d2f 100644 --- a/crikit/io/meta_process.py +++ b/crikit/io/meta_process.py @@ -34,7 +34,6 @@ def rosetta_query(key, rosetta, output_cls_instance): temp_key = count temp_val = output_cls_instance._meta[temp_key] break -# print('{}:{}'.format(count, temp_val)) else: pass except: @@ -63,29 +62,26 @@ def meta_process(rosetta, output_cls_instance): """ # Frequency-calibration - try: - calib_dict = {} - - calib_dict['a_vec'] = rosetta_query('ColorPolyVals',rosetta, output_cls_instance)[0] - calib_dict['n_pix'] = rosetta_query('ColorChannels',rosetta, output_cls_instance)[0] - calib_dict['ctr_wl'] = rosetta_query('ColorCenterWL',rosetta, output_cls_instance)[0] - calib_dict['ctr_wl0'] = rosetta_query('ColorCalibWL',rosetta, output_cls_instance)[0] - calib_dict['probe'] = rosetta_query('ColorProbe',rosetta, output_cls_instance)[0] - calib_dict['units'] = rosetta_query('ColorUnits',rosetta, output_cls_instance)[0] + calib_dict = {} - output_cls_instance.freq.calib = calib_dict + calib_dict['a_vec'] = rosetta_query('ColorPolyVals',rosetta, output_cls_instance)[0] + calib_dict['n_pix'] = rosetta_query('ColorChannels',rosetta, output_cls_instance)[0] + calib_dict['ctr_wl'] = rosetta_query('ColorCenterWL',rosetta, output_cls_instance)[0] + calib_dict['ctr_wl0'] = rosetta_query('ColorCalibWL',rosetta, output_cls_instance)[0] + calib_dict['probe'] = rosetta_query('ColorProbe',rosetta, output_cls_instance)[0] + calib_dict['units'] = rosetta_query('ColorUnits',rosetta, output_cls_instance)[0] - use_wn = rosetta_query('ColorWnMode',rosetta, output_cls_instance)[0] - print('Use wavenumber: {}'.format(use_wn)) - if use_wn: # Use wavenumber? - output_cls_instance.freq.calib_fcn = _calib_pix_wn - else: # Use wavelength - output_cls_instance.freq.calib_fcn = _calib_pix_wl + output_cls_instance.freq.calib = calib_dict - output_cls_instance.freq.update() - except: - print('Something failed in meta_process: freq-calib') + use_wn = rosetta_query('ColorWnMode',rosetta, output_cls_instance)[0] + print('Use wavenumber: {}'.format(use_wn)) + if use_wn: # Use wavenumber? + output_cls_instance.freq.calib_fcn = _calib_pix_wn + else: # Use wavelength + output_cls_instance.freq.calib_fcn = _calib_pix_wl + output_cls_instance.freq.update() + # See if an original calibration is found try: calib_orig_dict = {} @@ -118,11 +114,29 @@ def meta_process(rosetta, output_cls_instance): if type(output_cls_instance) == _Hsi: print('Type Hsi') try: - start = rosetta_query('XStart',rosetta, output_cls_instance)[0] - stop = rosetta_query('XStop',rosetta, output_cls_instance)[0] - steps = rosetta_query('XLength',rosetta, output_cls_instance)[0] - units = rosetta_query('XUnits',rosetta, output_cls_instance)[0] - label = rosetta_query('XLabel',rosetta, output_cls_instance)[0] + units = rosetta_query('XUnits',rosetta, output_cls_instance) + label = rosetta_query('XLabel',rosetta, output_cls_instance) + if units is not None: + units = units[0] + if label is not None: + label = label[0] + + start = rosetta_query('XStart',rosetta, output_cls_instance) + stop = rosetta_query('XStop',rosetta, output_cls_instance) + steps = rosetta_query('XLength',rosetta, output_cls_instance) + if (start is not None) & (stop is not None) & (steps is not None): + start = start[0] + stop = stop[0] + steps = steps[0] + else: + temp = output_cls_instance.shape + start = 0 + stop = temp[1] - 1 + steps = temp[1] + units = 'pix' + label = 'X' + + # HDF files store strings in np.bytes format if isinstance(units, bytes): @@ -137,11 +151,27 @@ def meta_process(rosetta, output_cls_instance): del start, stop, steps, units, label - start = rosetta_query('YStart',rosetta, output_cls_instance)[0] - stop = rosetta_query('YStop',rosetta, output_cls_instance)[0] - steps = rosetta_query('YLength',rosetta, output_cls_instance)[0] - units = rosetta_query('YUnits',rosetta, output_cls_instance)[0] - label = rosetta_query('YLabel',rosetta, output_cls_instance)[0] + units = rosetta_query('YUnits',rosetta, output_cls_instance) + label = rosetta_query('YLabel',rosetta, output_cls_instance) + if units is not None: + units = units[0] + if label is not None: + label = label[0] + + start = rosetta_query('YStart',rosetta, output_cls_instance) + stop = rosetta_query('YStop',rosetta, output_cls_instance) + steps = rosetta_query('YLength',rosetta, output_cls_instance) + if (start is not None) & (stop is not None) & (steps is not None): + start = start[0] + stop = stop[0] + steps = steps[0] + else: + temp = output_cls_instance.shape + start = 0 + stop = temp[0] - 1 + steps = temp[0] + units = 'pix' + label = 'Y' # HDF files store strings in np.bytes format if isinstance(units, bytes): diff --git a/crikit/io/tests/test_hdf5.py b/crikit/io/tests/test_hdf5.py new file mode 100644 index 0000000..7e2747e --- /dev/null +++ b/crikit/io/tests/test_hdf5.py @@ -0,0 +1,188 @@ +import os +import numpy as np +import numpy.testing + +import pytest +import h5py +import lazy5 + +from crikit.io.hdf5 import hdf_import_data +from crikit.data.spectrum import Spectrum +from crikit.data.spectra import Spectra +from crikit.data.hsi import Hsi + +@pytest.fixture(scope="module") +def hdf_dataset(): + """ Setups and tears down a sample HDF5 file """ + filename = 'temp_test.h5' + fid = h5py.File(filename, 'w') + + data_m, data_n, data_p = [20, 22, 24] + spectrum = np.random.randn(data_p) + spectra = np.random.randn(data_n, data_p) + hsi = np.random.randn(data_m, data_n, data_p) + + fid.create_dataset('hsi', data=hsi) + fid.create_dataset('spectra', data=spectra) + fid.create_dataset('spectrum', data=spectrum) + + yield filename, fid, (data_m, data_n, data_p) + + # Tear-down + if lazy5.utils.hdf_is_open(fid): + fid.close() + os.remove(filename) + +def test_hdf_import_spectrum_to_spectrum(hdf_dataset): + """ Import a spectrum into a spectrum """ + + filename, fid, hdf_data_shape = hdf_dataset + hdf_data_shape = np.array(hdf_data_shape) + + dname = 'spectrum' + dataset = Spectrum() + + out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) + assert out is True + assert dataset.size == hdf_data_shape[-1] + np.testing.assert_array_equal(dataset.data, fid[dname].value) + +def test_hdf_import_spectra_to_spectra(hdf_dataset): + """ Import a spectra into a spectra """ + + filename, fid, hdf_data_shape = hdf_dataset + hdf_data_shape = np.array(hdf_data_shape) + + dname = 'spectra' + dataset = Spectra() + + out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) + assert out is True + assert dataset.size == hdf_data_shape[1:].prod() + np.testing.assert_array_equal(dataset.data, fid[dname].value) + +def test_hdf_import_hsi_to_hsi(hdf_dataset): + """ Import an hsi into an hsi """ + + filename, fid, hdf_data_shape = hdf_dataset + hdf_data_shape = np.array(hdf_data_shape) + + dname = 'hsi' + dataset = Hsi() + + out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) + assert out is True + assert dataset.size == hdf_data_shape.prod() + np.testing.assert_array_equal(dataset.data, fid[dname].value) +def test_hdf_import_no_output_cls_given(hdf_dataset): + """ Import a spectrum, spectra, and hsi when no instantiated class is provided """ + + filename, fid, hdf_data_shape = hdf_dataset + hdf_data_shape = np.array(hdf_data_shape) + + # Spectrum + dname = 'spectrum' + dataset, dset_meta = hdf_import_data('.', filename, dname, output_cls_instance=None) + assert dataset.size == hdf_data_shape[-1] + np.testing.assert_array_equal(dataset, fid[dname].value) + + # Spectra + dname = 'spectra' + dataset, dset_meta = hdf_import_data('.', filename, dname, output_cls_instance=None) + assert dataset.size == hdf_data_shape[1:].prod() + np.testing.assert_array_equal(dataset, fid[dname].value) + + # HSI + dname = 'hsi' + dataset, dset_meta = hdf_import_data('.', filename, dname, output_cls_instance=None) + assert dataset.size == hdf_data_shape.prod() + np.testing.assert_array_equal(dataset, fid[dname].value) + +# def test_hdf_import_spectra_to_spectrum(hdf_dataset): +# """ Import spectra into a spectrum """ + +# filename, fid, hdf_data_shape = hdf_dataset +# hdf_data_shape = np.array(hdf_data_shape) + +# dname = 'spectra' +# dataset = Spectrum() + +# out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) +# assert out is True +# assert dataset.size == hdf_data_shape[-1] +# np.testing.assert_equal(dataset.data, fid[dname].value.mean(axis=0)) + +# def test_hdf_import_hsi_to_spectrum(hdf_dataset): +# """ Import hsi into a spectrum """ + +# filename, fid, hdf_data_shape = hdf_dataset +# hdf_data_shape = np.array(hdf_data_shape) + +# dname = 'hsi' +# dataset = Spectrum() + +# out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) +# assert out is True +# assert dataset.size == hdf_data_shape[-1] +# np.testing.assert_equal(dataset.data, fid[dname].value.mean(axis=(0,1))) + + +# def test_hdf_import_spectrum_to_spectra(hdf_dataset): +# """ Import a spectrum into a spectra """ + +# filename, fid, hdf_data_shape = hdf_dataset +# hdf_data_shape = np.array(hdf_data_shape) + +# dname = 'spectrum' +# dataset = Spectra() + +# out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) +# assert out is True +# assert dataset.size == hdf_data_shape[-1] +# assert dataset.ndim == 2 +# np.testing.assert_equal(dataset.data, fid[dname].value) + +# def test_hdf_import_hsi_to_spectra(hdf_dataset): +# """ Import hsi into spectra """ + +# filename, fid, hdf_data_shape = hdf_dataset +# hdf_data_shape = np.array(hdf_data_shape) + +# dname = 'hsi' +# dataset = Spectra() + +# out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) +# assert out is True +# assert dataset.size == hdf_data_shape.prod() +# assert dataset.ndim == 2 +# np.testing.assert_equal(dataset.data, fid[dname].value.reshape((-1, hdf_data_shape[-1]))) + +# def test_hdf_import_spectrum_to_hsi(hdf_dataset): +# """ Import a spectrum into an hsi """ + +# filename, fid, hdf_data_shape = hdf_dataset +# hdf_data_shape = np.array(hdf_data_shape) + +# dname = 'spectrum' +# dataset = Hsi() + +# out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) +# assert out is True +# assert dataset.size == hdf_data_shape[-1] +# assert dataset.ndim == 3 +# np.testing.assert_equal(dataset.data, fid[dname].value) + +# def test_hdf_import_spectra_to_hsi(hdf_dataset): +# """ Import spectra into an hsi """ + +# filename, fid, hdf_data_shape = hdf_dataset +# hdf_data_shape = np.array(hdf_data_shape) + +# dname = 'spectra' +# dataset = Hsi() + +# out = hdf_import_data('.', filename, dname, output_cls_instance=dataset) +# assert out is True +# assert dataset.size == hdf_data_shape[1:].prod() +# assert dataset.ndim == 3 +# np.testing.assert_equal(dataset.data, fid[dname].value.reshape((0, -1, hdf_data_shape[-1]))) \ No newline at end of file diff --git a/crikit/preprocess/algorithms/als.py b/crikit/preprocess/algorithms/als.py index 7036c3b..e9ba112 100644 --- a/crikit/preprocess/algorithms/als.py +++ b/crikit/preprocess/algorithms/als.py @@ -17,15 +17,17 @@ class AlsCvxopt(AbstractBaseline): def __init__(self, smoothness_param=1e3, asym_param=1e-4, redux=1, order=2, rng=None, fix_end_points=False, fix_rng=None, - fix_const=1, max_iter=100, min_diff=1e-5, verbose=False): + fix_const=1, max_iter=100, min_diff=1e-5, verbose=False, + **kwargs): """ Parameters ---------- smoothness_param : float, optional (default, 1e3) Smoothness parameter - asym_param : float, optional (default, 1e-4) - Assymetry parameter + asym_param : float, ndarray, optional (default, 1e-4) + Assymetry parameter. Note: if vector, length of signal/frequency + vector (i.e., not relative to rng) redux : int, optional (default, 1) Reduction parameter to sub-sample input signal @@ -43,7 +45,7 @@ def __init__(self, smoothness_param=1e3, asym_param=1e-4, redux=1, fix_rng : ndarray (1D), optional (default, None) Pixels to weight so that the baseline strongly approaches the data - at these pixels. + at these pixels. Note: pixel number relative to rng max_iter : int, optional (default, 100) Maximum number of least-squares iterations to perform @@ -54,6 +56,13 @@ def __init__(self, smoothness_param=1e3, asym_param=1e-4, redux=1, verbose : bool, optional (default, False) Display progress of detrending + Notes + ----- + Vector spaces: + + - asym_param, x + - fix_rng, x[rng] + """ self.smoothness_param=smoothness_param @@ -168,7 +177,11 @@ def _calc(self, signal): penalty_vector[-1] = 1 if self.fix_rng is not None: - penalty_vector[self.fix_rng] = self.fix_const + # ! Dirty fix to the problem of @property fix_rng being + # ! equal to the size of penalty_vector + fix_rng = 1*self.fix_rng + fix_rng = fix_rng[fix_rng < penalty_vector.size] + penalty_vector[fix_rng] = self.fix_const baseline_output[coords] = baseline_current @@ -180,53 +193,14 @@ def _calc(self, signal): return baseline_output if __name__ == '__main__': # pragma: no cover - import matplotlib.pyplot as _plt - - x = _np.linspace(0,1000,800) - data = _np.exp(-(x-500)**2/300**2) + _np.abs(5/(300 - x -1j*10) + .005) - - N = 1 - D = 2 - - if D == 3: - data = _np.dot((_np.random.rand(N,N)*_np.ones((N,N)))[...,None], data[None,:]) - else: - data = _np.dot((_np.random.rand(N)*_np.ones((N)))[...,None], data[None,:]) - -# print('Data.shape: {}\n'.format(data.shape)) - -# asym_param = _np.logspace(-4, -7, x.size) - - _plt.plot(x,data.T) - - sp_vec = _np.logspace(0,6,7) - for num, sp in enumerate(sp_vec): -# for ap in _np.logspace(-6,0,10): - ap = sp/1e6 - als = AlsCvxopt(smoothness_param=sp, asym_param=ap, redux=1, - max_iter=1000, - verbose=False) + x = _np.linspace(-100, 100, 1000) + y = 10*_np.exp(-(x**2/(2*20**2))) - baseline = als.calculate(data) - - scaled_num = (num)/(sp_vec.size) - color = _plt.cm.jet(scaled_num) - - _plt.plot(x, baseline.T, c=color, label='{:.1e}'.format(sp)) - _plt.legend() - _plt.show() -# print('Internal Timer: {:.4f} sec ({:.4f} per)'.format(als.t, -# als.t_per_iter)) - -# als = AlsCvxopt(smoothness_param=1, asym_param=1e-3, redux=10, -# max_iter=1000, -# verbose=False) -# -# baseline = als.calculate(data) -# print('Internal Timer: {:.4f} sec ({:.4f} per)'.format(als.t, -# als.t_per_iter)) -# -# if (D <= 2) & (N<21): -# _plt.plot(data.T,'k') -# _plt.plot(baseline.T,'r') -# _plt.show() + rng = _np.arange(200,800) + asym_vec = 0*x + 1e-7 + fix_rng = _np.arange(600) + + als = AlsCvxopt(smoothness_param=1, asym_param=asym_vec, rng=rng, + redux=10, fix_end_points=False, fix_rng=fix_rng, + verbose=True) + y_als = als.calculate(y) diff --git a/crikit/preprocess/subtract_dark.py b/crikit/preprocess/subtract_dark.py index 0324f0a..6db990c 100644 --- a/crikit/preprocess/subtract_dark.py +++ b/crikit/preprocess/subtract_dark.py @@ -1,9 +1,7 @@ """ Subtract mean value (optionally, over a range from all spectrum/spectra/hsi) -Created on Thu May 26 14:31:39 2016 - -@author: chc +Note: If dark > 1D, averaged -- even if data has same shape. """ import numpy as _np @@ -36,6 +34,12 @@ def transform(self, data): Returns the success state (True=success) """ + + if not _np.can_cast(self.dark.dtype, data.dtype): + err_str1 = 'Cannot transform input data type {}'.format(data.dtype) + err_str2 = ' with dark type {}'.format(self.dark.dtype) + raise TypeError(err_str1 + err_str2) + success = self._calc(data, ret_obj=data) return success @@ -69,12 +73,9 @@ def _calc(self, data, ret_obj): # Expand dark dimensionality to match data.ndim self.dark = _expand_1d_to_ndim(self.dark, data.ndim) - try: - ret_obj -= self.dark - except: - return False - else: - return True + ret_obj -= self.dark + return True + if __name__ == '__main__': # pragma: no cover diff --git a/crikit/preprocess/tests/test_als.py b/crikit/preprocess/tests/test_als.py index 6e27f05..5dfbfe9 100644 --- a/crikit/preprocess/tests/test_als.py +++ b/crikit/preprocess/tests/test_als.py @@ -165,18 +165,43 @@ def test_rng_redux_fix_rng(): x = np.linspace(-100, 100, 1000) y = 10*np.exp(-(x**2/(2*20**2))) - als = AlsCvxopt(smoothness_param=1, asym_param=1e-7, + rng = np.arange(200,800) + + als = AlsCvxopt(smoothness_param=1, asym_param=1e-7, rng=rng, redux=10, fix_end_points=False, fix_rng=None, verbose=True) y_als = als.calculate(y) assert np.max(y[250:750] - y_als[250:750]) > 9 - fix_rng = np.arange(200,800) - - als = AlsCvxopt(smoothness_param=1, asym_param=1e-7, + fix_rng = np.arange(600) + # fix_rng = np.hstack((np.arange(100), np.arange(500,600))) + + als = AlsCvxopt(smoothness_param=1, asym_param=1e-7, rng=rng, redux=10, fix_end_points=False, fix_rng=fix_rng, verbose=True) y_als = als.calculate(y) assert np.max(y[250:750] - y_als[250:750]) < 0.004 - + +def test_rng_redux_fix_rng_vecasym(): + x = np.linspace(-100, 100, 1000) + y = 10*np.exp(-(x**2/(2*20**2))) + + rng = np.arange(200,800) + + asym_vec = 0*x + 1e-7 + als = AlsCvxopt(smoothness_param=1, asym_param=asym_vec, rng=rng, + redux=10, fix_end_points=False, fix_rng=None, + verbose=True) + y_als = als.calculate(y) + + assert np.max(y[250:750] - y_als[250:750]) > 9 + + fix_rng = np.arange(600) + # fix_rng = np.hstack((np.arange(100), np.arange(500,600))) + + als = AlsCvxopt(smoothness_param=1, asym_param=1e-7, rng=rng, + redux=10, fix_end_points=False, fix_rng=fix_rng, + verbose=True) + y_als = als.calculate(y) + assert np.max(y[250:750] - y_als[250:750]) < 0.004 \ No newline at end of file diff --git a/crikit/preprocess/tests/test_subtract_dark.py b/crikit/preprocess/tests/test_subtract_dark.py new file mode 100644 index 0000000..a560d74 --- /dev/null +++ b/crikit/preprocess/tests/test_subtract_dark.py @@ -0,0 +1,327 @@ +import os +import numpy as np +import numpy.testing + +import pytest + +from crikit.preprocess.subtract_dark import SubtractDark + +@pytest.fixture(scope="function") +def make_datasets(): + """ Setups and tears down a series of datasets """ + + data_m, data_n, data_p = [20, 22, 24] + spectrum = np.random.randn(data_p)**2 + 1 + spectra = np.random.randn(data_n, data_p)**2 + 1 + hsi = np.random.randn(data_m, data_n, data_p)**2 + 1 + + return spectrum, spectra, hsi, np.array([data_m, data_n, data_p]) + +def test_sub_spectrum_from_spectrum(make_datasets): + """ Dark is spectrum. Data is spectrum. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*spectrum + dark = 1*spectrum + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + np.testing.assert_array_almost_equal(out, 0.0) + np.testing.assert_array_almost_equal(out, data - dark) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_spectra_from_spectrum(make_datasets): + """ Dark is spectra. Data is spectrum. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*spectrum + dark = 1*spectra + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=0)) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_hsi_from_spectrum(make_datasets): + """ Dark is HSI. Data is spectrum. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*spectrum + dark = 1*hsi + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=(0,1))) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_spectrum_from_spectra(make_datasets): + """ Dark is spectrum. Data is spectra. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*spectra + dark = 1*spectrum + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + np.testing.assert_array_almost_equal(out, data - dark[None,:]) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_spectra_from_spectra(make_datasets): + """ Dark is spectra. Data is spectra. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*spectra + dark = 1*spectra + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + + # * Even though the data and dark have same dimensions, the dark is averaged + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=0)[None,:]) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_hsi_from_spectra(make_datasets): + """ Dark is HSI. Data is spectrum. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*spectra + dark = 1*hsi + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=(0,1))[None,:]) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_spectrum_from_hsi(make_datasets): + """ Dark is spectrum. Data is HSI. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*hsi + dark = 1*spectrum + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + np.testing.assert_array_almost_equal(out, data - dark[None,None,:]) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_spectra_from_hsi(make_datasets): + """ Dark is spectra. Data is HSI. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*hsi + dark = 1*spectra + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=0)[None,None,:]) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_hsi_from_hsi(make_datasets): + """ Dark is HSI. Data is HSI. """ + + spectrum, spectra, hsi, shape = make_datasets + data = 1*hsi + dark = 1*hsi + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + + # * Even though the data and dark have same dimensions, the dark is averaged + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=(0,1))[None,None,:]) + + # Transform + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_sub_hsi_int_from_hsi_float(make_datasets): + """ Dark is HSI. Data is HSI. """ + + spectrum, spectra, hsi, shape = make_datasets + data = (1*hsi).astype(np.float) + dark = (1*hsi).astype(np.int) + + subdark = SubtractDark(dark) + + # Calculate + meaner = data.mean() + out = subdark.calculate(data) + assert meaner == data.mean() + assert out.mean() != data.mean() + assert out.size == data.size + + # * Even though the data and dark have same dimensions, the dark is averaged + np.testing.assert_array_almost_equal(out, data - dark.mean(axis=(0,1))[None,None,:]) + + # Transform + dark = (1*hsi).astype(np.int) + subdark = SubtractDark(dark) + success = subdark.transform(data) + np.testing.assert_array_almost_equal(data, out) + assert meaner != data.mean() + assert success is True + +def test_transform_incompatible_dtypes(make_datasets): + """ + Test that TypeError is raised when Dark and Data have incompatible + dtypes for in-place transformation + + Note: if spectra or hsi is used for dark, will convert to float due to mean + """ + + spectrum, spectra, hsi, shape = make_datasets + + # DOES NOT RAISE ERROR + data = (1*hsi).astype(np.int) + dark = (1*spectrum).astype(np.int) + subdark = SubtractDark(dark) + subdark.transform(data) + + # DOES NOT RAISE ERROR + data = (1*hsi).astype(np.float) + dark = (1*spectrum).astype(np.int) + subdark = SubtractDark(dark) + subdark.transform(data) + + # DOES NOT RAISE ERROR + data = (1*hsi).astype(np.complex) + dark = (1*spectrum).astype(np.int) + subdark = SubtractDark(dark) + subdark.transform(data) + + # DOES RAISE ERROR + data = (1*hsi).astype(np.int) + dark = (1*spectrum).astype(np.float) + subdark = SubtractDark(dark) + with pytest.raises(TypeError): + subdark.transform(data) + + # DOES NOT RAISE ERROR + data = (1*hsi).astype(np.float) + dark = (1*spectrum).astype(np.float) + subdark = SubtractDark(dark) + subdark.transform(data) + + # DOES NOT RAISE ERROR + data = (1*hsi).astype(np.complex) + dark = (1*spectrum).astype(np.float) + subdark = SubtractDark(dark) + subdark.transform(data) + + # DOES RAISE ERROR + data = (1*hsi).astype(np.int) + dark = (1*spectrum).astype(np.complex) + subdark = SubtractDark(dark) + with pytest.raises(TypeError): + subdark.transform(data) + + # DOES RAISE ERROR + data = (1*hsi).astype(np.float) + dark = (1*spectrum).astype(np.complex) + subdark = SubtractDark(dark) + with pytest.raises(TypeError): + subdark.transform(data) + + # DOES NOT RAISE ERROR + data = (1*hsi).astype(np.complex) + dark = (1*spectrum).astype(np.complex) + subdark = SubtractDark(dark) + subdark.transform(data) + + \ No newline at end of file diff --git a/crikit/ui/deprecated/dialog_SVD.py b/crikit/ui/deprecated/dialog_SVD.py deleted file mode 100644 index 29abec6..0000000 --- a/crikit/ui/deprecated/dialog_SVD.py +++ /dev/null @@ -1,363 +0,0 @@ -""" -SVD Dialog - -References ------------ -[1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - -""" - -import sys as _sys -import numpy as _np - -from PyQt5 import QtWidgets as _QtWidgets -from PyQt5.QtWidgets import (QApplication as _QApplication, - QDialog as _QDialog) -import PyQt5.QtCore as _QtCore - -from scipy.linalg import (svd as _svd, diagsvd as _diagsvd) - -# Import from Designer-based GUI -from crikit.ui.qt_Factorization import Ui_Dialog ### EDIT ### - -# Generic imports for MPL-incorporation -import matplotlib as _mpl - -from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas - -_mpl.use('Qt5Agg') -_mpl.rcParams['font.family'] = 'sans-serif' -_mpl.rcParams['font.size'] = 12 - -class DialogSVD(_QDialog): - """ - SubUiSVD : SVD SubUI - """ - - def __init__(self, data=None, parent = None): - - # Generic load/init designer-based GUI - super(DialogSVD, self).__init__(parent) ### EDIT ### - - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.pushButtonNext.clicked.connect(self.advance) - self.ui.pushButtonPrev.clicked.connect(self.advance) - self.ui.pushButtonGoTo.clicked.connect(self.advance) - self.ui.pushButtonCancel.clicked.connect(self.reject) - self.ui.pushButtonOk.clicked.connect(self.accept) - self.ui.pushButtonClear.clicked.connect(self.clear) - self.ui.pushButtonApply.clicked.connect(self.applyCheckBoxes) - self.ui.pushButtonScript.clicked.connect(self.runScript) - - self.firstSV = 0 - self.spanSV = 6 - - self.Mlen = 0 - self.Nlen = 0 - self.Olen = 0 - - self.data = _np.zeros([self.Mlen, self.Nlen, self.Olen]) - - self.selected_svs = set() - self.ui.lcdSelectedFactors.display(len(self.selected_svs)) - - self.svWins = [] - self.svLabelCheckBoxes = [self.ui.checkBox, - self.ui.checkBox_2, - self.ui.checkBox_3, - self.ui.checkBox_4, - self.ui.checkBox_5, - self.ui.checkBox_6] - - for count in range(self.spanSV): - self.svWins.append(_MplCanvas(subplot=211)) - self.svWins[count].ax[0].axis('Off') - self.svWins[count].ax[1].hold('Off') - - self.ui.gridLayout.addWidget(self.svWins[0],1,0) - self.ui.gridLayout.addWidget(self.svWins[1],1,1) - self.ui.gridLayout.addWidget(self.svWins[2],1,2) - - self.ui.gridLayout.addWidget(self.svWins[3],3,0) - self.ui.gridLayout.addWidget(self.svWins[4],3,1) - self.ui.gridLayout.addWidget(self.svWins[5],3,2) - - self.reconCurrent = _MplCanvas(subplot=211) - self.reconCurrent.ax[0].axis('Off') - self.reconCurrent.ax[1].hold('Off') - - self.reconRemainder = _MplCanvas(subplot=211) - self.reconRemainder.ax[0].axis('Off') - self.reconRemainder.ax[1].hold('Off') - - - self.ui.verticalLayout_3.insertWidget(1,self.reconCurrent) - self.ui.verticalLayout_3.insertWidget(4,self.reconRemainder) - - for count in range(self.spanSV): - self.svLabelCheckBoxes[count].setText('Keep: ' + str(count)) - - if data is not None: - self.data = data - if data.ndim == 3: - self.Mlen, self.Nlen, self.Olen = data.shape - self.reconCurrent.ax[0].imshow(_np.mean(data, axis=-1),interpolation='none', origin='lower') - self.reconCurrent.draw() - - data = data.reshape([-1, self.Olen]) - - self.svddata = self.SvdData() - self.svddata.orig_shape = [self.Mlen, self.Nlen, self.Olen] - self.svddata.U, self.svddata.S, self.svddata.Vh = _svd(data, full_matrices=False) - - self.maxsvs = self.svddata.S.size - - self.ui.lcdMaxFactors.display(self.maxsvs) - self.ui.spinBoxGoTo.setMaximum(self.maxsvs) - - self.updateCurrentRemainder() - - #print('U: {}, S: {}, Vh: {}'.format(self.svddata.U.shape, self.svddata.S.shape, self.svddata.Vh.shape)) - - self.updateSVPlots() - - @staticmethod - def dialogSVD(data, parent = None): - """ - Executes DialogSVD dialog and returns values - """ - dialog = DialogSVD(data, parent) - dialog.showMaximized() - result = dialog.exec_() # 1 = Aceepted, 0 = Rejected/Canceled - - if result == 1: - svs = list(dialog.selected_svs) - svs.sort() - svs = _np.array(svs) - - if svs.size == 0: - return None - else: - return svs - else: - return None - - class SvdData: - """ - Hold SVD factorized components of input data - """ - def __init__(self): - self.U = _np.zeros((0,0)) - self.S = _np.zeros((0)) - self.Vh = _np.zeros((0,0)) - self.orig_shape = [0,0,0] - - def return_svd(self, Select_list=None): - #print('Select_list:{}'.format(Select_list)) - temp = self.s_from_selected(self.S, self.U.shape[-1], self.Vh.shape[0], Select_list) - #print(temp[0:10,0]) - - return _np.dot(self.U, _np.dot(temp, self.Vh)) - - def return_remainder(self, Select_list=None): - return _np.dot(self.U, _np.dot(self.s_from_unselected(self.S, - self.U.shape[-1], - self.Vh.shape[0], - Select_list), - self.Vh)) - - @staticmethod - def s_from_selected(S, M, N, Select_list=None): - """ - Return SVD S-matrix of SELECTED singular values - """ - if Select_list is None: - return _diagsvd(S, M, N) - else: - if type(Select_list) is set: - Select_list = list(Select_list) - - #print(Select_list) - P = _np.zeros(S.size) - #print('P-shape:{}'.format(P.shape)) - #print('Select List:{}'.format(Select_list)) - #print('S-of-select:{}'.format(S[Select_list])) - P[Select_list] = S[Select_list] - #print('P:{}'.format(P[0:10])) - temp = _diagsvd(P, M, N) - return temp - - @staticmethod - def s_from_unselected(S, M, N, Select_list=None): - """ - Return SVD S-matrix of UNselected singular values - """ - if Select_list is None: - return _diagsvd(0*S, M, N) - else: - if type(Select_list) is set: - Select_list = list(Select_list) - P = S.copy() - P[Select_list] = 0 - return _diagsvd(P, M, N) - - def applyCheckBoxes(self): - """ - Add checked singular values (and remove un-checked SVs) - """ - for count, checkBox in enumerate(self.svLabelCheckBoxes): - if checkBox.isChecked() == True: - self.selected_svs.add(self.firstSV+count) - else: - try: - self.selected_svs.remove(self.firstSV+count) - except: - pass - - #print('Self.S: {}'.format(self.svddata.S[0:3])) - self.ui.lcdSelectedFactors.display(len(self.selected_svs)) - self.updateCurrentRemainder() - - def advance(self): - """ - View next set of SVs - """ - sender = self.sender().objectName() - if sender == 'pushButtonPrev': - self.updateSVPlots(startnum=self.firstSV-self.spanSV) - elif sender == 'pushButtonNext': - self.updateSVPlots(startnum=self.firstSV+self.spanSV) - elif sender == 'pushButtonGoTo': - self.updateSVPlots(startnum=self.ui.spinBoxGoTo.value()) - else: - pass - def runScript(self): - """ - Run "script" of singular value selection - - Example: - [1,2,3,5:7] = 1,2,3,5,6,7 - """ - script = self.ui.lineEditSelections.text() - script = script.strip('[').strip(']') - script = script.split(',') - for count in script: - if ':' in count: - temp = count.split(':') - self.selected_svs.update(set(_np.arange(int(temp[0]),int(temp[1])+1))) - elif count.strip() == '': - pass - else: - self.selected_svs.add(int(count)) - self.updateSVPlots(startnum=self.firstSV) - self.ui.lcdSelectedFactors.display(len(self.selected_svs)) - self.updateCurrentRemainder() - - def updateCurrentRemainder(self): - """ - Update image reconstructed (mean over spectral vector) using remaining \ - (unselected) singular values - """ - #print(self.selected_svs) - temp = self.svddata.return_svd(self.selected_svs) - #print(temp[0:10]) - self.showMeanImg(temp, - self.reconCurrent.ax[0], - self.reconCurrent.ax[1], - self.reconCurrent) - - self.showMeanImg(self.svddata.return_remainder(self.selected_svs), - self.reconRemainder.ax[0], - self.reconRemainder.ax[1], - self.reconRemainder) - - def updateSVPlots(self, startnum=0): - """ - Update images and spectra of set of singular values starting at SV \ - number startnum - """ - if startnum <= 0: - startnum = 0 - self.ui.pushButtonPrev.setEnabled(False) - self.ui.pushButtonNext.setEnabled(True) - elif startnum > self.Olen - self.spanSV: - startnum = self.Olen - self.spanSV - self.ui.pushButtonPrev.setEnabled(True) - self.ui.pushButtonNext.setEnabled(False) - else: - self.ui.pushButtonPrev.setEnabled(True) - self.ui.pushButtonNext.setEnabled(True) - - self.firstSV = startnum - - for count in range(self.spanSV): - self.svWins[count].ax[0].clear() - temp = self.svddata.U[:,count + self.firstSV].copy() - temp = _np.reshape(temp,[self.Mlen, self.Nlen]) - - self.svWins[count].ax[0].imshow(-temp*self.svddata.S[count + self.firstSV], interpolation='none', cmap = _mpl.cm.gray , origin='lower') - - self.svWins[count].ax[0].axis('Off') - - self.svWins[count].ax[1].clear() - self.svWins[count].ax[1].plot(-self.svddata.Vh[count + self.firstSV,:]*self.svddata.S[count + self.firstSV]) - #if count == 0: - # print(_np.min(self.svddata.Vh[count + self.firstSV,:])) - self.svLabelCheckBoxes[count].setText('Keep: ' + str(startnum + count)) - self.svWins[count].draw() - if self.firstSV + count in self.selected_svs: - self.svLabelCheckBoxes[count].setChecked(True) - else: - self.svLabelCheckBoxes[count].setChecked(False) - - - def showMeanImg(self, data, ax_img, ax_spectrum, canvas): - """ - Update image reconstructed (mean over spectral vector) using selected \ - singular values - """ - temp = _np.reshape(_np.sum(data,axis=-1),[self.Mlen, self.Nlen]) - #print(temp[0:10,0]) - ax_img.clear() - ax_img.imshow(temp, interpolation='none', cmap = _mpl.cm.gray , origin='lower') - #ax_img.figure.colorbar(img) - #ax_img.imshow(_np.random.rand(100,100), interpolation='none', cmap = _mpl.cm.gray , origin='lower') - ax_spectrum.clear() - ax_spectrum.plot(_np.mean(data,axis=0)) - canvas.draw() - - def clear(self): - """ - Clear selected singular values (i.e., none will be selected) - """ - self.selected_svs = set() - self.ui.lcdSelectedFactors.display(len(self.selected_svs)) - self.updateCurrentRemainder() - self.updateSVPlots(startnum=self.firstSV) - - -if __name__ == '__main__': - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - x = _np.linspace(100,200,50) - y = _np.linspace(200,300,50) - f = _np.linspace(500,3000,800) - Ex = 30*_np.exp((-(f-1750)**2/(200**2))) - Spectrum = _np.convolve(_np.flipud(Ex),Ex,mode='same') - - data = _np.zeros((y.size,x.size,f.size)) - - for count in range(y.size): - data[count,:,:] = y[count]*_np.random.poisson(_np.dot(x[:,None],Spectrum[None,:])) - - win = DialogSVD.dialogSVD(data) ### EDIT ### - - print(win) - - - _sys.exit(app.exec_()) -# _sys.exit() \ No newline at end of file diff --git a/crikit/ui/deprecated/dialog_options.py b/crikit/ui/deprecated/dialog_options.py deleted file mode 100644 index 3d4d962..0000000 --- a/crikit/ui/deprecated/dialog_options.py +++ /dev/null @@ -1,322 +0,0 @@ -""" -CRIkit Options Dialogs (crikit.ui.dialog_options) -======================================================= - -Classes that present dialog boxes that retrieve options - -DialogDarkOptions : Dark subtraction options dialog - -DialogKKOptions : Phase retrieval options dialog. Note: this class only\ - considers the Kramers-Kronig currently - -References ----------- -[1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - -""" - -# Append sys path -import sys as _sys -import os as _os - -# Generic imports for QT-based programs -from PyQt5.QtWidgets import (QApplication as _QApplication, - QWidget as _QWidget, QDialog as _QDialog, - QMainWindow as _QMainWindow, - QSizePolicy as _QSizePolicy) -import PyQt5.QtCore as _QtCore - -# Other imports -import numpy as _np - -# Import from Designer-based GUI -from crikit.ui.qt_DarkOptions import Ui_Dialog as Ui_DarkOptions ### EDIT ### -from crikit.ui.qt_KKOptions import Ui_Dialog as Ui_KKOptions -from crikit.ui.qt_AnscombeOptions import Ui_Dialog as Ui_AnscombeOptions - -from crikit.ui.subui_ploteffect import DialogPlotEffect as _DialogPlotEffect -from crikit.ui.widget_ploteffect import widgetKK as _widgetKK - -# Generic imports for MPL-incorporation -import matplotlib as _mpl -_mpl.use('Qt5Agg') -_mpl.rcParams['font.family'] = 'sans-serif' -_mpl.rcParams['font.size'] = 10 -#import matplotlib.pyplot as plt - -from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as _FigureCanvas, \ - NavigationToolbar2QT as _NavigationToolbar) - -from matplotlib.figure import Figure as _Figure - -class DialogDarkOptions(_QDialog): - """ - DialogDarkOptions : Dark subtraction options dialog - - Methods - -------- - dialogDarkOptions : Used to call UI and retrieve results of dialog - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - SUB_DARK = True - SUB_DARK_IMG = True - SUB_DARK_NRB = True - - RESIDUAL_FREQ = [-1500, -400] - SUB_RESIDUAL = True - - def __init__(self, parent = None): - super(DialogDarkOptions, self).__init__(parent) ### EDIT ### - self.ui = Ui_DarkOptions() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.frameResidual.setEnabled(self.SUB_RESIDUAL) - self.ui.spinBoxMax.setValue(self.RESIDUAL_FREQ[0]) - self.ui.spinBoxMax.setValue(self.RESIDUAL_FREQ[1]) - - self.subdark = self.SUB_DARK - self.subdarkimg = self.SUB_DARK_IMG - self.subdarknrb = self.SUB_DARK_NRB - - self.subresidual = self.SUB_RESIDUAL - self.freq0 = self.RESIDUAL_FREQ[0] - self.freq1 = self.RESIDUAL_FREQ[1] - - self.ui.checkBoxResidualDarkSub.stateChanged.connect(self.checkBoxResidualSub) - self.ui.checkBoxDarkSub.stateChanged.connect(self.checkBoxDarkSub) - self.ui.checkBoxDarkSubImg.stateChanged.connect(self.checkBoxDarkSubImg) - self.ui.checkBoxDarkSubNRB.stateChanged.connect(self.checkBoxDarkSubNRB) - - self.ui.spinBoxMin.editingFinished.connect(self.checkMinMax) - self.ui.spinBoxMax.editingFinished.connect(self.checkMinMax) - - @staticmethod - def dialogDarkOptions(parent = None, darkloaded = False, nrbloaded = False): - """ - Retrieve dark subtraction dialog results - - Parameters - ---------- - nrbloaded : (bool) - Is there an NRB loaded? - - darkloaded : (bool) - Is there a Dark spectrum(a) loaded? - - Returns - ---------- - out : (tuple) - Subtract Dark : (bool) - Subtract Dark from HSData: (bool) - Subtract Dark from NRB: (bool) - Subtract Residual over Frequency Range: (bool) - Frequency Range : (list[str]) - """ - dialog = DialogDarkOptions(parent) - dialog.ui.checkBoxDarkSubNRB.setChecked(nrbloaded) - dialog.ui.checkBoxDarkSubNRB.setEnabled(nrbloaded) - dialog.ui.checkBoxDarkSub.setChecked(darkloaded) - dialog.ui.checkBoxDarkSubImg.setChecked(darkloaded) - dialog.ui.checkBoxDarkSub.setEnabled(darkloaded) - #dialog.ui.checkBoxDarkSubNRB.setEnabled(nrbloaded) - - result = dialog.exec_() - - subdark = dialog.subdark - subresidual = dialog.subresidual - - if result == 1: - if subdark == True: - subdarkimg = dialog.subdarkimg - subdarknrb = dialog.subdarknrb - else: - subdarkimg = None - subdarknrb = None - - if subresidual == True: - freq = [dialog.freq0, dialog.freq1] - freq.sort() - else: - subresidual = False - freq = None - return (subdark, subdarkimg, subdarknrb, subresidual, freq) - else: - return (None, None, None, None, None) - - def checkBoxDarkSubImg(self): - if self.ui.checkBoxDarkSubImg.isChecked() == True: - self.subdarkimg = True - else: - self.subdarkimg = False - - - def checkBoxDarkSubNRB(self): - - if self.ui.checkBoxDarkSubNRB.isChecked() == True: - self.subdarknrb = True - else: - self.subdarknrb = False - - def checkBoxDarkSub(self): - if self.ui.checkBoxDarkSub.isChecked() == True: - self.ui.frameDark.setEnabled(True) - self.subdark = True - else: - self.ui.frameDark.setEnabled(False) - self.subdark = False - self.ui.checkBoxDarkSubImg.setChecked(False) - self.ui.checkBoxDarkSubNRB.setChecked(False) - - def checkBoxResidualSub(self): - if self.ui.checkBoxResidualDarkSub.isChecked() == True: - self.ui.frameResidual.setEnabled(True) - self.subresidual = True - else: - self.ui.frameResidual.setEnabled(False) - self.subresidual = False - - def checkMinMax(self): - self.freq0 = self.ui.spinBoxMin.value() - self.freq1 = self.ui.spinBoxMax.value() - -class DialogKKOptions(_QDialog): - """ - DialogKKOptions : Phase-Retrieval (only Kramers-Kronig currently \ - supported) options dialog - - Methods - -------- - dialogKKOptions : Used to call UI and retrieve results of dialog - - References - ---------- - [1] Y. Liu, Y. J. Lee, and M. T. Cicerone, "Broadband CARS spectral \ - phase retrieval using a time-domain Kramers-Kronig transform," \ - Opt. Lett. 34, 1363-1365 (2009). - - [2] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - NORM_TO_NRB = True - NRB_AMP = 0.0 - CARS_AMP = 0.0 - PHASE_OFFSET = 0.0 - PAD_FACTOR = 1 - - def __init__(self, parent=None, data=None): - super(DialogKKOptions, self).__init__(parent) ### EDIT ### - self.ui = Ui_KKOptions() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.doubleSpinBoxCARSAmp.setValue(self.CARS_AMP) - self.ui.doubleSpinBoxNRBAmp.setValue(self.NRB_AMP) - self.ui.doubleSpinBoxPhase.setValue(self.PHASE_OFFSET) - self.ui.checkBoxNormToNRB.setChecked(self.NORM_TO_NRB) - self.ui.spinBoxPadFactor.setValue(self.PAD_FACTOR) - - self.ui.checkBoxNormToNRB.stateChanged.connect(self.checkBoxNormToNRB) - - self.norm_to_nrb = self.NORM_TO_NRB - - self.data = data - - if data is None: - self.ui.pushButtonInteractive.setEnabled(False) - else: - self.ui.pushButtonInteractive.pressed.connect(self.goInteractive) - - def checkBoxNormToNRB(self): - if self.ui.checkBoxNormToNRB.isChecked() == True: - self.norm_to_nrb = True - else: - self.norm_to_nrb = False - - def goInteractive(self): - - plugin = _widgetKK() - - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(self.data, x=self.data[0], plugin=plugin, xlabel='Wavenumber (cm$^{-1}$)', ylabel='Imag. {$\chi_R$} (au)') - - if winPlotEffect is not None: - self.ui.doubleSpinBoxCARSAmp.setValue(winPlotEffect.cars_bias) - self.ui.doubleSpinBoxNRBAmp.setValue(winPlotEffect.nrb_bias) - self.ui.checkBoxNormToNRB.setChecked(winPlotEffect.nrb_norm) - self.ui.doubleSpinBoxPhase.setValue(winPlotEffect.phaselin) - self.ui.spinBoxPadFactor.setValue(winPlotEffect.pad_factor) - - @staticmethod - def dialogKKOptions(parent=None, data=None): - """ - Retrieve dark subtraction dialog results - - Parameters - ---------- - None : None - - Returns - ---------- - out : (tuple) - HSData amp offset : (float) - NRB amp offset : (float) - Phase offset : (float) - Normalize by NRB : (bool) - Pad factor : (int) - """ - dialog = DialogKKOptions(parent=parent,data=data) - - result = dialog.exec_() - - if result == 1: - - return (dialog.ui.doubleSpinBoxCARSAmp.value(), - dialog.ui.doubleSpinBoxNRBAmp.value(), - dialog.ui.doubleSpinBoxPhase.value(), - dialog.norm_to_nrb, - dialog.ui.spinBoxPadFactor.value()) - else: - return (None, None, None, None, None) - -if __name__ == '__main__': - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - - winDark = DialogDarkOptions.dialogDarkOptions(darkloaded=True) - - from crikit.data.hsi import Hsi as _Hsi - - temp = _Hsi() - - WN = _np.linspace(500,4000,1000) - - CARS = _np.zeros((20,20,WN.size)) - CARS[:,:,:] = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - temp.data = CARS - temp.freq.data = WN - - - NRB = 0*WN + .055 - - - winKK = DialogKKOptions.dialogKKOptions(data=[WN, NRB, - temp.get_rand_spectra(10, pt_sz=3, quads=False)]) -# -# winAnscombe = DialogAnscombeOptions.dialogAnscombeOptions() - - print('Dark return: {}'.format(winDark)) -# print('KK return:{}'.format(winKK)) -# print('Anscombe return:{}'.format(winAnscombe)) - - _sys.exit() \ No newline at end of file diff --git a/crikit/ui/deprecated/dialog_ploteffect.py b/crikit/ui/deprecated/dialog_ploteffect.py deleted file mode 100644 index cd30a82..0000000 --- a/crikit/ui/deprecated/dialog_ploteffect.py +++ /dev/null @@ -1,371 +0,0 @@ -""" -Plot-Effect Interface (crikit.ui.subui_ploteffect) -======================================================= - - -TODO: Do some manual tight layout assessment to make sure labels and titles \ -are fully visible - -""" - -# Append sys path -import sys as _sys -import os as _os - -# Generic imports for QT-based programs -from PyQt5.QtWidgets import (QApplication as _QApplication, - QDialog as _QDialog, - QColorDialog as _QColorDialog, - QDoubleSpinBox as _QDoubleSpinBox, - QComboBox as _QComboBox, - QLineEdit as _QLineEdit, - QStyledItemDelegate as _QStyledItemDelegate, - QWidget as _QWidget) - -from PyQt5.QtCore import (QAbstractTableModel as _QAbstractTableModel, - QModelIndex as _QModelIndex, - QVariant as _QVariant, - Qt as _Qt, - pyqtSignal as _pyqtSignal, - QObject as _QObject) - -from PyQt5.QtGui import (QPixmap as _QPixmap, - QIcon as _QIcon, - QColor as _QColor) - -# Other imports -import numpy as _np - -# Import from Designer-based GUI -from crikit.ui.qt_PlotEffect import Ui_Dialog as Ui_DialogPlotEffect -from crikit.ui.helper_plotOptions import plotStyle - -# Generic imports for MPL-incorporation -import matplotlib as _mpl -_mpl.use('Qt5Agg') -_mpl.rcParams['font.family'] = 'sans-serif' -_mpl.rcParams['font.size'] = 10 -_mpl.rcParams['savefig.dpi'] = 300 -_mpl.rcParams['figure.figsize'] = (4, 4) -#_mpl.rcParams['figure.autolayout'] = True -_mpl.rcParams['legend.fontsize'] = 10 - -from matplotlib.backends.backend_qt5agg import \ - (FigureCanvasQTAgg as _FigureCanvas, - NavigationToolbar2QT as _NavigationToolbar) - -from matplotlib.figure import Figure as _Figure - - -class _winMpl: - def __init__(self): - self.fig = None - self.ax = None - self.img = None - self.canvas = None - self.toolbar = None - -class DialogPlotEffect(_QDialog): - """ - Plotter subUI class - """ - XLABEL = 'X (au)' - YLABEL = 'Y (au)' - - def __init__(self, data, x=None, plugin=None, xlabel=None, ylabel=None, show_difference=False, parent=None): - super(DialogPlotEffect, self).__init__(parent) - self.ui = Ui_DialogPlotEffect() - self.ui.setupUi(self) - - self.data = data - - self.mpl_orig = _winMpl() - self.mpl_orig.fig = _Figure(facecolor=[1, 1, 1]) - self.mpl_orig.ax = self.mpl_orig.fig.add_subplot(111) - self.mpl_orig.canvas = _FigureCanvas(self.mpl_orig.fig) - self.mpl_orig.toolbar = _NavigationToolbar(self.mpl_orig.canvas, None) - - self.mpl_affected = _winMpl() - self.mpl_affected.fig = _Figure(facecolor=[1, 1, 1]) - self.mpl_affected.ax = self.mpl_affected.fig.add_subplot(111) - self.mpl_affected.canvas = _FigureCanvas(self.mpl_affected.fig) - self.mpl_affected.toolbar = _NavigationToolbar(self.mpl_affected.canvas, None) - - self.ui.verticalLayout.insertWidget(1, self.mpl_orig.canvas) - self.ui.verticalLayout.insertWidget(1, self.mpl_orig.toolbar) - - self.ui.verticalLayout.insertWidget(3, self.mpl_affected.canvas) - self.ui.verticalLayout.insertWidget(3, self.mpl_affected.toolbar) - - # Plugin that brings functionality to PlotEffect - self.plugin = plugin - - # Signal emited when something changes in the plugin widget - self.plugin.changed.connect(self.widget_changed) - - if xlabel is None: - self.ui.xlabel = self.XLABEL - else: - self.ui.xlabel = xlabel - - if ylabel is None: - self.ui.ylabel = self.YLABEL - else: - self.ui.ylabel = ylabel - - if x is None: - self.x = _np.linspace(0,data.shape[0],self.data.shape[0]) - else: - self.x = x - - self.show_diff = show_difference - - - if not isinstance(data, list): - try: - self.mpl_orig.ax.plot(self.x,data) - except: - self.mpl_orig.ax.plot(self.x,data.T) - - self.mpl_orig.ax.xaxis.set_label_text(self.ui.xlabel) - self.mpl_orig.ax.yaxis.set_label_text(self.ui.ylabel) -# self.mpl_orig.fig.tight_layout(rect=[-.05,0.05,1,.95]) - self.mpl_orig.ax.set_title('Original') - else: - if self.plugin is not None: - - try: - self.mpl_orig.ax.plot(self.x,self.plugin.fcn(self.data)) - except: - self.mpl_orig.ax.plot(self.x,self.plugin.fcn(self.data).T) - - self.mpl_orig.ax.xaxis.set_label_text(self.ui.xlabel) - self.mpl_orig.ax.yaxis.set_label_text(self.ui.ylabel) -# self.mpl_orig.fig.tight_layout(rect=[0,0.05,1,.9]) - self.mpl_orig.ax.set_title('Original') - - if self.plugin is not None: - self.ui.verticalLayout.insertWidget(8, plugin) - - self.widget_changed() - self.mpl_orig.canvas.draw() - self.mpl_affected.canvas.draw() - - self.ui.pushButtonOk.clicked.connect(self.accept) - self.ui.pushButtonCancel.clicked.connect(self.reject) - - def widget_changed(self): - """ - Plugin widget has changed. Re-submit data to plugin function. - """ -# try: -# print(self.data.shape) -# except: -# pass - if self.plugin is not None: - self.mpl_affected.ax.clear() - try: -# print('Here 1') - affected_data = self.plugin.fcn(self.data).T - self.mpl_affected.ax.plot(self.x,affected_data) - except: - try: -# print('Here 2') - affected_data = self.plugin.fcn(self.data) - self.mpl_affected.ax.plot(self.x,affected_data) - except: - pass - self.mpl_affected.ax.xaxis.set_label_text(self.ui.xlabel) - self.mpl_affected.ax.yaxis.set_label_text(self.ui.ylabel) - self.mpl_affected.ax.set_title('Processed') -# self.mpl_affected.fig.tight_layout(rect=[0,0.05,1,.95]) - - self.mpl_affected.canvas.draw() - - if self.show_diff: - self.mpl_orig.ax.clear() - if not isinstance(self.data, list): - try: - self.mpl_orig.ax.plot(self.x,self.data.T) - except: - try: - self.mpl_orig.ax.plot(self.x,self.data) - except: - pass - - try: - self.mpl_orig.ax.plot(self.x,self.data.T-affected_data, linestyle='dashed') - except: - try: - self.mpl_orig.ax.plot(self.x,self.data-affected_data, linestyle='dashed') - except: - pass - - - self.mpl_orig.ax.xaxis.set_label_text(self.ui.xlabel) - self.mpl_orig.ax.yaxis.set_label_text(self.ui.ylabel) - # self.mpl_orig.fig.tight_layout(rect=[-.05,0.05,1,.95]) - self.mpl_orig.ax.set_title('Original') - self.mpl_orig.canvas.draw() - - @staticmethod - def dialogPlotEffect(data, x = None, plugin=None, xlabel=None, ylabel=None, - show_difference=False, parent = None): - """ - Executes DialogPlotEffect - - Parameters - ---------- - data : (np.ndarray, list) - Array for straightforward plotting, list if plugin.fcn requires \ - multiple inputs - plugin : object - Plugin container class - xlabel : str - String describing independent variable - ylabel : str - String describing dependent variable - show_difference : bool - Plot the difference between the original data and the affected \ - (perfomed-on) data overlaid with the original data. Note: \ - difference shown with dashed line - parent : object - Parent object - - Returns - ------- - out : object - Returns access to the plugin variables - - """ - dialog = DialogPlotEffect(data, x=x, plugin=plugin, xlabel=xlabel, - ylabel=ylabel, show_difference=show_difference, - parent=parent) - - result = dialog.exec_() # 1 = Aceepted, 0 = Rejected/Canceled - - if result == 1: - #print('----------------\nReturned: Ok!\n') - #print(dialog.plugin.__dict__) - - return dialog.plugin - - else: - #print('----------------\nReturned: Cancel!\n') - return None - - -if __name__ == '__main__': - - from crikit.ui.widget_ploteffect import (widgetNothing, widgetKK, - widgetALS, widgetSG, - widgetCalibrate) - - app = _QApplication(_sys.argv) - - - ################# - # KK Demo - plugin = widgetKK() - - WN = _np.linspace(500,4000,800) - CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - NRB = 0*WN + .055 - - winPlotEffect = DialogPlotEffect.dialogPlotEffect([WN, NRB, CARS], x=WN, - plugin=plugin, - xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Imag. {$\chi_R$} (au)') - - if winPlotEffect is not None: - print('CARS Bias: {}'.format(winPlotEffect.cars_bias)) - print('NRB Bias: {}'.format(winPlotEffect.nrb_bias)) - print('Norm by NRB: {}'.format(winPlotEffect.nrb_norm)) - print('Phase correction constant: {}'.format(winPlotEffect.phaselin)) - print('KK algorithm pad factor: {}'.format(winPlotEffect.pad_factor)) - print('Phase correction constant type: {}'.format(winPlotEffect.phase_type)) - ################## - - ################ - # ALS Demo - plugin = widgetALS() - - WN = _np.linspace(500,4000,800) - CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - NRB = 0*WN + .055 - CARS = _np.dot(_np.ones((5,1)),CARS[None,:]) - winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, plugin=plugin, - xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Imag. {$\chi_R$} (au)', - show_difference=True) - - if winPlotEffect is not None: - print('P-Value: {}'.format(winPlotEffect.p)) - print('Lambda-Value: {}'.format(winPlotEffect.lam)) - print('Redux: {}'.format(winPlotEffect.redux)) - - ################ - # SG Demo - plugin = widgetSG(win_size=501, order=5) - - WN = _np.linspace(500,4000,800) - CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - NRB = 0*WN + .055 - CARS = _np.dot(_np.ones((5,1)),CARS[None,:]) - winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, plugin=plugin, - xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Imag. {$\chi_R$} (au)', - show_difference=True) - - if winPlotEffect is not None: - print('Window Size: {}'.format(winPlotEffect.win_size)) - print('Order: {}'.format(winPlotEffect.order)) - - - ################ - # Calibrate Demo - plugin = widgetCalibrate() - - - calib_dict = {} - calib_dict['n_pix'] = 1600 - calib_dict['ctr_wl'] = 730.0 - calib_dict['ctr_wl0'] = 730.0 - calib_dict['probe'] = 771.461 - calib_dict['units'] = 'nm' - calib_dict['a_vec'] = (-0.167740721307557, 863.8736708961577) # slope, intercept - - from crikit.data.frequency import calib_pix_wl, calib_pix_wn - wl_vec, units_wl = calib_pix_wl(calib_dict) - WN, units_wn = calib_pix_wn(calib_dict) - - #WN = _np.linspace(500,4000,800) - CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - NRB = 0*WN + .055 -# CARS = _np.dot(_np.ones((5,1)),CARS[None,:]) - winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, plugin=plugin, - xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Imag. {$\chi_R$} (au)', - show_difference=False) - - if winPlotEffect is not None: - print('New Calibration Dictionary: {}'.format(winPlotEffect.new_calib_dict)) -# print('Order: {}'.format(winPlotEffect.order)) - - - ################# - # Nothing Demo - plugin = widgetNothing() - - x = _np.linspace(1,100,100) - data = _np.random.randn(100) - - winPlotEffect = DialogPlotEffect.dialogPlotEffect(data, x=x, plugin=plugin, xlabel='Wavenumber (cm$^{-1}$)', ylabel='Imag. {$\chi_R$} (au)') - - if winPlotEffect is not None: - print('This plugin did nothing, as expected.') - ################## - -# print(winPlotEffect.__dict__) - - _sys.exit() \ No newline at end of file diff --git a/crikit/ui/deprecated/dialog_plugin.py b/crikit/ui/deprecated/dialog_plugin.py deleted file mode 100644 index a2961ea..0000000 --- a/crikit/ui/deprecated/dialog_plugin.py +++ /dev/null @@ -1,254 +0,0 @@ -""" -Created on Tue Feb 16 15:51:32 2016 - -@author: camp -""" - -import sys as _sys -import os as _os - -# Generic imports for QT-based programs -from PyQt5.QtWidgets import (QApplication as _QApplication, - QWidget as _QWidget, QDialog as _QDialog, - QMainWindow as _QMainWindow, - QSizePolicy as _QSizePolicy) -import PyQt5.QtCore as _QtCore - -# Other imports -import numpy as _np - -from yapsy.PluginManager import (PluginManager as _PluginManager, - PluginInfo as _PluginInfo) - -from crikit.ui.helper_plugin_categories import DeNoiser, ErrorCorrect -#import logging -#logging.basicConfig(level=logging.DEBUG) - -# Import from Designer-based GUI -from crikit.ui.qt_PluginSelector import Ui_Dialog - - -# Generic imports for MPL-incorporation -import matplotlib as _mpl -_mpl.use('Qt5Agg') -_mpl.rcParams['font.family'] = 'sans-serif' -_mpl.rcParams['font.size'] = 10 -#import matplotlib.pyplot as plt - -#from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as _FigureCanvas, \ -# NavigationToolbar2QT as _NavigationToolbar) - -#from matplotlib.figure import Figure as _Figure - -class DialogDenoisePlugins(_QDialog): - """ - DialogDenoisePlugins : Denoise plugin selector - - Methods - ------------- - dialogDenoisePlugins : Used to call UI and retrieve results of dialog - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - - def __init__(self, parent = None): - super(DialogDenoisePlugins, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.temp = 0 - - # Create plugin manager - self.manager = _PluginManager() - - - if _os.path.isdir(_os.path.abspath('./plugins')): - plugins_loc = 'plugins' - elif _os.path.isdir(_os.path.abspath('./crikit/ui/plugins')): - plugins_loc = './crikit/ui/plugins' - elif _os.path.isdir(_os.path.abspath('./ui/plugins')): - plugins_loc = './ui/plugins' - else: - plugins_loc = None - - self.manager.setPluginPlaces([plugins_loc]) - self.manager.setCategoriesFilter({'DeNoiser' : DeNoiser}) - - self.manager.collectPlugins() - - # Load plugins - self.manager.locatePlugins() - - self.manager.loadPlugins() - self.denoisers = {} - self.denoiser_desc = {} - - for plugin in self.manager.getPluginsOfCategory('DeNoiser'): - self.ui.comboBox.addItem(plugin.plugin_object.name) - self.denoisers[plugin.plugin_object.name] = plugin.plugin_object - self.denoiser_desc[plugin.plugin_object.name] = plugin._PluginInfo__details['Documentation']['description'] - - #print(self.denoiser_desc[self.ui.comboBox.currentText]) - self.ui.plainTextEditDescription.setPlainText(self.denoiser_desc[self.ui.comboBox.currentText()]) - self.ui.comboBox.currentIndexChanged.connect(self.changeDesc) - - def changeDesc(self): - self.ui.plainTextEditDescription.setPlainText(self.denoiser_desc[self.ui.comboBox.currentText()]) - - @staticmethod - def dialogDenoisePlugins(parent = None): - """ - - """ - - dialog = DialogDenoisePlugins(parent) - - result = dialog.exec_() - - - if result == 1: # Accepted - return (dialog.denoisers[dialog.ui.comboBox.currentText()]) - else: # Rejected/Cancel - return None - -class DialogErrCorrPlugins(_QDialog): - """ - DialogErrCorrPlugins : Error correction plugin selector - - Methods - ------------- - dialogErrCorrPlugins : Used to call UI and retrieve results of dialog - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - - def __init__(self, parent = None): - super(DialogErrCorrPlugins, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.temp = 0 - - # Create plugin manager - self.manager = _PluginManager() - - - if _os.path.isdir(_os.path.abspath('./plugins')): - plugins_loc = 'plugins' - elif _os.path.isdir(_os.path.abspath('./crikit/ui/plugins')): - plugins_loc = './crikit/ui/plugins' - elif _os.path.isdir(_os.path.abspath('./ui/plugins')): - plugins_loc = './ui/plugins' - else: - plugins_loc = None - - self.manager.setPluginPlaces([plugins_loc]) - self.manager.setCategoriesFilter({'ErrorCorrect' : ErrorCorrect}) - - self.manager.collectPlugins() - - # Load plugins - self.manager.locatePlugins() - - self.manager.loadPlugins() - self.errcorrectors = {} - self.errcorrectors_desc = {} - - for plugin in self.manager.getPluginsOfCategory('ErrorCorrect'): - self.ui.comboBox.addItem(plugin.plugin_object.name) - self.errcorrectors[plugin.plugin_object.name] = plugin.plugin_object - self.errcorrectors_desc[plugin.plugin_object.name] = plugin._PluginInfo__details['Documentation']['description'] - - self.ui.comboBox.currentIndexChanged.connect(self.changeDesc) - - try: - self.ui.plainTextEditDescription.setPlainText(self.errcorrectors_desc[self.ui.comboBox.currentText()]) - - except: # Fails if no plugins found - pass - - def changeDesc(self): - - try: - self.ui.plainTextEditDescription.setPlainText(self.errcorrectors_desc[self.ui.comboBox.currentText()]) - except: # Fails if no plugins found - pass - - @staticmethod - def dialogErrCorrPlugins(parent = None): - """ - - """ - - dialog = DialogErrCorrPlugins(parent) - - result = dialog.exec_() - - - if result == 1: # Accepted - return (dialog.errcorrectors[dialog.ui.comboBox.currentText()]) - else: # Rejected/Cancel - return None - - -if __name__ == '__main__': - - -# from crikit.data.classes import HSData -# - x = _np.linspace(100,200,50) - y = _np.linspace(200,300,50) - f = _np.linspace(500,3000,800) - Ex = 30*_np.exp((-(f-1750)**2/(200**2))) - Spectrum = _np.convolve(_np.flipud(Ex),Ex,mode='same') - - data = _np.zeros((y.size,x.size,f.size)) - for count in range(y.size): - data[count,:,:] = y[count]*_np.random.poisson(_np.dot(x[:,None],Spectrum[None,:])) - - #temp = HSData() - #temp.spectrafull = data - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - ### DeNoise Demo - win = DialogDenoisePlugins.dialogDenoisePlugins() - - if win is not None: - retwin = win.denoiseHSData(data) - print('RetWin:{}'.format(retwin)) - -# ### Error Correction Demo -# win = DialogErrCorrPlugins.dialogErrCorrPlugins() -# -## temp = HSData() -# -# WN = _np.linspace(500,4000,1000) -# -# CARS = _np.zeros((20,20,WN.size), dtype=complex) -# CARS[:,:,:] = (1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) -# temp.spectrafull = CARS -# temp.freqvecfull = WN -# -# -# NRB = 0*WN + .055 -# -# if win is not None: -# retwin = win.errorCorrectHSData(data) -# #if win is not None: -# #retwin = win.denoiseHSData(temp) -# #print('RetWin:{}'.format(retwin)) -# -# _sys.exit() - app.exec_() \ No newline at end of file diff --git a/crikit/ui/deprecated/qt_BWImage.py b/crikit/ui/deprecated/qt_BWImage.py deleted file mode 100644 index 48667fa..0000000 --- a/crikit/ui/deprecated/qt_BWImage.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'ui_BWImage.ui' -# -# Created by: PyQt5 UI code generator 5.5 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(635, 480) - Form.setStyleSheet("font: 10pt \"Arial\";") - self.gridLayout = QtWidgets.QGridLayout(Form) - self.gridLayout.setObjectName("gridLayout") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.frame_2 = QtWidgets.QFrame(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth()) - self.frame_2.setSizePolicy(sizePolicy) - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame_2.setObjectName("frame_2") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_2) - self.horizontalLayout.setObjectName("horizontalLayout") - self.verticalLayout_5 = QtWidgets.QVBoxLayout() - self.verticalLayout_5.setObjectName("verticalLayout_5") - self.checkBoxFixed = QtWidgets.QCheckBox(self.frame_2) - self.checkBoxFixed.setChecked(False) - self.checkBoxFixed.setObjectName("checkBoxFixed") - self.verticalLayout_5.addWidget(self.checkBoxFixed) - self.checkBoxCompress = QtWidgets.QCheckBox(self.frame_2) - self.checkBoxCompress.setChecked(False) - self.checkBoxCompress.setObjectName("checkBoxCompress") - self.verticalLayout_5.addWidget(self.checkBoxCompress) - self.horizontalLayout.addLayout(self.verticalLayout_5) - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.label_2 = QtWidgets.QLabel(self.frame_2) - self.label_2.setObjectName("label_2") - self.verticalLayout_2.addWidget(self.label_2) - self.lineEditMin = QtWidgets.QLineEdit(self.frame_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.lineEditMin.sizePolicy().hasHeightForWidth()) - self.lineEditMin.setSizePolicy(sizePolicy) - self.lineEditMin.setMinimumSize(QtCore.QSize(0, 25)) - self.lineEditMin.setMaximumSize(QtCore.QSize(16777215, 25)) - self.lineEditMin.setObjectName("lineEditMin") - self.verticalLayout_2.addWidget(self.lineEditMin) - self.horizontalLayout.addLayout(self.verticalLayout_2) - self.verticalLayout_3 = QtWidgets.QVBoxLayout() - self.verticalLayout_3.setSpacing(6) - self.verticalLayout_3.setObjectName("verticalLayout_3") - self.label = QtWidgets.QLabel(self.frame_2) - self.label.setObjectName("label") - self.verticalLayout_3.addWidget(self.label) - self.lineEditMax = QtWidgets.QLineEdit(self.frame_2) - self.lineEditMax.setMinimumSize(QtCore.QSize(0, 25)) - self.lineEditMax.setMaximumSize(QtCore.QSize(16777215, 25)) - self.lineEditMax.setObjectName("lineEditMax") - self.verticalLayout_3.addWidget(self.lineEditMax) - self.horizontalLayout.addLayout(self.verticalLayout_3) - self.frame = QtWidgets.QFrame(self.frame_2) - self.frame.setFrameShape(QtWidgets.QFrame.VLine) - self.frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame.setObjectName("frame") - self.horizontalLayout.addWidget(self.frame) - self.checkBoxRemOutliers = QtWidgets.QCheckBox(self.frame_2) - self.checkBoxRemOutliers.setObjectName("checkBoxRemOutliers") - self.horizontalLayout.addWidget(self.checkBoxRemOutliers) - self.verticalLayout_4 = QtWidgets.QVBoxLayout() - self.verticalLayout_4.setObjectName("verticalLayout_4") - self.label_3 = QtWidgets.QLabel(self.frame_2) - self.label_3.setObjectName("label_3") - self.verticalLayout_4.addWidget(self.label_3) - self.spinBoxStdDevs = QtWidgets.QDoubleSpinBox(self.frame_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.spinBoxStdDevs.sizePolicy().hasHeightForWidth()) - self.spinBoxStdDevs.setSizePolicy(sizePolicy) - self.spinBoxStdDevs.setProperty("value", 3.0) - self.spinBoxStdDevs.setObjectName("spinBoxStdDevs") - self.verticalLayout_4.addWidget(self.spinBoxStdDevs) - self.horizontalLayout.addLayout(self.verticalLayout_4) - self.verticalLayout.addWidget(self.frame_2, 0, QtCore.Qt.AlignHCenter) - self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.checkBoxFixed.setText(_translate("Form", "Fixed")) - self.checkBoxCompress.setText(_translate("Form", "Compress")) - self.label_2.setText(_translate("Form", "Minimum")) - self.label.setText(_translate("Form", "Maximum")) - self.checkBoxRemOutliers.setText(_translate("Form", "Outlier Removal")) - self.label_3.setText(_translate("Form", "Std. Dev\'s")) - diff --git a/crikit/ui/deprecated/qt_ColorMath.py b/crikit/ui/deprecated/qt_ColorMath.py deleted file mode 100644 index f3608dd..0000000 --- a/crikit/ui/deprecated/qt_ColorMath.py +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '.\ui_ColorMath.ui' -# -# Created by: PyQt5 UI code generator 5.5.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(785, 202) - Form.setStyleSheet("font: 10pt \"Arial\";") - self.gridLayout_5 = QtWidgets.QGridLayout(Form) - self.gridLayout_5.setObjectName("gridLayout_5") - self.frame_3 = QtWidgets.QFrame(Form) - self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_3.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame_3.setObjectName("frame_3") - self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_3) - self.gridLayout_3.setObjectName("gridLayout_3") - self.verticalLayout_3 = QtWidgets.QVBoxLayout() - self.verticalLayout_3.setObjectName("verticalLayout_3") - self.label_3 = QtWidgets.QLabel(self.frame_3) - self.label_3.setObjectName("label_3") - self.verticalLayout_3.addWidget(self.label_3) - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.pushButtonOpFreq1 = QtWidgets.QPushButton(self.frame_3) - self.pushButtonOpFreq1.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonOpFreq1.setObjectName("pushButtonOpFreq1") - self.horizontalLayout.addWidget(self.pushButtonOpFreq1) - self.comboBoxOperations = QtWidgets.QComboBox(self.frame_3) - self.comboBoxOperations.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBoxOperations.sizePolicy().hasHeightForWidth()) - self.comboBoxOperations.setSizePolicy(sizePolicy) - self.comboBoxOperations.setObjectName("comboBoxOperations") - self.horizontalLayout.addWidget(self.comboBoxOperations) - self.pushButtonOpFreq2 = QtWidgets.QPushButton(self.frame_3) - self.pushButtonOpFreq2.setEnabled(False) - self.pushButtonOpFreq2.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonOpFreq2.setObjectName("pushButtonOpFreq2") - self.horizontalLayout.addWidget(self.pushButtonOpFreq2) - self.pushButtonOpFreq3 = QtWidgets.QPushButton(self.frame_3) - self.pushButtonOpFreq3.setEnabled(False) - self.pushButtonOpFreq3.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonOpFreq3.setObjectName("pushButtonOpFreq3") - self.horizontalLayout.addWidget(self.pushButtonOpFreq3) - self.verticalLayout_3.addLayout(self.horizontalLayout) - self.gridLayout_3.addLayout(self.verticalLayout_3, 0, 0, 1, 1) - self.gridLayout_5.addWidget(self.frame_3, 0, 0, 1, 1) - self.frame = QtWidgets.QFrame(Form) - self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame.setLineWidth(1) - self.frame.setMidLineWidth(0) - self.frame.setObjectName("frame") - self.gridLayout = QtWidgets.QGridLayout(self.frame) - self.gridLayout.setObjectName("gridLayout") - self.verticalLayout_5 = QtWidgets.QVBoxLayout() - self.verticalLayout_5.setObjectName("verticalLayout_5") - self.checkBox = QtWidgets.QCheckBox(self.frame) - self.checkBox.setEnabled(False) - self.checkBox.setObjectName("checkBox") - self.verticalLayout_5.addWidget(self.checkBox) - self.pushButtonDoMath = QtWidgets.QPushButton(self.frame) - self.pushButtonDoMath.setEnabled(True) - self.pushButtonDoMath.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonDoMath.setObjectName("pushButtonDoMath") - self.verticalLayout_5.addWidget(self.pushButtonDoMath) - self.gridLayout.addLayout(self.verticalLayout_5, 0, 0, 1, 1) - self.gridLayout_5.addWidget(self.frame, 0, 1, 1, 1) - self.frame_2 = QtWidgets.QFrame(Form) - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame_2.setObjectName("frame_2") - self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_2) - self.gridLayout_2.setObjectName("gridLayout_2") - self.verticalLayout_6 = QtWidgets.QVBoxLayout() - self.verticalLayout_6.setObjectName("verticalLayout_6") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setSpacing(0) - self.verticalLayout.setObjectName("verticalLayout") - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setSpacing(0) - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.label = QtWidgets.QLabel(self.frame_2) - self.label.setObjectName("label") - self.verticalLayout_2.addWidget(self.label) - self.lineEditMax = QtWidgets.QLineEdit(self.frame_2) - self.lineEditMax.setMinimumSize(QtCore.QSize(0, 25)) - self.lineEditMax.setMaximumSize(QtCore.QSize(16777215, 25)) - self.lineEditMax.setReadOnly(False) - self.lineEditMax.setObjectName("lineEditMax") - self.verticalLayout_2.addWidget(self.lineEditMax) - self.verticalLayout.addLayout(self.verticalLayout_2) - self.label_2 = QtWidgets.QLabel(self.frame_2) - self.label_2.setObjectName("label_2") - self.verticalLayout.addWidget(self.label_2) - self.lineEditMin = QtWidgets.QLineEdit(self.frame_2) - self.lineEditMin.setMinimumSize(QtCore.QSize(0, 25)) - self.lineEditMin.setMaximumSize(QtCore.QSize(16777215, 25)) - self.lineEditMin.setReadOnly(False) - self.lineEditMin.setObjectName("lineEditMin") - self.verticalLayout.addWidget(self.lineEditMin) - self.verticalLayout_6.addLayout(self.verticalLayout) - self.gridLayout_2.addLayout(self.verticalLayout_6, 1, 0, 1, 1) - self.verticalLayout_8 = QtWidgets.QVBoxLayout() - self.verticalLayout_8.setObjectName("verticalLayout_8") - self.checkBoxFixed = QtWidgets.QCheckBox(self.frame_2) - self.checkBoxFixed.setEnabled(True) - self.checkBoxFixed.setChecked(False) - self.checkBoxFixed.setObjectName("checkBoxFixed") - self.verticalLayout_8.addWidget(self.checkBoxFixed) - self.checkBoxCompress = QtWidgets.QCheckBox(self.frame_2) - self.checkBoxCompress.setEnabled(True) - self.checkBoxCompress.setChecked(False) - self.checkBoxCompress.setObjectName("checkBoxCompress") - self.verticalLayout_8.addWidget(self.checkBoxCompress) - self.gridLayout_2.addLayout(self.verticalLayout_8, 0, 0, 1, 1) - self.gridLayout_5.addWidget(self.frame_2, 0, 2, 3, 1) - self.frame_4 = QtWidgets.QFrame(Form) - self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_4.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame_4.setObjectName("frame_4") - self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_4) - self.gridLayout_4.setObjectName("gridLayout_4") - self.verticalLayout_4 = QtWidgets.QVBoxLayout() - self.verticalLayout_4.setSpacing(0) - self.verticalLayout_4.setObjectName("verticalLayout_4") - self.label_4 = QtWidgets.QLabel(self.frame_4) - self.label_4.setObjectName("label_4") - self.verticalLayout_4.addWidget(self.label_4) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.pushButtonCondFreq1 = QtWidgets.QPushButton(self.frame_4) - self.pushButtonCondFreq1.setEnabled(False) - self.pushButtonCondFreq1.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonCondFreq1.setObjectName("pushButtonCondFreq1") - self.horizontalLayout_2.addWidget(self.pushButtonCondFreq1) - self.comboBoxCondOps = QtWidgets.QComboBox(self.frame_4) - self.comboBoxCondOps.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBoxCondOps.sizePolicy().hasHeightForWidth()) - self.comboBoxCondOps.setSizePolicy(sizePolicy) - self.comboBoxCondOps.setObjectName("comboBoxCondOps") - self.horizontalLayout_2.addWidget(self.comboBoxCondOps) - self.pushButtonCondFreq2 = QtWidgets.QPushButton(self.frame_4) - self.pushButtonCondFreq2.setEnabled(False) - self.pushButtonCondFreq2.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonCondFreq2.setObjectName("pushButtonCondFreq2") - self.horizontalLayout_2.addWidget(self.pushButtonCondFreq2) - self.pushButtonCondFreq3 = QtWidgets.QPushButton(self.frame_4) - self.pushButtonCondFreq3.setEnabled(False) - self.pushButtonCondFreq3.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButtonCondFreq3.setObjectName("pushButtonCondFreq3") - self.horizontalLayout_2.addWidget(self.pushButtonCondFreq3) - self.comboBoxCondInEquality = QtWidgets.QComboBox(self.frame_4) - self.comboBoxCondInEquality.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBoxCondInEquality.sizePolicy().hasHeightForWidth()) - self.comboBoxCondInEquality.setSizePolicy(sizePolicy) - self.comboBoxCondInEquality.setObjectName("comboBoxCondInEquality") - self.horizontalLayout_2.addWidget(self.comboBoxCondInEquality) - self.spinBoxInEquality = QtWidgets.QDoubleSpinBox(self.frame_4) - self.spinBoxInEquality.setEnabled(False) - self.spinBoxInEquality.setMinimumSize(QtCore.QSize(100, 0)) - self.spinBoxInEquality.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) - self.spinBoxInEquality.setDecimals(5) - self.spinBoxInEquality.setMinimum(-1000000000000.0) - self.spinBoxInEquality.setMaximum(1000000000000.0) - self.spinBoxInEquality.setObjectName("spinBoxInEquality") - self.horizontalLayout_2.addWidget(self.spinBoxInEquality) - self.verticalLayout_4.addLayout(self.horizontalLayout_2) - self.gridLayout_4.addLayout(self.verticalLayout_4, 1, 0, 1, 1) - self.gridLayout_5.addWidget(self.frame_4, 2, 0, 1, 2) - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_5.addItem(spacerItem, 1, 0, 1, 1) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.label_3.setText(_translate("Form", "Basic Math")) - self.pushButtonOpFreq1.setText(_translate("Form", "Freq 1")) - self.pushButtonOpFreq2.setText(_translate("Form", "Freq 2")) - self.pushButtonOpFreq3.setText(_translate("Form", "Freq 3")) - self.checkBox.setText(_translate("Form", "Norm. Intensity")) - self.pushButtonDoMath.setText(_translate("Form", "Perform Math")) - self.label.setText(_translate("Form", "Maximum")) - self.label_2.setText(_translate("Form", "Minimum")) - self.checkBoxFixed.setText(_translate("Form", "Fixed")) - self.checkBoxCompress.setText(_translate("Form", "Compress")) - self.label_4.setText(_translate("Form", "Conditional")) - self.pushButtonCondFreq1.setText(_translate("Form", "Freq 1")) - self.pushButtonCondFreq2.setText(_translate("Form", "Freq 2")) - self.pushButtonCondFreq3.setText(_translate("Form", "Freq 3")) - diff --git a/crikit/ui/deprecated/qt_SglColorImage.py b/crikit/ui/deprecated/qt_SglColorImage.py deleted file mode 100644 index 9771aba..0000000 --- a/crikit/ui/deprecated/qt_SglColorImage.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '.\ui_SglColorImage.ui' -# -# Created by: PyQt5 UI code generator 5.5.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(642, 579) - Form.setMouseTracking(False) - Form.setStyleSheet("font: 10pt \"Arial\";") - self.gridLayout = QtWidgets.QGridLayout(Form) - self.gridLayout.setContentsMargins(-1, 0, -1, 0) - self.gridLayout.setObjectName("gridLayout") - self.verticalLayoutMain = QtWidgets.QVBoxLayout() - self.verticalLayoutMain.setObjectName("verticalLayoutMain") - self.widgetImgOpt = QtWidgets.QWidget(Form) - self.widgetImgOpt.setEnabled(True) - self.widgetImgOpt.setObjectName("widgetImgOpt") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widgetImgOpt) - self.horizontalLayout_3.setContentsMargins(-1, 0, -1, 0) - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.pushButtonPop = QtWidgets.QPushButton(self.widgetImgOpt) - self.pushButtonPop.setEnabled(True) - self.pushButtonPop.setObjectName("pushButtonPop") - self.horizontalLayout_3.addWidget(self.pushButtonPop) - self.pushButtonSpectrum = QtWidgets.QPushButton(self.widgetImgOpt) - self.pushButtonSpectrum.setEnabled(True) - self.pushButtonSpectrum.setObjectName("pushButtonSpectrum") - self.horizontalLayout_3.addWidget(self.pushButtonSpectrum) - self.pushButtonGSPop = QtWidgets.QPushButton(self.widgetImgOpt) - self.pushButtonGSPop.setEnabled(True) - self.pushButtonGSPop.setObjectName("pushButtonGSPop") - self.horizontalLayout_3.addWidget(self.pushButtonGSPop) - self.comboBox = QtWidgets.QComboBox(self.widgetImgOpt) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth()) - self.comboBox.setSizePolicy(sizePolicy) - self.comboBox.setMinimumSize(QtCore.QSize(140, 0)) - self.comboBox.setLayoutDirection(QtCore.Qt.LeftToRight) - self.comboBox.setEditable(False) - self.comboBox.setObjectName("comboBox") - self.horizontalLayout_3.addWidget(self.comboBox, 0, QtCore.Qt.AlignHCenter) - self.pushButtonSpectrum.raise_() - self.pushButtonGSPop.raise_() - self.comboBox.raise_() - self.pushButtonPop.raise_() - self.verticalLayoutMain.addWidget(self.widgetImgOpt) - self.horizontalLayoutGainImg = QtWidgets.QHBoxLayout() - self.horizontalLayoutGainImg.setContentsMargins(10, -1, -1, -1) - self.horizontalLayoutGainImg.setObjectName("horizontalLayoutGainImg") - self.groupBox = QtWidgets.QGroupBox(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth()) - self.groupBox.setSizePolicy(sizePolicy) - self.groupBox.setMinimumSize(QtCore.QSize(120, 0)) - self.groupBox.setMaximumSize(QtCore.QSize(120, 16777215)) - self.groupBox.setObjectName("groupBox") - self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) - self.gridLayout_2.setObjectName("gridLayout_2") - self.verticalLayoutGain = QtWidgets.QVBoxLayout() - self.verticalLayoutGain.setContentsMargins(-1, 6, -1, -1) - self.verticalLayoutGain.setSpacing(6) - self.verticalLayoutGain.setObjectName("verticalLayoutGain") - self.gainSlider = QtWidgets.QSlider(self.groupBox) - self.gainSlider.setMaximum(100) - self.gainSlider.setProperty("value", 10) - self.gainSlider.setSliderPosition(10) - self.gainSlider.setOrientation(QtCore.Qt.Vertical) - self.gainSlider.setInvertedAppearance(False) - self.gainSlider.setTickPosition(QtWidgets.QSlider.TicksAbove) - self.gainSlider.setTickInterval(10) - self.gainSlider.setObjectName("gainSlider") - self.verticalLayoutGain.addWidget(self.gainSlider, 0, QtCore.Qt.AlignHCenter) - self.lineEditGainSlider = QtWidgets.QLineEdit(self.groupBox) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.lineEditGainSlider.sizePolicy().hasHeightForWidth()) - self.lineEditGainSlider.setSizePolicy(sizePolicy) - self.lineEditGainSlider.setMaximumSize(QtCore.QSize(30, 16777215)) - self.lineEditGainSlider.setObjectName("lineEditGainSlider") - self.verticalLayoutGain.addWidget(self.lineEditGainSlider, 0, QtCore.Qt.AlignHCenter) - self.pushButtonGain1 = QtWidgets.QPushButton(self.groupBox) - self.pushButtonGain1.setObjectName("pushButtonGain1") - self.verticalLayoutGain.addWidget(self.pushButtonGain1, 0, QtCore.Qt.AlignHCenter) - self.gridLayout_2.addLayout(self.verticalLayoutGain, 0, 0, 1, 1) - self.horizontalLayoutGainImg.addWidget(self.groupBox) - self.verticalLayoutMain.addLayout(self.horizontalLayoutGainImg) - self.gridLayout.addLayout(self.verticalLayoutMain, 0, 0, 1, 1) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.pushButtonPop.setText(_translate("Form", "Pop")) - self.pushButtonSpectrum.setText(_translate("Form", "Mean Spectrum")) - self.pushButtonGSPop.setText(_translate("Form", "Grayscale")) - self.groupBox.setTitle(_translate("Form", "Gain")) - self.lineEditGainSlider.setText(_translate("Form", "1.0")) - self.pushButtonGain1.setText(_translate("Form", "1.0")) - diff --git a/crikit/ui/deprecated/widget_ploteffect.py b/crikit/ui/deprecated/widget_ploteffect.py deleted file mode 100644 index 805ba8c..0000000 --- a/crikit/ui/deprecated/widget_ploteffect.py +++ /dev/null @@ -1,722 +0,0 @@ -""" -Widgets for Plot-Effect Interface (crikit.ui.widget_ploteffect) -=============================================================== - -widgetNothing : This demo widget does nothing - -widgetKK : This applies the Kramers-Kronig relation phase retrieval operation - -widgetALS : Controls alternating least square parameters - -widgetCalibrate : Controls calibration parameters - - -Operation ---------- -PlotEffect subUI widgets are essentially 3 parts: a visual component that \ -controls any necessary variables, a function (fcn) that performs the \ -mathemtical operation on the input data, and a signal (changed) that conveys \ -that some change has occurred to the variables within the widget UI. - -data_in : (np.array, list) - For function (fcn) with single-input, data_in should be a numpy array. For \ - fcn with multiple input variables, data_in of type list - -changed : QtCore.pyqtSignal - -""" - -# Append sys path -import sys as _sys -import os as _os - -# Generic imports for QT-based programs -from PyQt5.QtWidgets import (QApplication as _QApplication, - QWidget as _QWidget) - -from PyQt5.QtCore import pyqtSignal as _pyqtSignal - -# Other imports -import numpy as _np -from scipy.signal import savgol_filter as _sg -from scipy.interpolate import UnivariateSpline as _UnivariateSpline -import copy as _copy - -# Import from Designer-based GUI - -from crikit.ui.qt_PlotEffect_Nothing import Ui_Form as Ui_Nothing_Form -from crikit.ui.qt_PlotEffect_KK import Ui_Form as Ui_KK_Form -from crikit.ui.qt_PlotEffect_ALS import Ui_Form as Ui_ALS_Form -from crikit.ui.qt_PlotEffect_SG import Ui_Form as Ui_SG_Form -from crikit.ui.qt_PlotEffect_Calibrate import Ui_Form as Ui_Calibrate_Form - - -from crikit.cri.algorithms.kk import kkrelation as _kk -from crikit.preprocess.algorithms.als import als_baseline_redux as _als - -from crikit.data.frequency import (calib_pix_wn as _calib_pix_wn) - -from crikit.utils.general import find_nearest as _find_nearest - -class widgetNothing(_QWidget): - """ - Plugin widget for PlotEffect subUI. - - This plugin does nothing (i.e., it is a template and for demonstration \ - purposes). - - """ - - changed = _pyqtSignal() - - def __init__(self, parent = None): - super(widgetNothing, self).__init__(parent) ### EDIT ### - self.ui = Ui_Nothing_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - def fcn(self, data_in): - return data_in - -class widgetCalibrate(_QWidget): - """ - This plugin widget provides calibration functionality. - - """ - DEFAULT_N_PIX = 1600 - DEFAULT_CTR_WL = 730.0 - DEFAULT_CTR_WL0 = 730.0 - DEFAULT_A_VEC = (-0.167740721307557, 863.8736708961577) - DEFAULT_PROBE = 771.461 - - DEFAULT_MEAS = 1004.0 - - CALIB_DICT = {'n_pix' : DEFAULT_N_PIX, 'ctr_wl' : DEFAULT_CTR_WL, - 'ctr_wl0' : DEFAULT_CTR_WL0, 'a_vec' : DEFAULT_A_VEC, - 'probe' : DEFAULT_PROBE} - - changed = _pyqtSignal() - - def __init__(self, calib_dict=None, parent = None): - super(widgetCalibrate, self).__init__(parent) ### EDIT ### - self.ui = Ui_Calibrate_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - if calib_dict is None: - self.calib_dict = self.CALIB_DICT - else: - self.calib_dict = calib_dict - if isinstance(self.calib_dict['a_vec'], tuple): - self.calib_dict['a_vec'] = list(self.calib_dict['a_vec']) - - self.new_calib_dict = _copy.deepcopy(self.calib_dict) - - self.updateUI() - self.WN, _ = _calib_pix_wn(self.calib_dict) - self.WN_2, _ = _calib_pix_wn(self.new_calib_dict) - -# self.WN, self.WL, _ = _make_freq_vector(self.calib_dict) -# self.WN_2, self.WL_2, _ = _make_freq_vector(self.new_calib_dict) - - self.ui.spinBoxMeas.setValue(self.DEFAULT_MEAS) - self.ui.spinBoxCorrect.setValue(self.DEFAULT_MEAS) - - self.meas = self.DEFAULT_MEAS - self.correct = self.DEFAULT_MEAS - - self.ui.spinBoxCorrect.editingFinished.connect(self.calcCalibDict) - self.ui.spinBoxMeas.editingFinished.connect(self.calcCalibDict) - - def fcn(self, data_in): - """ - Performs the KK. - - Parameters - ---------- - data : list - data[0] : Wavenumber vector - data[1] : NRB spectrum(a) - data[2] : CARS spectrum(a) - - Returns - ------- - out : np.array - Imaginary component the of KK-retrieved spectrum(a) - - See also - -------- - crikit.process.phase_retr, crikit.process.maths.kk - - """ - if data_in.ndim == 1: - spl = _UnivariateSpline(self.WN_2, data_in, s=0, ext=0) - output = spl(self.WN) - elif data_in.ndim == 2: - output = _np.zeros(data_in.shape) - for num, spect in enumerate(data_in): - spl = _UnivariateSpline(self.WN_2, spect, s=0, ext=0) - output[num,:] = spl(self.WN) - return output - #return data_in - - def calcCalibDict(self): - """ - (Re)-Calculate calibration dictionary components and recalculate \ - wavenumber/wavelength vector - """ - self.meas = self.ui.spinBoxMeas.value() - self.correct = self.ui.spinBoxCorrect.value() - - delta_lambda = 1/(((self.correct)/1e7) + 1/self.calib_dict['probe']) - \ - 1/(((self.meas)/1e7) + 1/self.calib_dict['probe']) - - self.new_calib_dict['a_vec'][1] = self.calib_dict['a_vec'][1] + delta_lambda - - self.WN_2, _ = _calib_pix_wn(self.new_calib_dict) - - self.updateUI() - self.changed.emit() - - def updateUI(self): - # Set calibration values - - self.ui.spinBoxNPix.setValue(self.calib_dict['n_pix']) - self.ui.spinBoxNPix_2.setValue(self.new_calib_dict['n_pix']) - - self.ui.spinBoxCenterWL.setValue(self.calib_dict['ctr_wl']) - self.ui.spinBoxCenterWL_2.setValue(self.new_calib_dict['ctr_wl']) - - self.ui.spinBoxCalibWL.setValue(self.calib_dict['ctr_wl0']) - self.ui.spinBoxCalibWL_2.setValue(self.new_calib_dict['ctr_wl0']) - - self.ui.spinBoxSlope.setValue(self.calib_dict['a_vec'][0]) - self.ui.spinBoxSlope_2.setValue(self.new_calib_dict['a_vec'][0]) - - self.ui.spinBoxIntercept.setValue(self.calib_dict['a_vec'][1]) - self.ui.spinBoxIntercept_2.setValue(self.new_calib_dict['a_vec'][1]) - - self.ui.spinBoxProbeWL.setValue(self.calib_dict['probe']) - self.ui.spinBoxProbeWL_2.setValue(self.new_calib_dict['probe']) - - - -class widgetKK(_QWidget): - """ - Plugin widget for PlotEffect subUI. - - This plugin performs the Kramers-Kronig (KK) relation phase retrieval. - - Attributes - ---------- - nrb_norm : bool - Normalize by the NRB flag - - cars_bias : (int, float) - Constant added to the input CARS spectrum(a) - - nrb_bias : (int, float) - Constant added to the input NRB spectrum(a) - - phaselin : (int, float) - Constant phase correction to the retrieved phase - - phasesig1 : (int, float) - For sigmoidal phase correction, the is the starting phase - - phasesig2 : (int, float) - For sigmoidal phase correction, the is the ending phase - - sigrate : (int, float) - For sigmoidal phase correction, this is the rate of change from \ - phasesig1 to phasesig2 - - pad_factor : int - Padding factor to use with the KK algorithm - - phase_type : str - Global phase addition type: 'linear' or 'sigmoidal' - - - Methods - --------- - fcn : Performs the KK - - Signals : - changed : a value in the UI has changed - - """ - - changed = _pyqtSignal() - - NRB_NORM = True - PHASE_TYPE = 'Linear' - - CARS_BIAS = 0 - NRB_BIAS = 0 - PHASELIN = 0 - - PHASESIG1 = 0 - PHASESIG2 = 0 - SIGRATE = 1 - - PADFACTOR = 1 - - def __init__(self, parent = None): - super(widgetKK, self).__init__(parent) ### EDIT ### - self.ui = Ui_KK_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - self.setupKK() - - def setupKK(self): - - self.ui.checkBoxNRBNorm.setChecked(self.NRB_NORM) - self.nrb_norm = self.NRB_NORM - - self.ui.spinBoxCARSBias.setValue(self.CARS_BIAS) - self.ui.sliderCARSBias.setValue(self.CARS_BIAS) - self.cars_bias = self.CARS_BIAS - - self.ui.spinBoxNRBBias.setValue(self.NRB_BIAS) - self.ui.sliderNRBBias.setValue(self.NRB_BIAS) - self.nrb_bias = self.NRB_BIAS - - self.ui.spinBoxPhaseLin.setValue(self.PHASELIN) - self.ui.sliderPhaseLin.setValue(self.PHASELIN) - self.phaselin = self.PHASELIN - - self.ui.spinBoxSigPhase1.setValue(self.PHASESIG1) - self.ui.sliderSigPhase1.setValue(self.PHASESIG1) - self.phasesig1 = self.PHASESIG1 - - self.ui.spinBoxSigPhase2.setValue(self.PHASESIG2) - self.ui.sliderSigPhase2.setValue(self.PHASESIG2) - self.phasesig2 = self.PHASESIG2 - - self.ui.spinBoxSigRate.setValue(self.SIGRATE) - self.ui.sliderSigRate.setValue(self.SIGRATE) - self.sigrate = self.SIGRATE - - self.ui.spinBoxPadFactor.setValue(self.PADFACTOR) - self.pad_factor = self.PADFACTOR - - if self.PHASE_TYPE.lower() == 'linear': - self.ui.tabWidget.setCurrentIndex(0) - self.phase_type = 'linear' - elif self.PHASE_TYPE.lower() == 'sigmoidal': - self.ui.tabWidget.setCurrentIndex(1) - self.phase_type = 'sigmoidal' - else: - self.ui.tabWidget.setCurrentIndex(0) - self.phase_type = 'linear' - - # Signals-Slots - self.ui.sliderCARSBias.valueChanged.connect(self.changeSliderCARSBiasPre) - self.ui.sliderCARSBias.sliderReleased.connect(self.changeSliderCARSBiasFinal) - self.ui.spinBoxCARSBias.valueChanged.connect(self.changeSpinBoxCARSBias) - - self.ui.sliderNRBBias.valueChanged.connect(self.changeSliderNRBBiasPre) - self.ui.sliderNRBBias.sliderReleased.connect(self.changeSliderNRBBiasFinal) - self.ui.spinBoxNRBBias.valueChanged.connect(self.changeSpinBoxNRBBias) - - self.ui.sliderPhaseLin.valueChanged.connect(self.changeSliderPhaseLinPre) - self.ui.sliderPhaseLin.sliderReleased.connect(self.changeSliderPhaseLinFinal) - self.ui.spinBoxPhaseLin.valueChanged.connect(self.changeSpinBoxPhaseLin) - - self.ui.sliderSigPhase1.valueChanged.connect(self.changeSliderSigPhase1Pre) - self.ui.sliderSigPhase1.sliderReleased.connect(self.changeSliderSigPhase1Final) - self.ui.spinBoxSigPhase1.valueChanged.connect(self.changeSpinBoxSigPhase1) - - self.ui.sliderSigPhase2.valueChanged.connect(self.changeSliderSigPhase2Pre) - self.ui.sliderSigPhase2.sliderReleased.connect(self.changeSliderSigPhase2Final) - self.ui.spinBoxSigPhase2.valueChanged.connect(self.changeSpinBoxSigPhase2) - - self.ui.sliderSigRate.valueChanged.connect(self.changeSliderSigRatePre) - self.ui.sliderSigRate.sliderReleased.connect(self.changeSliderSigRateFinal) - self.ui.spinBoxSigRate.valueChanged.connect(self.changeSpinBoxSigRate) - - self.ui.spinBoxPadFactor.valueChanged.connect(self.changeSpinBoxPadFactor) - - self.ui.checkBoxNRBNorm.clicked.connect(self.changeCheckBoxNRBNorm) - self.ui.checkBoxLockBias.clicked.connect(self.changeCheckBoxLockBias) - - self.ui.radioButtonPhaseLin.clicked.connect(self.changeRadioPhaseLin) - self.ui.radioButtonPhaseSig.clicked.connect(self.changeRadioPhaseSig) - - # Disabled sigmoidal phase correction for now - self.ui.radioButtonPhaseSig.setEnabled(False) - - self.ui.sliderNRBBias.setEnabled(False) - self.ui.spinBoxNRBBias.setEnabled(False) - self.ui.sliderCARSBias.sliderReleased.connect(self.sliderBiasLock) - self.ui.spinBoxCARSBias.valueChanged.connect(self.spinBoxBiasLock) - - - - def fcn(self, data_in): - """ - Performs the KK. - - Parameters - ---------- - data : list - data[0] : Wavenumber vector - data[1] : NRB spectrum(a) - data[2] : CARS spectrum(a) - - Returns - ------- - out : np.array - Imaginary component the of KK-retrieved spectrum(a) - - See also - -------- - crikit.process.phase_retr, crikit.process.maths.kk - - """ - assert isinstance(data_in, list), 'KK plot effect fcn requires the data input be a list with length 3: WN, NRB, CARS' - - out = _kk(data_in[1] + self.nrb_bias, data_in[2] + - self.cars_bias, phase_offset=self.phaselin*_np.pi/360, - norm_by_bg=self.nrb_norm, pad_factor=self.pad_factor) - return out.imag - - - - def changeSliderCARSBiasPre(self): - self.ui.spinBoxCARSBias.setValue(self.ui.sliderCARSBias.value()) - self.cars_bias = self.ui.sliderCARSBias.value() - self.changed.emit() - - def changeSliderCARSBiasFinal(self): - self.ui.spinBoxCARSBias.setValue(self.ui.sliderCARSBias.value()) - self.cars_bias = self.ui.sliderCARSBias.value() - self.changed.emit() - - def changeSpinBoxCARSBias(self): - self.ui.sliderCARSBias.setValue(self.ui.spinBoxCARSBias.value()) - self.cars_bias = self.ui.spinBoxCARSBias.value() - self.changed.emit() - - def changeSliderNRBBiasPre(self): - self.ui.spinBoxNRBBias.setValue(self.ui.sliderNRBBias.value()) - self.nrb_bias = self.ui.sliderNRBBias.value() - self.changed.emit() - - def changeSliderNRBBiasFinal(self): - self.ui.spinBoxNRBBias.setValue(self.ui.sliderNRBBias.value()) - self.nrb_bias = self.ui.sliderNRBBias.value() - self.changed.emit() - - def changeSpinBoxNRBBias(self): - self.ui.sliderNRBBias.setValue(self.ui.spinBoxNRBBias.value()) - self.nrb_bias = self.ui.spinBoxNRBBias.value() - self.changed.emit() - - def changeSliderPhaseLinPre(self): - self.ui.spinBoxPhaseLin.setValue(self.ui.sliderPhaseLin.value()) - self.phaselin = self.ui.sliderPhaseLin.value() - self.changed.emit() - - def changeSliderPhaseLinFinal(self): - self.ui.spinBoxPhaseLin.setValue(self.ui.sliderPhaseLin.value()) - self.phaselin = self.ui.sliderPhaseLin.value() - self.changed.emit() - - def changeSpinBoxPhaseLin(self): - self.ui.sliderPhaseLin.setValue(self.ui.spinBoxPhaseLin.value()) - self.phaselin = self.ui.spinBoxPhaseLin.value() - self.changed.emit() - - def changeSliderSigPhase1Pre(self): - self.ui.spinBoxSigPhase1.setValue(self.ui.sliderSigPhase1.value()) - self.phasesig1 = self.ui.sliderSigPhase1.value() - self.changed.emit() - - def changeSliderSigPhase1Final(self): - self.ui.spinBoxSigPhase1.setValue(self.ui.sliderSigPhase1.value()) - self.phasesig1 = self.ui.sliderSigPhase1.value() - self.changed.emit() - - def changeSpinBoxSigPhase1(self): - self.ui.sliderSigPhase1.setValue(self.ui.spinBoxSigPhase1.value()) - self.phasesig1 = self.ui.spinBoxSigPhase1.value() - self.changed.emit() - - def changeSliderSigPhase2Pre(self): - self.ui.spinBoxSigPhase2.setValue(self.ui.sliderSigPhase2.value()) - self.phasesig2 = self.ui.sliderSigPhase2.value() - self.changed.emit() - - def changeSliderSigPhase2Final(self): - self.ui.spinBoxSigPhase2.setValue(self.ui.sliderSigPhase2.value()) - self.phasesig2 = self.ui.sliderSigPhase2.value() - self.changed.emit() - - def changeSpinBoxSigPhase2(self): - self.ui.sliderSigPhase2.setValue(self.ui.spinBoxSigPhase2.value()) - self.phasesig2 = self.ui.spinBoxSigPhase2.value() - self.changed.emit() - - def changeSliderSigRatePre(self): - self.ui.spinBoxSigRate.setValue(self.ui.sliderSigRate.value()) - self.sigrate = self.ui.sliderSigRate.value() - self.changed.emit() - - def changeSliderSigRateFinal(self): - self.ui.spinBoxSigRate.setValue(self.ui.sliderSigRate.value()) - self.sigrate = self.ui.sliderSigRate.value() - self.changed.emit() - - def changeSpinBoxSigRate(self): - self.ui.sliderSigRate.setValue(self.ui.spinBoxSigRate.value()) - self.sigrate = self.ui.spinBoxSigRate.value() - self.changed.emit() - - def changeCheckBoxLockBias(self): - if self.ui.checkBoxLockBias.isChecked(): - self.ui.sliderNRBBias.setEnabled(False) - self.ui.spinBoxNRBBias.setEnabled(False) - self.ui.sliderCARSBias.sliderReleased.connect(self.sliderBiasLock) - self.ui.spinBoxCARSBias.valueChanged.connect(self.spinBoxBiasLock) - self.sliderBiasLock() - self.spinBoxBiasLock() - - else: - self.ui.sliderNRBBias.setEnabled(True) - self.ui.spinBoxNRBBias.setEnabled(True) - self.ui.sliderCARSBias.sliderReleased.disconnect(self.sliderBiasLock) - self.ui.spinBoxCARSBias.valueChanged.disconnect(self.spinBoxBiasLock) - self.changed.emit() - - def sliderBiasLock(self): - self.ui.sliderNRBBias.setValue(self.ui.sliderCARSBias.value()) - self.nrb_bias = self.ui.sliderCARSBias.value() - self.changed.emit() - - def spinBoxBiasLock(self): - self.ui.spinBoxNRBBias.setValue(self.ui.spinBoxCARSBias.value()) - self.nrb_bias = self.ui.sliderCARSBias.value() - self.changed.emit() - - def changeCheckBoxNRBNorm(self): - if self.ui.checkBoxNRBNorm.isChecked(): - self.nrb_norm = True - else: - self.nrb_norm = False - self.changed.emit() - - def changeRadioPhaseLin(self): - self.phase_type = 'linear' - self.ui.tabWidget.setCurrentIndex(0) - - def changeRadioPhaseSig(self): - self.phase_type = 'sigmoidal' - self.ui.tabWidget.setCurrentIndex(1) - - def changeSpinBoxPadFactor(self): - self.pad_factor = self.ui.spinBoxPadFactor.value() - self.changed.emit() - - - - - - - -class widgetALS(_QWidget): - """ - Plugin widget for PlotEffect subUI. - - This performs detrending with the asymmetric least squares algorithms - - Attributes - ---------- - p : float - ALS asymmetry parameter - - lam : float - ALS smoothness parameter - - redux : int - - - - Methods - --------- - fcn : Performs the Asymmetric Least Squares - - Signals: - changed : a value in the UI has changed - - Notes - ----- - Please cite the C. H. Camp Jr., et al. reference (below) if you - use this software. - - References - ---------- - [1] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, - Comparable Coherent Anti-Stokes Raman Scattering (CARS) - Spectroscopy: Correcting Errors in Phase Retrieval" - - [2] P. H. C. Eilers, "A perfect smoother," Anal. Chem. 75, - 3631-3636 (2003). - - [3] P. H. C. Eilers and H. F. M. Boelens, "Baseline correction with - asymmetric least squares smoothing," Report. October 21, 2005. - - """ - - changed = _pyqtSignal() - - P_VAL = 1e-3 # Asymmetry - LAMBDA_VAL = 1 # Smothness - REDUX = 10 # Interpolation step size (pixels) - - def __init__(self, parent = None): - super(widgetALS, self).__init__(parent) ### EDIT ### - self.ui = Ui_ALS_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.spinBoxP.setValue(self.P_VAL) - self.ui.spinBoxLambda.setValue(self.LAMBDA_VAL) - self.ui.spinBoxRedux.setValue(self.REDUX) - - self.p = self.P_VAL - self.lam = self.LAMBDA_VAL - self.redux = self.REDUX - - self.ui.spinBoxP.valueChanged.connect(self.changeP) - self.ui.spinBoxLambda.valueChanged.connect(self.changeLambda) - self.ui.spinBoxRedux.valueChanged.connect(self.changeRedux) - - - def fcn(self, data_in): - data_out = _np.zeros(data_in.shape) - - if data_in.ndim == 1: - baseline = _als(data_in, redux_factor=self.redux, - redux_full=False, - smoothness_param=self.lam, - asym_param=self.p)[0] - data_out = data_in - baseline - else: - for num, spectrum in enumerate(data_in): - baseline = _als(spectrum, redux_factor=self.redux, - redux_full=False, smoothness_param=self.lam, - asym_param=self.p, print_iteration=False)[0] - data_out[num,:] = spectrum - baseline - return data_out - - def changeP(self): - self.p = self.ui.spinBoxP.value() - self.changed.emit() - - def changeLambda(self): - self.lam = self.ui.spinBoxLambda.value() - self.changed.emit() - - def changeRedux(self): - self.redux = self.ui.spinBoxRedux.value() - self.changed.emit() - -class widgetSG(_QWidget): - """ - Plugin widget for PlotEffect subUI. - - This performs the Savitky-Golay filtering - - Attributes - ---------- - win_size : int - Window size - - order : int - Order (polynomial) - - Methods - --------- - fcn : Performs the Savitky-Golay - - Signals: - changed : a value in the UI has changed - - References - ---------- - [1] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, - Comparable Coherent Anti-Stokes Raman Scattering (CARS) - Spectroscopy: Correcting Errors in Phase Retrieval" - - """ - - changed = _pyqtSignal() - -# WIN_SIZE = 601 # Window size -# ORDER = 2 # Order - - def __init__(self, win_size=601, order=2, parent = None): - super(widgetSG, self).__init__(parent) ### EDIT ### - self.ui = Ui_SG_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.win_size = win_size - self.order = order - - # Window size must be > order - if self.win_size <= self.order: - self.win_size = self.order + 1 - - # Window size must be odd - if self.win_size%2 == 1: - pass - else: - self.win_size += 1 - - self.ui.spinBoxWinSize.setValue(self.win_size) - self.ui.spinBoxOrder.setValue(self.order) - - self.ui.spinBoxWinSize.valueChanged.connect(self.changeWinSize) - self.ui.spinBoxOrder.valueChanged.connect(self.changeOrder) - - def fcn(self, data_in): - - baseline = _sg(data_in, window_length=self.win_size, polyorder=self.order, axis=-1) - data_out = data_in - baseline - - return data_out - - def changeWinSize(self): - temp_win_size = self.ui.spinBoxWinSize.value() - if temp_win_size%2 == 1: - self.win_size = temp_win_size - else: - self.ui.spinBoxWinSize.setValue(temp_win_size+1) - self.win_size = temp_win_size+1 - self.changed.emit() - - def changeOrder(self): - self.order = self.ui.spinBoxOrder.value() - self.changed.emit() - - -if __name__ == '__main__': - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - winNothing = widgetNothing() - winNothing.show() - - winKK = widgetKK() - winKK.show() - - winALS = widgetALS() - winALS.show() - - winSG = widgetSG(win_size=3, order=3) - winSG.show() - - winCalib = widgetCalibrate() - winCalib.show() - - - app.exec_() - _sys.exit() \ No newline at end of file diff --git a/crikit/ui/dialog_AbstractFactorization.py b/crikit/ui/dialog_AbstractFactorization.py index 2765833..04cb7f8 100644 --- a/crikit/ui/dialog_AbstractFactorization.py +++ b/crikit/ui/dialog_AbstractFactorization.py @@ -33,7 +33,7 @@ class DialogAbstractFactorization(_QDialog): """ def __init__(self, parent=None): super(DialogAbstractFactorization, self).__init__(parent=parent) - + self._mpl_v1 = _mpl.__version__.split('.')[0] == 1 ## def __init__(self, parent=None): # raise NotImplementedError('This is an abstract class.') ## super(DialogAbstractFactorization, self).__init__(parent=parent) ### EDIT ### @@ -99,7 +99,8 @@ def setup(self, parent = None): for count in range(self._num_factor_visible): self.factorWins.append(_MplCanvas(subplot=211)) self.factorWins[count].ax[0].axis('Off') - self.factorWins[count].ax[1].hold('Off') + if self._mpl_v1: + self.factorWins[count].ax[1].hold('Off') self.ui.gridLayout.addWidget(self.factorWins[0],1,0) self.ui.gridLayout.addWidget(self.factorWins[1],1,1) @@ -111,11 +112,13 @@ def setup(self, parent = None): self.reconCurrent = _MplCanvas(subplot=211) self.reconCurrent.ax[0].axis('Off') - self.reconCurrent.ax[1].hold('Off') + if self._mpl_v1: + self.reconCurrent.ax[1].hold('Off') self.reconRemainder = _MplCanvas(subplot=211) self.reconRemainder.ax[0].axis('Off') - self.reconRemainder.ax[1].hold('Off') + if self._mpl_v1: + self.reconRemainder.ax[1].hold('Off') self.ui.verticalLayout_3.insertWidget(1,self.reconCurrent) diff --git a/crikit/ui/dialog_kkOptions.py b/crikit/ui/dialog_kkOptions.py index eaa3d78..51576c6 100644 --- a/crikit/ui/dialog_kkOptions.py +++ b/crikit/ui/dialog_kkOptions.py @@ -21,7 +21,7 @@ # Import from Designer-based GUI from crikit.ui.qt_KKOptions import Ui_Dialog as Ui_KKOptions -from crikit.ui.dialog_ploteffect import (DialogPlotEffectFuture as +from crikit.ui.dialog_ploteffect import (DialogPlotEffect as _DialogPlotEffect) from crikit.ui.widget_KK import (widgetKK as _widgetKK) diff --git a/crikit/ui/dialog_ploteffect.py b/crikit/ui/dialog_ploteffect.py index 050e495..34bbac2 100644 --- a/crikit/ui/dialog_ploteffect.py +++ b/crikit/ui/dialog_ploteffect.py @@ -9,6 +9,7 @@ from PyQt5.QtWidgets import (QApplication as _QApplication, QDialog as _QDialog) +from PyQt5 import QtWidgets as _QtWidgets from crikit.ui.qt_PlotEffect import Ui_Dialog as Ui_DialogPlotEffect @@ -18,7 +19,7 @@ from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas -class DialogPlotEffectFuture(_QDialog): +class DialogPlotEffect(_QDialog): """ Extensible Dialog that shows the effect of a plugin on input data. @@ -37,23 +38,30 @@ class DialogPlotEffectFuture(_QDialog): parent : QObject Parent """ + + TRANSPOSE_ARR = True - def __init__(self, data, x=None, plugin=None, parent=None): - super(DialogPlotEffectFuture, self).__init__(parent) + def __init__(self, data, x=None, plugin=None, mpl_kwargs={'width':8, 'height':2}, parent=None): + super(DialogPlotEffect, self).__init__(parent) self.ui = Ui_DialogPlotEffect() self.ui.setupUi(self) self.data = data # Setup MPL containers - self.mpl_orig = _MplCanvas(subplot=111) - self.mpl_affected = _MplCanvas(subplot=111) - + self.mpl_orig = _MplCanvas(subplot=111, **mpl_kwargs) + self.mpl_orig.fig.canvas.setMinimumSize(100,200) + self.mpl_orig.fig.canvas.setSizePolicy(_QtWidgets.QSizePolicy.Expanding, _QtWidgets.QSizePolicy.Minimum) + + self.mpl_affected = _MplCanvas(subplot=111, **mpl_kwargs) + self.mpl_affected.fig.canvas.setMinimumSize(100,200) + self.mpl_affected.fig.canvas.setSizePolicy(_QtWidgets.QSizePolicy.Expanding, _QtWidgets.QSizePolicy.Minimum) + # Show(), although not needed, enables mpl-tight_layout # to work later on self.show() - self.ui.verticalLayout.insertWidget(1, self.mpl_orig) + self.ui.verticalLayout.insertWidget(1, self.mpl_orig, stretch=1) self.ui.verticalLayout.insertWidget(1, self.mpl_orig.toolbar) self.ui.verticalLayout.insertWidget(3, self.mpl_affected) @@ -71,23 +79,8 @@ def __init__(self, data, x=None, plugin=None, parent=None): self.x = _np.linspace(0,data.shape[0],self.data.shape[0]) else: self.x = x - - # If data is a list (assumed to be a list of ndarrays), - # plot each item in list - if isinstance(data, _np.ndarray): - try: - self.mpl_orig.ax.plot(self.x,data) - except: - self.mpl_orig.ax.plot(self.x,data.T) - elif isinstance(data, list): - for d in data: - try: - self.mpl_orig.ax.plot(self.x,d) - except: - self.mpl_orig.ax.plot(self.x,d.T) - - - self.plot_labels() + + self.make_orig_plots(self.data) if self.plugin is not None: self.ui.verticalLayout.insertWidget(8, plugin) @@ -100,14 +93,69 @@ def __init__(self, data, x=None, plugin=None, parent=None): self.ui.pushButtonOk.clicked.connect(self.accept) self.ui.pushButtonCancel.clicked.connect(self.reject) + def make_orig_plots(self, data, lw=1, ls='-'): + """ + + """ + self.make_plots(self.mpl_orig, data, lw=lw, ls=ls) + + def make_affected_plots(self, data, lw=1, ls='-'): + """ + + """ + self.make_plots(self.mpl_affected, data, lw=lw, ls=ls) + + def make_plots(self, canvas, data, lw=1, ls='-'): + """ + + """ + # If data is a list (assumed to be a list of ndarrays), + # plot each item in list + if isinstance(data, _np.ndarray): + # TRANSPOSE ARRAY in case of plt.plot(data) -- in a for-loop, this is opposite + if self.TRANSPOSE_ARR: + if data.ndim > 1: + for num, d in enumerate(data): + canvas.ax.plot(self.x,d, lw=lw, ls=ls, color='C{}'.format(num % 10)) + else: + canvas.ax.plot(self.x,data, lw=lw, ls=ls, color='C0') + else: + if data.ndim > 1: + for num, d in enumerate(data.T): + canvas.ax.plot(self.x,d, lw=lw, color='C{}'.format(num % 10)) + else: + canvas.ax.plot(self.x,data, lw=lw, color='C0') + + elif isinstance(data, list): + for d in data: + if d.ndim > 1: + if self.TRANSPOSE_ARR: + for num, d2 in enumerate(d): + canvas.ax.plot(self.x, d2, lw=lw, ls=ls, color='C{}'.format(num % 10)) + else: + for num, d2 in enumerate(d.T): + canvas.ax.plot(self.x, d2, lw=lw, ls=ls, color='C{}'.format(num % 10)) + else: + canvas.ax.plot(self.x, d, lw=lw, ls=ls, color='C0') + + self.plot_labels() + try: + canvas.fig.tight_layout() + except: + print('Tight layout failed (dialog_ploteffect') + + @staticmethod - def dialogPlotEffect(data, x = None, plugin=None, parent = None): + def dialogPlotEffect(data, x=None, plugin=None, parent=None): """ Static method that is actually called """ - dialog = DialogPlotEffectFuture(data, x=x, plugin=plugin, + dialog = DialogPlotEffect(data, x=x, plugin=plugin, parent=parent) - + # Resize to fit plugin + if dialog.width() < dialog.plugin.width(): + dialog.resize(int(dialog.plugin.width()*1.1), dialog.height()) + result = dialog.exec_() # 1 = Accepted, 0 = Rejected/Canceled if result == 1: @@ -144,28 +192,11 @@ def widget_changed(self): self.mpl_orig.ax.clear() + self.make_orig_plots(self.data) - if isinstance(self.data, _np.ndarray): - try: - self.mpl_orig.ax.plot(self.x,self.data) - except: - self.mpl_orig.ax.plot(self.x,self.data.T) - - # If data is a list (assumed to be a list of ndarrays), - # plot each item in list - elif isinstance(self.data, list): - for d in self.data: - try: - self.mpl_orig.ax.plot(self.x,d) - except: - self.mpl_orig.ax.plot(self.x,d.T) - if orig_data_addon is not None: - try: - self.mpl_orig.ax.plot(self.x,orig_data_addon, lw=2) - except: - self.mpl_orig.ax.plot(self.x,orig_data_addon.T, lw=2) - + self.make_orig_plots(orig_data_addon, lw=0.75, ls=':') + # If there already exists an affected plot, keep those # axis limits upon re-plotting if len(self.mpl_affected.ax.lines) > 0: @@ -182,15 +213,7 @@ def widget_changed(self): self.mpl_affected.toolbar.setVisible(True) self.mpl_affected.ax.clear() - try: - self.mpl_affected.ax.plot(self.x,affected_data) - except: - self.mpl_affected.ax.plot(self.x,affected_data.T) - - self.plot_labels() # Update x-,y-, and title-labels on plots - - self.mpl_orig.fig.tight_layout() - self.mpl_affected.fig.tight_layout() + self.make_affected_plots(affected_data) # Reset axis limits to previous setting before re-plotting if lim_orig is not None: @@ -274,47 +297,48 @@ def fcn(self, data_in): CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) NRB = 0*WN + .055 - CARS = _np.dot(_np.ones((5,1)),CARS[None,:]) + CARS = _np.dot(_np.arange(1,4)[:,None],CARS[None,:]) - NRB_LEFT = 20e3*_np.exp(-(WN)**2/(1000**2)) + 500 - NRB_RIGHT = 6e3*_np.exp(-(WN-2500)**2/(400**2)) + 500 + # NRB_LEFT = 20e3*_np.exp(-(WN)**2/(1000**2)) + 500 + # NRB_RIGHT = 6e3*_np.exp(-(WN-2500)**2/(400**2)) + 500 - NRB_LEFT[WN<500] *= 0 - NRB_LEFT[WN<500] += 1e-6 - NRB_RIGHT[WN<500] *= 0 - NRB_RIGHT[WN<500] += 1e-6 + # NRB_LEFT[WN<500] *= 0 + # NRB_LEFT[WN<500] += 1e-6 + # NRB_RIGHT[WN<500] *= 0 + # NRB_RIGHT[WN<500] += 1e-6 - from crikit.cri.merge_nrbs import MergeNRBs as _MergeNRBs + # from crikit.cri.merge_nrbs import MergeNRBs as _MergeNRBs from crikit.utils.general import find_nearest as _find_nearest - NRB2 = _MergeNRBs(nrb_left=NRB_LEFT, nrb_right=NRB_RIGHT, - pix=_find_nearest(WN, 1885.0)[1], - left_side_scale=False).calculate() + # NRB2 = _MergeNRBs(nrb_left=NRB_LEFT, nrb_right=NRB_RIGHT, + # pix=_find_nearest(WN, 1885.0)[1], + # left_side_scale=False).calculate() - CARS2 = _np.abs(500*(1/(1000-WN-1j*20) + 1/(2700-WN-1j*20)) + NRB2**0.5)**2 - CARS2 = _np.dot(_np.ones((10,1), dtype=_np.double),CARS2[None,:]) + # CARS2 = _np.abs(500*(1/(1000-WN-1j*20) + 1/(2700-WN-1j*20)) + NRB2**0.5)**2 + # CARS2 = _np.dot(_np.ones((3,1), dtype=_np.double),CARS2[None,:]) # # Demo # plugin = widgetDemoPlotEffectPlugin() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, +# winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, # plugin=plugin) # if winPlotEffect is not None: # print(winPlotEffect.parameters) # ## # ALS -## from crikit.ui.widget_ALS import widgetALS as _widgetALS -## -## plugin = _widgetALS() -## winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -## plugin=plugin) -## if winPlotEffect is not None: -## print(winPlotEffect.parameters) + from crikit.ui.widget_ALS import widgetALS as _widgetALS + + rng = _np.arange(*_find_nearest(WN, [500, 3800])[1]) + plugin = _widgetALS(x=WN, rng=rng) + winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, + plugin=plugin) + if winPlotEffect is not None: + print(winPlotEffect.parameters) # # # ArPLS # from crikit.ui.widget_ArPLS import widgetArPLS as _widgetArPLS # plugin = _widgetArPLS() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, +# winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, # plugin=plugin) # if winPlotEffect is not None: # print(winPlotEffect.parameters) @@ -323,7 +347,7 @@ def fcn(self, data_in): # from crikit.ui.widget_DeTrending import (widgetDeTrending as # _widgetDeTrending) # plugin = _widgetDeTrending() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, +# winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, # plugin=plugin) # if winPlotEffect is not None: # print(winPlotEffect.parameters) @@ -331,7 +355,7 @@ def fcn(self, data_in): # # SG # from crikit.ui.widget_SG import (widgetSG as _widgetSG) # plugin = _widgetSG() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, +# winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, # plugin=plugin) # if winPlotEffect is not None: # print(winPlotEffect.parameters) @@ -339,7 +363,7 @@ def fcn(self, data_in): # # KK # from crikit.ui.widget_KK import (widgetKK as _widgetKK) # plugin = _widgetKK() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect([NRB,CARS], x=WN, +# winPlotEffect = DialogPlotEffect.dialogPlotEffect([NRB,CARS], x=WN, # plugin=plugin) # if winPlotEffect is not None: # print(winPlotEffect.parameters) @@ -348,19 +372,19 @@ def fcn(self, data_in): # from crikit.ui.widget_Calibrate import (widgetCalibrate as # _widgetCalibrate) # plugin = _widgetCalibrate(calib_dict) -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, +# winPlotEffect = DialogPlotEffect.dialogPlotEffect(CARS, x=WN, # plugin=plugin) # if winPlotEffect is not None: # print(winPlotEffect.parameters) # Merge NRBs - from crikit.ui.widget_mergeNRBs import (widgetMergeNRBs as - _widgetMergeNRBs) - plugin = _widgetMergeNRBs(WN, NRB_LEFT, NRB_RIGHT) - winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS2, x=WN, - plugin=plugin) - if winPlotEffect is not None: - print(winPlotEffect.parameters) + # from crikit.ui.widget_mergeNRBs import (widgetMergeNRBs as + # _widgetMergeNRBs) + # plugin = _widgetMergeNRBs(WN, NRB_LEFT, NRB_RIGHT) + # winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS2, x=WN, + # plugin=plugin) + # if winPlotEffect is not None: + # print(winPlotEffect.parameters) diff --git a/crikit/ui/dialog_save.py b/crikit/ui/dialog_save.py index d83a8ac..7db3790 100644 --- a/crikit/ui/dialog_save.py +++ b/crikit/ui/dialog_save.py @@ -217,7 +217,7 @@ def dialogSave(current_filename=None, current_path=None, suffix : str Suffix to append to _dataset_name based on processing steps - NOTE : save_ parameters supercede current_ parameters + NOTE : save* parameters supercede current* parameters Returns ---------- diff --git a/crikit/ui/main_Mosaic.py b/crikit/ui/main_Mosaic.py new file mode 100644 index 0000000..8d4c9dc --- /dev/null +++ b/crikit/ui/main_Mosaic.py @@ -0,0 +1,695 @@ +""" +MainWindow program that allows construction of stitched images from +multiple dataset +""" + +import sys as _sys +import os as _os +import copy as _copy + +from collections import OrderedDict + +import h5py +import numpy as _np + +from PyQt5 import QtWidgets as _QtWidgets +from PyQt5.QtWidgets import (QApplication as _QApplication, + QMainWindow as _QMainWindow, + QWidget as _QWidget, + QListWidget as _QListWidget, + QMessageBox as _QMessageBox) + +import PyQt5.QtCore as _QtCore +from PyQt5.QtCore import (pyqtSignal as _pyqtSignal) + +from crikit.ui.qt_Mosaic import Ui_MainWindow + +from crikit.data.frequency import calib_pix_wl, calib_pix_wn +from crikit.data.mosaic import Mosaic +from crikit.ui.dialog_save import DialogSave + +from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas + +import lazy5 +from lazy5.utils import FidOrFile, fullpath +from lazy5.ui.QtHdfLoad import HdfLoad + + +class DnDReorderListWidget(_QListWidget): + """ List widget with drag-n-drop reordering """ + + reordered = _pyqtSignal() + + def __init__(self, parent): + super(DnDReorderListWidget, self).__init__(parent) + + self.setAcceptDrops(True) + self.setEditTriggers(_QtWidgets.QAbstractItemView.NoEditTriggers) + self.setDragEnabled(True) + self.setDragDropMode(_QtWidgets.QAbstractItemView.InternalMove) + self.setDefaultDropAction(_QtCore.Qt.MoveAction) + self.setAlternatingRowColors(False) + self.setSelectionMode(_QtWidgets.QAbstractItemView.SingleSelection) + self.setObjectName("listWidgetDatasets") + + item = _QtWidgets.QListWidgetItem() + self.addItem(item) + item = _QtWidgets.QListWidgetItem() + self.addItem(item) + + self.setSortingEnabled(False) + item = self.item(0) + item.setText('A') + item = self.item(1) + item.setText('B') + + def dropEvent(self, e): + super().dropEvent(e) + self.reordered.emit() + +class MainWindowMosaic(_QMainWindow): + """ + + """ + + frequency_calib = {'Slope':-0.165955456, 'Intercept':832.5510120093941, + 'Probe': 771.461, 'Calib_WL': 700.0, 'Center_WL': 700.0} + + config = {'allow_duplicates':False} + + def __init__(self, parent=None): + super(MainWindowMosaic, self).__init__(parent) + self.ui = Ui_MainWindow() + self.ui.setupUi(self) + self.setupListWidget() + + self.ui.spinBoxIntercept.setValue(self.frequency_calib['Intercept']) + self.ui.spinBoxSlope.setValue(self.frequency_calib['Slope']) + self.ui.spinBoxProbe.setValue(self.frequency_calib['Probe']) + self.ui.spinBoxCalibWL.setValue(self.frequency_calib['Calib_WL']) + self.ui.spinBoxCenterWL.setValue(self.frequency_calib['Center_WL']) + + # Internal data + self.init_internals() + + self.mpl = _MplCanvas(parent=self) + self.ui.verticalLayoutMPL.insertWidget(0, self.mpl, _QtCore.Qt.AlignCenter) + self.ui.verticalLayoutMPL.insertWidget(0,self.mpl.toolbar, _QtCore.Qt.AlignHCenter) + + # SIGNALS AND SLOTS + self.ui.actionAddFromHDF.triggered.connect(self.addDataset) + self.ui.pushButtonAddDataset.pressed.connect(self.addDataset) + + self.ui.actionSaveToHDF5.triggered.connect(self.save) + + self.ui.sliderFreq.valueChanged.connect(self.updateSlider) + self.ui.sliderFreq.sliderReleased.connect(self.updateMosaicImage) + + self.ui.lineEditPix.editingFinished.connect(self.lineEditPixChange) + + self.ui.spinBoxMRows.editingFinished.connect(self.updateParams) + self.ui.spinBoxNCols.editingFinished.connect(self.updateParams) + self.ui.comboBoxRowCol.currentIndexChanged.connect(self.updateParams) + self.ui.checkBoxFlipH.stateChanged.connect(self.updateParams) + self.ui.checkBoxFlipV.stateChanged.connect(self.updateParams) + self.ui.checkBoxTranspose.stateChanged.connect(self.updateParams) + self.ui.spinBoxStartRow.editingFinished.connect(self.updateParams) + self.ui.spinBoxStartCol.editingFinished.connect(self.updateParams) + self.ui.spinBoxEndRow.editingFinished.connect(self.updateParams) + self.ui.spinBoxEndCol.editingFinished.connect(self.updateParams) + + # ! Currently, cannot save compress in HDF5 + self.ui.checkBoxCompress.setEnabled(False) + # self.ui.checkBoxCompress.stateChanged.connect(self.updateParams) + + self.ui.spinBoxSlope.editingFinished.connect(self.updateFrequency) + self.ui.spinBoxIntercept.editingFinished.connect(self.updateFrequency) + self.ui.spinBoxProbe.editingFinished.connect(self.updateFrequency) + self.ui.spinBoxCalibWL.editingFinished.connect(self.updateFrequency) + self.ui.spinBoxCenterWL.editingFinished.connect(self.updateFrequency) + + # self.ui.spinBoxXStepSize.editingFinished.connect(self.updateSpace) + # self.ui.spinBoxYStepSize.editingFinished.connect(self.updateSpace) + + self.ui.pushButtonMoveUp.pressed.connect(self.promote_demote_list_item) + self.ui.pushButtonMoveDown.pressed.connect(self.promote_demote_list_item) + self.ui.pushButtonDeleteDataset.pressed.connect(self.deleteDataset) + + self.ui.listWidgetDatasets.reordered.connect(self.list_reordered) + + # Close event + self.ui.closeEvent = self.closeEvent + self.ui.actionExit.triggered.connect(self.closeEvent) + + def setupListWidget(self): + + self.ui.listWidgetDatasets = DnDReorderListWidget(parent=self.ui.frame) + self.ui.verticalLayout_4.insertWidget(2, self.ui.listWidgetDatasets) + + def deleteDataset(self): + if self.data._data: + row = self.ui.listWidgetDatasets.currentRow() + + if row < 0: + # print('No selection') + pass + else: + # print('Current row: {}'.format(row)) + + it = self.ui.listWidgetDatasets.takeItem(row) + out = self.data_list.pop(row) + out = self.data._data.pop(row) + out = self.h5dlist.pop(row) + out.file.close() + + if self.data.size > 0: + self.list_reordered() + else: + self.init_internals() + self.mpl.ax.clear() + self.mpl.draw() + + def promote_demote_list_item(self): + if self.data._data: + sndr = self.sender() + row = self.ui.listWidgetDatasets.currentRow() + isup = None + + if sndr == self.ui.pushButtonMoveUp: + isup = True + elif sndr == self.ui.pushButtonMoveDown: + isup = False + + if row < 0: + # print('No selection') + pass + else: + # print('Current row: {}'.format(row)) + pass + if isup & (row == 0): + # print('Can\'t promote first') + pass + elif (isup == False) & (row + 1 == self.ui.listWidgetDatasets.count()): + # print('Can\'t demote last') + pass + elif row < 0: + # print('Can\'t promote/demote no selection') + pass + elif isup: + # print('Promoting') + it = self.ui.listWidgetDatasets.takeItem(row) + self.ui.listWidgetDatasets.insertItem(row - 1, it) + self.list_reordered() + elif not isup: + # print('Demoting') + it = self.ui.listWidgetDatasets.takeItem(row) + self.ui.listWidgetDatasets.insertItem(row + 1, it) + self.list_reordered() + + def list_reordered(self): + if self.data._data: + if self.data.size >= 1: + dset_list = [] + for num in range(self.ui.listWidgetDatasets.count()): + dset_list.append(self.ui.listWidgetDatasets.item(num).text().split(' : ')) + + new_order = [] + for q in self.data_list: + new_order.append(dset_list.index(q)) + + assert len(new_order) == self.data.size + assert len(new_order) == _np.unique(new_order).size + + self.data_list = [self.data_list[idx] for idx in new_order] + self.data._data = [self.data._data[idx] for idx in new_order] + self.h5dlist = [self.h5dlist[idx] for idx in new_order] + self.updateMosaicImage() + + else: + pass + + def init_internals(self): + """ Initialize internal variables """ + self.data = Mosaic() + self.data_list = [] # List of list [pth, fname, dsetname] + self.h5dlist = [] # List of dataset pointers + + self.pix = None + self.wl = None + self.freq = None + + self.last_path = None + self.last_fname = None + self.last_dsetname = None + + self.imported_calib_vec = None + self.imported_spatial_vec = None + + def lineEditPixChange(self): + """ + Frequency manually entered in frequency-slider-display + """ + + freq_in = int(float(self.ui.lineEditPix.text())) + + max_freq = self.ui.sliderFreq.maximum() + min_freq = self.ui.sliderFreq.minimum() + + if freq_in > max_freq: + freq_in = max_freq + elif freq_in < min_freq: + freq_in = min_freq + else: + pass + + self.ui.sliderFreq.setValue(freq_in) + + def updateSlider(self): + idx = self.ui.sliderFreq.value() + self.ui.lineEditPix.setText(str(idx)) + + if self.freq is not None: + self.ui.lineEditFreq.setText(str(self.freq[idx])) + + # In case incremented by the arrow buttons + if not self.ui.sliderFreq.isSliderDown(): + self.updateMosaicImage() + + def addDataset(self): + if (self.last_path is None) | (self.last_fname is None) | (self.last_dsetname is None): + first_dset = True + to_open = HdfLoad.getFileDataSets(parent=self) + else: + first_dset = False + to_open = HdfLoad.getFileDataSets(pth=_os.path.join(self.last_path, self.last_fname), + parent=self) + + if to_open is not None: + temp_last_path, temp_last_fname, _ = to_open + + # Since to_open's dsets will be lists, this is an unraveled version + to_import = [[temp_last_path, temp_last_fname, q] for q in to_open[-1]] + to_import2 = [] # Duplicates removed if NOT allowing duplicates + + for q in to_import: + if not self.config['allow_duplicates']: + if self.is_duplicate_import([q[0], q[1], q[2]]): + msg = _QMessageBox(self) + msg.setIcon(_QMessageBox.Critical) + str1 = 'Cannot import duplicate image:\n\n' + str2 = '{} : {} : {}\n\n'.format(*q) + str3 = '\n\nNot importing this dataset' + msg.setText(str1 + str2 + str3) + msg.setWindowTitle('Duplicate Image Found.') + msg.setStandardButtons(_QMessageBox.Ok) + msg.setDefaultButton(_QMessageBox.Ok) + out = msg.exec() + else: + to_import2.append(q) + + else: + to_import2.append(q) + + for q in to_import2: + fof = FidOrFile(fullpath(pth=q[0], filename=q[1])) + if fof.fid[q[-1]].ndim != 3: + msg = _QMessageBox(self) + msg.setIcon(_QMessageBox.Critical) + str1 = 'Dataset is not 3D:\n\n' + str2 = '{} : {} : {}'.format(*q) + str3 = '\n\nNot importing this dataset' + msg.setText(str1 + str2 + str3) + msg.setWindowTitle('Cannot Load Non-3D Datasets.') + msg.setStandardButtons(_QMessageBox.Ok) + msg.setDefaultButton(_QMessageBox.Ok) + out = msg.exec() + fof.fid.close() + else: + self.h5dlist.append(fof.fid[q[-1]]) + self.data.append(fof.fid[q[-1]]) + self.last_path = q[0] + self.last_fname = q[1] + self.last_dsetname = q[2] + self.data_list.append(q) + + if first_dset: + flen = self.data.unitshape_orig[-1] + self.ui.sliderFreq.setMinimum(0) + self.ui.sliderFreq.setMaximum(flen-1) + self.ui.sliderFreq.setValue(0) + + self.pix = _np.arange(flen) + calib_vec = self.check_for_spectral_calib(fof.fid[q[-1]]) + self.check_for_spatial_calib(fof.fid[q[-1]]) + + self.updateFrequency(calib_vec) + first_dset = False + + self.updateDatasets() + + def check_for_spatial_calib(self, dset): + """ See if dataset has spatial calibration meta data """ + if not isinstance(dset, h5py.Dataset): + return None + if not hasattr(dset, 'attrs'): + return None + + spatial_vec = [] # X, Y + + attrs_dict = lazy5.inspect.get_attrs_dset(dset.file, dset.name) + list_of_keys = list(attrs_dict) + + ct = 0 + temp = [] + to_check = ['Raster.Fast.StepSize', 'Raster.Slow.StepSize'] # X, Y + for num, tc in enumerate(to_check): + if list_of_keys.count(tc) > 0: + ct += 1 + temp.append(attrs_dict[tc]) + if ct == len(to_check): + print('Has StepSize info (New)') + spatial_vec = temp + else: + ct = 0 + temp = [] + to_check = ['RasterScanParams.FastAxisStepSize', 'RasterScanParams.SlowAxisStepSize'] # X, Y + for num, tc in enumerate(to_check): + if list_of_keys.count(tc) > 0: + ct += 1 + temp.append(attrs_dict[tc]) + if ct == len(to_check): + print('Has StepSize info (Old)') + spatial_vec = temp + else: + ct = 0 + temp = [] + to_check = ['Raster.Fast.Start', 'Raster.Fast.Stop', 'Raster.Fast.Steps', + 'Raster.Slow.Start', 'Raster.Slow.Stop', 'Raster.Slow.Steps'] + for num, tc in enumerate(to_check): + if list_of_keys.count(tc) > 0: + ct += 1 + temp.append(attrs_dict[tc]) + if ct == len(to_check): + print('Has Start-Stop-Steps info (New)') + x_stepsize = (temp[1] - temp[0])/(temp[2]-1) + y_stepsize = (temp[4] - temp[3])/(temp[5]-1) + spatial_vec = [x_stepsize, y_stepsize] + else: + ct = 0 + temp = [] + to_check = ['RasterScanParams.FastAxisStart', 'RasterScanParams.FastAxisStop', + 'RasterScanParams.FastAxisSteps', + 'RasterScanParams.SlowAxisStart', 'RasterScanParams.SlowAxisStop', + 'RasterScanParams.SlowAxisSteps'] + for num, tc in enumerate(to_check): + if list_of_keys.count(tc) > 0: + ct += 1 + temp.append(attrs_dict[tc]) + if ct == len(to_check): + print('Has Start-Stop-Steps info (Old)') + x_stepsize = (temp[1] - temp[0])/(temp[2]-1) + y_stepsize = (temp[4] - temp[3])/(temp[5]-1) + spatial_vec = [x_stepsize, y_stepsize] + + if spatial_vec: + self.imported_spatial_vec = spatial_vec + self.ui.checkBoxSpaceFromData.setChecked(True) + self.ui.spinBoxXStepSize.setValue(spatial_vec[0]) + self.ui.spinBoxYStepSize.setValue(spatial_vec[1]) + + def check_for_spectral_calib(self, dset): + """ See if dataset has spectral calibration meta data """ + if not isinstance(dset, h5py.Dataset): + return None + if not hasattr(dset, 'attrs'): + return None + + calib_vec = [] + + attrs_dict = lazy5.inspect.get_attrs_dset(dset.file, dset.name) + list_of_keys = list(attrs_dict) + + ct = 0 + temp = [] + to_check = ['Calib.a_vec', 'Calib.ctr_wl', 'Calib.ctr_wl0', 'Calib.n_pix', + 'Calib.probe'] + for num, tc in enumerate(to_check): + if list_of_keys.count(tc) > 0: + ct += 1 + temp.append(attrs_dict[tc]) + if ct == len(to_check): + print('Has Calib series') + calib_vec = temp + else: + ct = 0 + temp = [] + to_check = ['Spectro.Avec', 'Spectro.CurrentWavelength', 'Spectro.CalibWavelength', + 'Spectro.SpectralPixels', 'Spectro.ProbeWavelength'] + for num, tc in enumerate(to_check): + if list_of_keys.count(tc) > 0: + ct += 1 + temp.append(attrs_dict[tc]) + if ct == len(to_check): + print('Has Spectro series') + calib_vec = temp + if calib_vec: + self.ui.checkBoxSpectFromData.setChecked(True) + return calib_vec + + def is_duplicate_import(self, to_open): + if self.data._data: + return self.data_list.count(to_open) > 0 + else: + return False + + def updateFrequency(self, calib_vec=None): + if self.pix is not None: + if calib_vec is None: + probe = self.ui.spinBoxProbe.value() * 1e-9 + intercept = self.ui.spinBoxIntercept.value() * 1e-9 + slope = self.ui.spinBoxSlope.value() * 1e-9 + ctr_wl = self.ui.spinBoxCenterWL.value() * 1e-9 + calib_wl = self.ui.spinBoxCalibWL.value() * 1e-9 + + self.frequency_calib['Probe'] = probe + self.frequency_calib['Intercept'] = intercept + self.frequency_calib['Slope'] = slope + self.frequency_calib['Center_WL'] = ctr_wl + self.frequency_calib['Calib_WL'] = calib_wl + + self.wl = slope*self.pix + intercept + (ctr_wl - calib_wl) + + if probe != 0.0: + self.freq = 0.01 / self.wl - 0.01 / probe + else: + self.freq = 0.01 / self.wl + else: + a_vec = calib_vec[0] + if len(a_vec) == 2: + slope = a_vec[0] * 1e-9 + intercept = a_vec[1] * 1e-9 + else: # Linearizes higher order polynomial + a_vec = _np.polyfit(self.pix, _np.polyval(a_vec, self.pix), 1) + slope = a_vec[0] * 1e-9 + intercept = a_vec[1] * 1e-9 + + ctr_wl = calib_vec[1] * 1e-9 + calib_wl = calib_vec[2] * 1e-9 + local_pix = calib_vec[3] + probe = calib_vec[4] * 1e-9 + + self.ui.spinBoxProbe.setValue(probe * 1e9) + self.ui.spinBoxIntercept.setValue(intercept * 1e9) + self.ui.spinBoxSlope.setValue(slope * 1e9) + self.ui.spinBoxCenterWL.setValue(ctr_wl * 1e9) + self.ui.spinBoxCalibWL.setValue(calib_wl * 1e9) + + self.wl = slope*self.pix + intercept + (ctr_wl - calib_wl) + if probe != 0.0: + self.freq = 0.01 / self.wl - 0.01 / probe + else: + self.freq = 0.01 / self.wl + + self.imported_calib_vec = _copy.deepcopy(calib_vec) + + self.updateSlider() + + @staticmethod + def _create_list_names(item_list): + temp = [] + for q in item_list: + temp.append(q[0] + ' : ' + q[1] + ' : ' + q[-1]) + return temp + + def updateDatasets(self): + """ Update the listWidget of datasets """ + self.ui.listWidgetDatasets.clear() + + temp = self._create_list_names(self.data_list) + + for q in temp: + self.ui.listWidgetDatasets.addItem(q) + + self.updateParams() + # self.updateMosaicImage() + + def updateMosaicImage(self): + if self.data._data: + + idx = self.ui.sliderFreq.value() + self.ui.lineEditPix.setText(str(idx)) + if self.freq is not None: + self.ui.lineEditFreq.setText(str(self.freq[idx])) + + self.mpl.ax.clear() + temp = self.data.mosaic2d(idx=idx) + if _np.iscomplexobj(temp): + self.mpl.ax.imshow(temp.imag) + else: + self.mpl.ax.imshow(temp) + + self.mpl.draw() + + def closeEvent(self, event): + print('Closing') + + if self.h5dlist: + for q in self.h5dlist: + print('Closing: {}'.format(q)) + q.file.close() + self.init_internals() + + app = _QApplication.instance() + app.closeAllWindows() + app.quit() + + + + def updateParams(self): + """ Update Mosaic object parameters """ + self.data.parameters['StartC'] = self.ui.spinBoxStartCol.value() + self.data.parameters['StartR'] = self.ui.spinBoxStartRow.value() + self.data.parameters['EndC'] = -1*self.ui.spinBoxEndCol.value() + self.data.parameters['EndR'] = -1*self.ui.spinBoxEndRow.value() + self.data.parameters['Transpose'] = self.ui.checkBoxTranspose.isChecked() + self.data.parameters['FlipVertical'] = self.ui.checkBoxFlipV.isChecked() + self.data.parameters['FlipHorizontally'] = self.ui.checkBoxFlipH.isChecked() + self.data.parameters['Compress'] = self.ui.checkBoxCompress.isChecked() + self.data.parameters['Shape'] = [self.ui.spinBoxMRows.value(), self.ui.spinBoxNCols.value()] + + idx = self.ui.comboBoxRowCol.currentIndex() + if idx == 0: + self.data.parameters['Order'] = 'R' + else: + self.data.parameters['Order'] = 'C' + + mrows = self.ui.spinBoxMRows.value() + ncols = self.ui.spinBoxNCols.value() + n_dsets = len(self.data_list) + + if (mrows * ncols) < n_dsets: + mrows = int(_np.ceil(n_dsets / ncols)) + + self.ui.spinBoxMRows.setValue(mrows) + self.ui.spinBoxNCols.setValue(ncols) + + self.data.parameters['Shape'] = [mrows, ncols] + + if self.data._data: + self.updateMosaicImage() + + def save(self): + + if self.data.parameters['Compress']: + msg = _QMessageBox(self) + msg.setIcon(_QMessageBox.Information) + str1 = 'Currently, HDF5-saving with compression is not supported. Saving full data.' + msg.setText(str1) + msg.setWindowTitle('Compression not supported.') + msg.setStandardButtons(_QMessageBox.Ok) + msg.setDefaultButton(_QMessageBox.Ok) + msg.exec() + + ret = DialogSave.dialogSave(parent=self, + current_filename='MOSAIC_' + self.last_fname, + current_path=self.last_path, + current_dataset_name=self.last_dsetname, + suffix='') + if ret is None: + pass # Save canceled + else: + save_filename = ret[0] + save_path = ret[1] + save_dataset_name = ret[2] + + save_grp = save_dataset_name.rpartition('/')[0] + save_dataset_name_no_grp = save_dataset_name.rpartition('/')[-1] + save_dataset_mask = save_grp + '/' + 'MASK_' + save_dataset_name_no_grp + mask = self.data.mosaic_mask() + + new_attrs = OrderedDict() + new_attrs.update(self.data.attr_dict()) + + if self.imported_calib_vec: + new_attrs.update({'Calib.a_vec':self.imported_calib_vec[0], + 'Calib.ctr_wl':self.imported_calib_vec[1], + 'Calib.ctr_wl0':self.imported_calib_vec[2], + 'Calib.n_pix':self.imported_calib_vec[3], + 'Calib.probe':self.imported_calib_vec[4], + 'Calib.units':'nm'}) + + if self.imported_spatial_vec: + temp = self.data.mosaic_shape() + x_stepsize = self.imported_spatial_vec[0] + y_stepsize = self.imported_spatial_vec[0] + x_start = 0 + y_start = 0 + x_stop = (temp[1]-1)*x_stepsize + y_stop = (temp[0]-1)*y_stepsize + x_steps = temp[1] + y_steps = temp[0] + + # ['Raster.Fast.Start', 'Raster.Fast.Stop', 'Raster.Fast.Steps', + # 'Raster.Slow.Start', 'Raster.Slow.Stop', 'Raster.Slow.Steps'] + new_attrs.update({'Raster.Fast.StepSize':x_stepsize, 'Raster.Fast.Steps':x_steps, + 'Raster.Fast.Start':x_start, 'Raster.Fast.Stop':x_stop, + 'Raster.Slow.StepSize':y_stepsize, 'Raster.Slow.Steps':y_steps, + 'Raster.Slow.Start':y_start, 'Raster.Slow.Stop':y_stop}) + + for num, q in enumerate(self.data._data): + curr_shape = [(mask == num).sum(axis=0).max(), (mask == num).sum(axis=1).max()] + new_attrs.update({'Mosaic.shape.{}'.format(num):curr_shape}) + new_attrs.update({'Mosaic.path.{}'.format(num):self.data_list[num][0]}) + new_attrs.update({'Mosaic.filename.{}'.format(num):self.data_list[num][1]}) + new_attrs.update({'Mosaic.datasetname.{}'.format(num):self.data_list[num][2]}) + if hasattr(q, 'attrs'): + orig_attrs = lazy5.inspect.get_attrs_dset(q.file, q.name) + for k in orig_attrs: + new_attrs.update({'Mosaic.{}.{}'.format(num, k):orig_attrs[k]}) + + # try: + fid = h5py.File(_os.path.join(save_path, save_filename), 'a') + fid.require_group(save_grp) + fid.create_dataset(save_dataset_name, shape=self.data.mosaic_shape(), + dtype=self.data.dtype, chunks=True) + self.data.mosaicfull(out=fid[save_dataset_name]) + lazy5.alter.write_attr_dict(fid[save_dataset_name], new_attrs) + fid.close() + + lazy5.create.save(save_filename, save_dataset_mask, self.data.mosaic_mask(), + pth=save_path, attr_dict=new_attrs) + +if __name__ == '__main__': + app = _QApplication(_sys.argv) + app.setStyle('Cleanlooks') + app.setQuitOnLastWindowClosed(True) + + win = MainWindowMosaic(parent=None) + win.show() + app.exec_() + + + + print(win) + + _sys.exit() \ No newline at end of file diff --git a/crikit/ui/old/dialog_plugin (2).py b/crikit/ui/old/dialog_plugin (2).py deleted file mode 100644 index 6349333..0000000 --- a/crikit/ui/old/dialog_plugin (2).py +++ /dev/null @@ -1,254 +0,0 @@ -""" -Created on Tue Feb 16 15:51:32 2016 - -@author: camp -""" - -import sys as _sys -import os as _os - -# Generic imports for QT-based programs -from PyQt5.QtWidgets import (QApplication as _QApplication, - QWidget as _QWidget, QDialog as _QDialog, - QMainWindow as _QMainWindow, - QSizePolicy as _QSizePolicy) -import PyQt5.QtCore as _QtCore - -# Other imports -import numpy as _np - -from yapsy.PluginManager import (PluginManager as _PluginManager, - PluginInfo as _PluginInfo) - -from crikit.ui.helper_plugin_categories import DeNoiser, ErrorCorrect -#import logging -#logging.basicConfig(level=logging.DEBUG) - -# Import from Designer-based GUI -from crikit.ui.qt_PluginSelector import Ui_Dialog - - -# Generic imports for MPL-incorporation -import matplotlib as _mpl -_mpl.use('Qt5Agg') -_mpl.rcParams['font.family'] = 'sans-serif' -_mpl.rcParams['font.size'] = 10 -#import matplotlib.pyplot as plt - -#from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as _FigureCanvas, \ -# NavigationToolbar2QT as _NavigationToolbar) - -#from matplotlib.figure import Figure as _Figure - -class DialogDenoisePlugins(_QDialog): - """ - DialogDenoisePlugins : Denoise plugin selector - - Methods - -------- - dialogDenoisePlugins : Used to call UI and retrieve results of dialog - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - - def __init__(self, parent = None): - super(DialogDenoisePlugins, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.temp = 0 - - # Create plugin manager - self.manager = _PluginManager() - - - if _os.path.isdir(_os.path.abspath('./plugins')): - plugins_loc = 'plugins' - elif _os.path.isdir(_os.path.abspath('./crikit/ui/plugins')): - plugins_loc = './crikit/ui/plugins' - elif _os.path.isdir(_os.path.abspath('./ui/plugins')): - plugins_loc = './ui/plugins' - else: - plugins_loc = None - - self.manager.setPluginPlaces([plugins_loc]) - self.manager.setCategoriesFilter({'DeNoiser' : DeNoiser}) - - self.manager.collectPlugins() - - # Load plugins - self.manager.locatePlugins() - - self.manager.loadPlugins() - self.denoisers = {} - self.denoiser_desc = {} - - for plugin in self.manager.getPluginsOfCategory('DeNoiser'): - self.ui.comboBox.addItem(plugin.plugin_object.name) - self.denoisers[plugin.plugin_object.name] = plugin.plugin_object - self.denoiser_desc[plugin.plugin_object.name] = plugin._PluginInfo__details['Documentation']['description'] - - #print(self.denoiser_desc[self.ui.comboBox.currentText]) - self.ui.plainTextEditDescription.setPlainText(self.denoiser_desc[self.ui.comboBox.currentText()]) - self.ui.comboBox.currentIndexChanged.connect(self.changeDesc) - - def changeDesc(self): - self.ui.plainTextEditDescription.setPlainText(self.denoiser_desc[self.ui.comboBox.currentText()]) - - @staticmethod - def dialogDenoisePlugins(parent = None): - """ - - """ - - dialog = DialogDenoisePlugins(parent) - - result = dialog.exec_() - - - if result == 1: # Accepted - return (dialog.denoisers[dialog.ui.comboBox.currentText()]) - else: # Rejected/Cancel - return None - -class DialogErrCorrPlugins(_QDialog): - """ - DialogErrCorrPlugins : Error correction plugin selector - - Methods - ------- - dialogErrCorrPlugins : Used to call UI and retrieve results of dialog - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - - def __init__(self, parent = None): - super(DialogErrCorrPlugins, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.temp = 0 - - # Create plugin manager - self.manager = _PluginManager() - - - if _os.path.isdir(_os.path.abspath('./plugins')): - plugins_loc = 'plugins' - elif _os.path.isdir(_os.path.abspath('./crikit/ui/plugins')): - plugins_loc = './crikit/ui/plugins' - elif _os.path.isdir(_os.path.abspath('./ui/plugins')): - plugins_loc = './ui/plugins' - else: - plugins_loc = None - - self.manager.setPluginPlaces([plugins_loc]) - self.manager.setCategoriesFilter({'ErrorCorrect' : ErrorCorrect}) - - self.manager.collectPlugins() - - # Load plugins - self.manager.locatePlugins() - - self.manager.loadPlugins() - self.errcorrectors = {} - self.errcorrectors_desc = {} - - for plugin in self.manager.getPluginsOfCategory('ErrorCorrect'): - self.ui.comboBox.addItem(plugin.plugin_object.name) - self.errcorrectors[plugin.plugin_object.name] = plugin.plugin_object - self.errcorrectors_desc[plugin.plugin_object.name] = plugin._PluginInfo__details['Documentation']['description'] - - self.ui.comboBox.currentIndexChanged.connect(self.changeDesc) - - try: - self.ui.plainTextEditDescription.setPlainText(self.errcorrectors_desc[self.ui.comboBox.currentText()]) - - except: # Fails if no plugins found - pass - - def changeDesc(self): - - try: - self.ui.plainTextEditDescription.setPlainText(self.errcorrectors_desc[self.ui.comboBox.currentText()]) - except: # Fails if no plugins found - pass - - @staticmethod - def dialogErrCorrPlugins(parent = None): - """ - - """ - - dialog = DialogErrCorrPlugins(parent) - - result = dialog.exec_() - - - if result == 1: # Accepted - return (dialog.errcorrectors[dialog.ui.comboBox.currentText()]) - else: # Rejected/Cancel - return None - - -if __name__ == '__main__': - - -# from crikit.data.classes import HSData -# - x = _np.linspace(100,200,50) - y = _np.linspace(200,300,50) - f = _np.linspace(500,3000,800) - Ex = 30*_np.exp((-(f-1750)**2/(200**2))) - Spectrum = _np.convolve(_np.flipud(Ex),Ex,mode='same') - - data = _np.zeros((y.size,x.size,f.size)) - for count in range(y.size): - data[count,:,:] = y[count]*_np.random.poisson(_np.dot(x[:,None],Spectrum[None,:])) - - #temp = HSData() - #temp.spectrafull = data - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - ### DeNoise Demo - win = DialogDenoisePlugins.dialogDenoisePlugins() - - if win is not None: - retwin = win.denoiseHSData(data) - print('RetWin:{}'.format(retwin)) - -# ### Error Correction Demo -# win = DialogErrCorrPlugins.dialogErrCorrPlugins() -# -## temp = HSData() -# -# WN = _np.linspace(500,4000,1000) -# -# CARS = _np.zeros((20,20,WN.size), dtype=complex) -# CARS[:,:,:] = (1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) -# temp.spectrafull = CARS -# temp.freqvecfull = WN -# -# -# NRB = 0*WN + .055 -# -# if win is not None: -# retwin = win.errorCorrectHSData(data) -# #if win is not None: -# #retwin = win.denoiseHSData(temp) -# #print('RetWin:{}'.format(retwin)) -# -# _sys.exit() - app.exec_() \ No newline at end of file diff --git a/crikit/ui/old/helper_plugin_categories.py b/crikit/ui/old/helper_plugin_categories.py deleted file mode 100644 index 47f15ad..0000000 --- a/crikit/ui/old/helper_plugin_categories.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Created on Tue Feb 16 16:07:39 2016 - -@author: camp -""" - -class DeNoiser(object): - """ - Plugins of this class denoise hyperspectral data (crikit.data.HSData) - """ - - name = 'Do Nothing' - - def denoiseHSData(self, hsdatacls): - return 1 - -class ErrorCorrect(object): - """ - Plugins of this class perform error correction (phase, baseline, etc) on - hyperspectral data - """ - - name = 'Do Nothing' - - def errorCorrectHSData(self, hsdatacls): - return 1 \ No newline at end of file diff --git a/crikit/ui/old/plugins/__init__.py b/crikit/ui/old/plugins/__init__.py deleted file mode 100644 index c745558..0000000 --- a/crikit/ui/old/plugins/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -CRIkit User Interfaces (crikit.ui) -======================================================= - -""" diff --git a/crikit/ui/old/plugins/denoise_Anscombe_SVD.py b/crikit/ui/old/plugins/denoise_Anscombe_SVD.py deleted file mode 100644 index aaddf0f..0000000 --- a/crikit/ui/old/plugins/denoise_Anscombe_SVD.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Created on Mon Feb 22 15:27:50 2016 - -@author: chc -""" - -from crikit.ui.helper_plugin_categories import DeNoiser -import crikit.ui.subui_SVD -from crikit.process.varstabilize import gen_anscombe_forward -from crikit.process.varstabilize import gen_anscombe_inverse_exact_unbiased - -from crikit.ui.dialog_options import DialogAnscombeOptions - -import copy as _copy - -class DeNoiseSVD(DeNoiser): - name = 'Anscombe SVD' - - def denoiseHSData(self, hsdatacls): - data = _copy.deepcopy(hsdatacls.spectra) - result = DialogAnscombeOptions.dialogAnscombeOptions() - if result[0] is not None: - stddev = result[0] - gain = result[1] - data = gen_anscombe_forward(data, gauss_std=stddev, poisson_multi=gain) - ret = crikit.ui.subui_SVD.DialogSVD.dialogSVD(data=data) - if ret is None: - return None - else: - data = gen_anscombe_inverse_exact_unbiased(ret[0], gauss_std=stddev, poisson_multi=gain) - hsdatacls.spectra = data - ret[1][0] = 'AnscSVD' - return ret[1] - else: - return None - - diff --git a/crikit/ui/old/plugins/denoise_Anscombe_SVD.yapsy-plugin b/crikit/ui/old/plugins/denoise_Anscombe_SVD.yapsy-plugin deleted file mode 100644 index 726b2b5..0000000 --- a/crikit/ui/old/plugins/denoise_Anscombe_SVD.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = Anscombe SVD -Module = denoise_Anscombe_SVD - -[Documentation] -Author = Charles H. Camp Jr. -Version = 16.02.22 -Description = Anscombe-Transformed Singular Value Decomposition diff --git a/crikit/ui/old/plugins/denoise_SVD.py b/crikit/ui/old/plugins/denoise_SVD.py deleted file mode 100644 index 6845945..0000000 --- a/crikit/ui/old/plugins/denoise_SVD.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Created on Tue Feb 16 17:23:25 2016 - -@author: camp -""" -from crikit.ui.helper_plugin_categories import DeNoiser -import crikit.ui.subui_SVD - -class DeNoiseSVD(DeNoiser): - name = 'SVD' - - def denoiseHSData(self, hsdatacls): - ret = crikit.ui.subui_SVD.DialogSVD.dialogSVD(data=hsdatacls.spectra) - if ret is None: - return None - else: - hsdatacls.spectra = ret[0] - return ret[1] - diff --git a/crikit/ui/old/plugins/denoise_SVD.yapsy-plugin b/crikit/ui/old/plugins/denoise_SVD.yapsy-plugin deleted file mode 100644 index dee4653..0000000 --- a/crikit/ui/old/plugins/denoise_SVD.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = SVD -Module = denoise_SVD - -[Documentation] -Author = Charles H. Camp Jr. -Version = 16.02.16 -Description = Singular Value Decomposition diff --git a/crikit/ui/old/plugins/errcorrect_amp_ALS.py b/crikit/ui/old/plugins/errcorrect_amp_ALS.py deleted file mode 100644 index 31cd847..0000000 --- a/crikit/ui/old/plugins/errcorrect_amp_ALS.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -Created on Tue Mar 2 2016 - -@author: chc -""" - -from crikit.ui.helper_plugin_categories import ErrorCorrect -from crikit.ui.subui_ploteffect import DialogPlotEffect -from crikit.ui.widget_ploteffect import widgetALS - -from crikit.process.maths.als_methods import als_baseline_redux as _als -from crikit.process.maths.kk import hilbertfft as _hilbert - -import numpy as _np -import numexpr as _ne -import timeit as _ti -#import copy as _copy - -class ErrCorrectAmpALS(ErrorCorrect): - name = 'Amp Error: ALS' - - def errorCorrectHSData(self, hsdatacls): - temp_spectra = hsdatacls._get_rand_spectra(10, pt_sz=3, quads=True) - - plugin = widgetALS() - - result = DialogPlotEffect.dialogPlotEffect(temp_spectra, x=hsdatacls.freqvec, - plugin=plugin, xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Imag. {$\chi_R$} (au)', show_difference=True) - if result is not None: - p = result.p - lam = result.lam - redux = result.redux - - data_out = _np.zeros(hsdatacls.spectra.shape, dtype=hsdatacls.spectrafull.dtype) - - detrend_ct = 0 - detrend_tot = hsdatacls.mlen * hsdatacls.nlen - - for count_col in _np.arange(0, hsdatacls.nlen): - start = _ti.default_timer() - for count_row in _np.arange(0, hsdatacls.mlen): -# start2 = _ti.default_timer() - - # Most efficient system - if len(hsdatacls.pixrange) != 0: - sig = hsdatacls.spectrafull[count_row, count_col, hsdatacls.pixrange[0]:hsdatacls.pixrange[1]+1] - else: - sig = hsdatacls.spectrafull[count_row, count_col,:] - - # MUCH LESS EFFICIENT - #ph = hsdatacls.spectraphase[count_row, count_col,:] - -# stop2 = _ti.default_timer() - -# start3 = _ti.default_timer() - if isinstance(sig, complex): - err_amp, als_type = _als(sig.imag, redux_factor=redux, redux_full=False, - smoothness_param=lam, asym_param=p, print_iteration=False) - data_out[count_row, count_col, :] = hsdatacls.spectracomplex[count_row, count_col, :] - 1j*err_amp - else: - err_amp, als_type = _als(sig, redux_factor=redux, redux_full=False, - smoothness_param=lam, asym_param=p, print_iteration=False) - data_out[count_row, count_col, :] = hsdatacls.spectracomplex[count_row, count_col, :] - err_amp - - detrend_ct += 1 - stop = _ti.default_timer() -# print('2: {}'.format(stop2-start2)) -# print('3: {}'.format(stop3-start3)) -# print('4: {}'.format(stop4-start4)) -# print('5: {}'.format(stop5-start5)) -# - print('Detrended {} / {} ({:.5f} sec/spect)'.format(detrend_ct, detrend_tot, (stop-start)/hsdatacls.mlen )) - - hsdatacls.spectra = data_out - return ['AmpErrorCorect','Type', 'ALS', 'p', p, 'lambda', lam, 'redux', redux, 'alg', als_type] - else: - return None \ No newline at end of file diff --git a/crikit/ui/old/plugins/errcorrect_amp_ALS.yapsy-plugin b/crikit/ui/old/plugins/errcorrect_amp_ALS.yapsy-plugin deleted file mode 100644 index 68a24e9..0000000 --- a/crikit/ui/old/plugins/errcorrect_amp_ALS.yapsy-plugin +++ /dev/null @@ -1,9 +0,0 @@ -[Core] -Name = Amp Error: ALS -Module = errcorrect_amp_ALS - -[Documentation] -Author = Charles H. Camp Jr. -Version = 16.03.02 -Description = Amplitude error correction with alternating least squares. If complex, performed on imag component. - diff --git a/crikit/ui/old/plugins/errcorrect_phase_ALS.py b/crikit/ui/old/plugins/errcorrect_phase_ALS.py deleted file mode 100644 index 680fbf0..0000000 --- a/crikit/ui/old/plugins/errcorrect_phase_ALS.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -Created on Tue Mar 1 11:12:12 2016 - -@author: chc -""" - -from crikit.ui.helper_plugin_categories import ErrorCorrect -from crikit.ui.subui_ploteffect import DialogPlotEffect -from crikit.ui.widget_ploteffect import widgetALS - -from crikit.process.maths.als_methods import als_baseline_redux as _als -from crikit.process.maths.kk import hilbertfft as _hilbert - -import numpy as _np -import numexpr as _ne -import timeit as _ti -#import copy as _copy - -class ErrCorrectPhaseALS(ErrorCorrect): - name = 'Phase Error: ALS' - - def errorCorrectHSData(self, hsdatacls): - temp_spectra = hsdatacls._get_rand_spectra_phase(10, pt_sz=3, quads=True) - - plugin = widgetALS() - - result = DialogPlotEffect.dialogPlotEffect(temp_spectra, x=hsdatacls.freqvec, - plugin=plugin, xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Imag. {$\chi_R$} (au)', show_difference=True) - if result is not None: - p = result.p - lam = result.lam - redux = result.redux - - data_out = _np.zeros(hsdatacls.spectra.shape, dtype=complex) - - detrend_ct = 0 - detrend_tot = hsdatacls.mlen * hsdatacls.nlen - - for count_col in _np.arange(0, hsdatacls.nlen): - start = _ti.default_timer() - for count_row in _np.arange(0, hsdatacls.mlen): -# start2 = _ti.default_timer() - - # Most efficient system - if len(hsdatacls.pixrange) != 0: - ph = _np.angle(hsdatacls.spectrafull[count_row, count_col, hsdatacls.pixrange[0]:hsdatacls.pixrange[1]+1]) - else: - ph = _np.angle(hsdatacls.spectrafull[count_row, count_col,:]) - - # MUCH LESS EFFICIENT - #ph = hsdatacls.spectraphase[count_row, count_col,:] - -# stop2 = _ti.default_timer() - -# start3 = _ti.default_timer() - err_phase, als_type = _als(ph, redux_factor=redux, redux_full=False, - smoothness_param=lam, asym_param=p, print_iteration=False) -# stop3 = _ti.default_timer() - -# start4 = _ti.default_timer() - h = _hilbert(err_phase) -# stop4 = _ti.default_timer() - #err_amp = _np.exp(_hilbert(err_phase).imag) - #err_amp = _ne.evaluate('exp(imag(h))') - #correction_factor = 1/err_amp * _np.exp(-1j*err_phase) - -# start5 = _ti.default_timer() - correction_factor = _ne.evaluate('1/exp(imag(h)) * exp(-1j*err_phase)') -# stop5 = _ti.default_timer() - - - data_out[count_row, count_col, :] = hsdatacls.spectracomplex[count_row, count_col, :]*correction_factor - - detrend_ct += 1 - stop = _ti.default_timer() -# print('2: {}'.format(stop2-start2)) -# print('3: {}'.format(stop3-start3)) -# print('4: {}'.format(stop4-start4)) -# print('5: {}'.format(stop5-start5)) -# - print('Detrended {} / {} ({:.5f} sec/spect)'.format(detrend_ct, detrend_tot, (stop-start)/hsdatacls.mlen )) - - hsdatacls.spectra = data_out - return ['PhaseErrorCorect','Type', 'ALS', 'p', p, 'lambda', lam, 'redux', redux, 'alg', als_type] - else: - return None \ No newline at end of file diff --git a/crikit/ui/old/plugins/errcorrect_phase_ALS.yapsy-plugin b/crikit/ui/old/plugins/errcorrect_phase_ALS.yapsy-plugin deleted file mode 100644 index 22b918e..0000000 --- a/crikit/ui/old/plugins/errcorrect_phase_ALS.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = Phase Error: ALS -Module = errcorrect_phase_ALS - -[Documentation] -Author = Charles H. Camp Jr. -Version = 16.03.01 -Description = Phase error correction with alternating least squares diff --git a/crikit/ui/old/plugins/errcorrect_scale_SG.py b/crikit/ui/old/plugins/errcorrect_scale_SG.py deleted file mode 100644 index 436eae3..0000000 --- a/crikit/ui/old/plugins/errcorrect_scale_SG.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Created on Wed Mar 2 12:39:53 2016 - -@author: chc -""" - -from crikit.ui.helper_plugin_categories import ErrorCorrect -from crikit.ui.subui_ploteffect import DialogPlotEffect -from crikit.ui.widget_ploteffect import widgetSG - -from crikit.process.maths.als_methods import als_baseline_redux as _als -from crikit.process.maths.kk import hilbertfft as _hilbert - -import numpy as _np -import numexpr as _ne -import timeit as _ti -#import scipy as _scipy -from scipy.signal import savgol_filter as _sg -#import copy as _copy - -class ErrCorrectScaleSG(ErrorCorrect): - name = 'Scaling: Savitky-Golay' - - def errorCorrectHSData(self, hsdatacls): - temp_spectra = hsdatacls._get_rand_spectra_real(10, pt_sz=3, quads=True) - - plugin = widgetSG() - - result = DialogPlotEffect.dialogPlotEffect(temp_spectra, x=hsdatacls.freqvec, - plugin=plugin, xlabel='Wavenumber (cm$^{-1}$)', - ylabel='Real {$\chi_R$} (au)', show_difference=True) - if result is not None: - win_size = result.win_size - order = result.order - - - detrend_ct = 0 - detrend_tot = hsdatacls.mlen * hsdatacls.nlen - - # Most efficient system - if len(hsdatacls.pixrange) != 0: - data_out = hsdatacls.spectrafull[:,:, hsdatacls.pixrange[0]:hsdatacls.pixrange[1]+1] - else: - data_out = hsdatacls.spectrafull - - start = _ti.default_timer() - - correction = (1/_sg(data_out.real, window_length=win_size, polyorder=order, axis=-1)) - - data_out = data_out*correction - - stop = _ti.default_timer() -# print('2: {}'.format(stop2-start2)) -# print('3: {}'.format(stop3-start3)) -# print('4: {}'.format(stop4-start4)) -# print('5: {}'.format(stop5-start5)) -# - print('Scaled {} spectra ({:.5f} sec/spect)'.format(detrend_tot, (stop-start)/(hsdatacls.mlen*hsdatacls.nlen))) - - hsdatacls.spectra = data_out - return ['Scaling','Type', 'SG', 'win_size', win_size, 'order', order] - else: - return None \ No newline at end of file diff --git a/crikit/ui/old/plugins/errcorrect_scale_SG.yapsy-plugin b/crikit/ui/old/plugins/errcorrect_scale_SG.yapsy-plugin deleted file mode 100644 index 8989d4e..0000000 --- a/crikit/ui/old/plugins/errcorrect_scale_SG.yapsy-plugin +++ /dev/null @@ -1,9 +0,0 @@ -[Core] -Name = Scaling: SG -Module = errcorrect_scale_SG - -[Documentation] -Author = Charles H. Camp Jr. -Version = 16.03.02 -Description = Scaling determined and applied by a Savitky-Golay filter. - diff --git a/crikit/ui/old/qt_PluginSelector.py b/crikit/ui/old/qt_PluginSelector.py deleted file mode 100644 index cc32f3f..0000000 --- a/crikit/ui/old/qt_PluginSelector.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'ui_PluginSelector.ui' -# -# Created by: PyQt5 UI code generator 5.5.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(389, 239) - Dialog.setStyleSheet("font: 10pt \"Arial\";") - self.gridLayout = QtWidgets.QGridLayout(Dialog) - self.gridLayout.setObjectName("gridLayout") - self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") - self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1) - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.label = QtWidgets.QLabel(Dialog) - font = QtGui.QFont() - font.setFamily("Arial") - font.setPointSize(10) - font.setItalic(False) - self.label.setFont(font) - self.label.setObjectName("label") - self.verticalLayout.addWidget(self.label, 0, QtCore.Qt.AlignTop) - self.comboBox = QtWidgets.QComboBox(Dialog) - self.comboBox.setObjectName("comboBox") - self.verticalLayout.addWidget(self.comboBox) - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem) - spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem1) - self.label_2 = QtWidgets.QLabel(Dialog) - self.label_2.setObjectName("label_2") - self.verticalLayout.addWidget(self.label_2) - self.plainTextEditDescription = QtWidgets.QPlainTextEdit(Dialog) - self.plainTextEditDescription.setReadOnly(True) - self.plainTextEditDescription.setObjectName("plainTextEditDescription") - self.verticalLayout.addWidget(self.plainTextEditDescription) - self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) - - self.retranslateUi(Dialog) - self.buttonBox.accepted.connect(Dialog.accept) - self.buttonBox.rejected.connect(Dialog.reject) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Plugin Selector")) - self.label.setText(_translate("Dialog", "Plugin")) - self.label_2.setText(_translate("Dialog", "Description")) - diff --git a/crikit/ui/qt5/ui_BlankLayout.ui b/crikit/ui/qt5/ui_BlankLayout.ui index 8936f23..2c45408 100644 --- a/crikit/ui/qt5/ui_BlankLayout.ui +++ b/crikit/ui/qt5/ui_BlankLayout.ui @@ -6,8 +6,8 @@ 0 0 - 802 - 1128 + 600 + 54 @@ -17,8 +17,24 @@ - 2 + 10 + + + 10 + + + 10 + + + 10 + + 10 + + + + + 2 @@ -34,7 +50,17 @@ - + + + Qt::Vertical + + + + 20 + 40 + + + diff --git a/crikit/ui/qt5/ui_CRIkit.ui b/crikit/ui/qt5/ui_CRIkit.ui index 7dcbc4d..aa509d6 100644 --- a/crikit/ui/qt5/ui_CRIkit.ui +++ b/crikit/ui/qt5/ui_CRIkit.ui @@ -6,8 +6,8 @@ 0 0 - 1691 - 905 + 1200 + 800 @@ -152,7 +152,55 @@ - + + + History + + + + + + QAbstractItemView::NoEditTriggers + + + 0 + + + 2 + + + false + + + 200 + + + true + + + false + + + false + + + 37 + + + + Process Attributes + + + + + Value + + + + + + + Notes @@ -347,8 +395,8 @@ This will be saved to the processed file. 0 0 - 1691 - 22 + 1200 + 19 @@ -359,6 +407,10 @@ This will be saved to the processed file. + + + + @@ -473,6 +525,11 @@ This will be saved to the processed file. + + + + + @@ -483,6 +540,8 @@ This will be saved to the processed file. Settings + + @@ -493,6 +552,12 @@ This will be saved to the processed file. + + + NIST Special + + + @@ -500,6 +565,7 @@ This will be saved to the processed file. + @@ -1044,29 +1110,61 @@ This will be saved to the processed file. + + + :/icons/open-iconic-master/png/account-login-4x.png:/icons/open-iconic-master/png/account-login-4x.png + - Load NRB (HDF; Left-Side) + Load NRB (HDF; Left) + + + Load NRB (HDF; Left) + + + :/icons/open-iconic-master/png/account-login-4x.png:/icons/open-iconic-master/png/account-login-4x.png + - Load NRB (HDF; Right-Side) + Load NRB (HDF; Right) + + + Load NRB (HDF; Right) + + + :/icons/open-iconic-master/png/globe-4x.png:/icons/open-iconic-master/png/globe-4x.png + - NRB from ROI (Left-Side) + NRB from ROI (Left) + + + NRB from ROI (Left) + + + :/icons/open-iconic-master/png/globe-4x.png:/icons/open-iconic-master/png/globe-4x.png + - NRB from ROI (Right-Side) + NRB from ROI (Right) + + + NRB from ROI (Right) false + + + :/icons/open-iconic-master/png/wrench-4x.png:/icons/open-iconic-master/png/wrench-4x.png + Merge NRBs @@ -1157,6 +1255,90 @@ This will be saved to the processed file. BCARS Numerical Phantom + + + true + + + true + + + Use Preview ROI(s) + + + + + false + + + Set Preview ROI(s) + + + + + false + + + false + + + Delete Preview ROI(s) + + + + + true + + + Show Preview ROI(s) + + + + + true + + + Show Preview ROI Legend + + + + + false + + + + :/icons/open-iconic-master/png/compass-4x.png:/icons/open-iconic-master/png/compass-4x.png + + + Est. Calibration + + + + + + :/icons/open-iconic-master/png/grid-three-up-4x.png + + + + Create Mosaic + + + + + true + + + true + + + Use Imaginary if Exists + + + + + Open HDF OOC (NIST) + + diff --git a/crikit/ui/qt5/ui_CompositeColor.ui b/crikit/ui/qt5/ui_CompositeColor.ui index 9c0df3c..1a033c7 100644 --- a/crikit/ui/qt5/ui_CompositeColor.ui +++ b/crikit/ui/qt5/ui_CompositeColor.ui @@ -6,8 +6,8 @@ 0 0 - 767 - 594 + 600 + 100 @@ -128,6 +128,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/crikit/ui/qt5/ui_HDFLoad.ui b/crikit/ui/qt5/ui_HDFLoad.ui deleted file mode 100644 index f5abf36..0000000 --- a/crikit/ui/qt5/ui_HDFLoad.ui +++ /dev/null @@ -1,279 +0,0 @@ - - - Dialog - - - - 0 - 0 - 845 - 588 - - - - HDF File Inspector - - - font: 10pt "Arial"; - - - - - - QLayout::SetNoConstraint - - - - - QLayout::SetNoConstraint - - - - - - - Groups Containing Datasets - - - - - - - - - - Datasets - - - - - - - QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked - - - QAbstractItemView::ExtendedSelection - - - - - - - <html><head/><body><p><span style=" font-weight:600;">Include</span> Entires with Substring (separate by ',' [comma])</p></body></html> - - - - - - - - - - <html><head/><body><p><span style=" font-weight:600;">Exclude</span> Entires with Substring (separate by ',' [comma])</p></body></html> - - - - - - - - - - - - Filter List - - - - - - - Reset List - - - - - - - - - - - - - Current Selection - - - - - - - - 0 - 0 - - - - - 16777215 - 100 - - - - - - - - Atrribute Table - - - - - - - - - - true - - - 2 - - - true - - - 200 - - - false - - - true - - - true - - - false - - - false - - - - Attribute - - - - 10 - - - - - 121 - 121 - 121 - - - - - - 91 - 91 - 91 - - - - - - - Value - - - - 123 - 123 - 123 - - - - - - 91 - 91 - 91 - - - - - - - - - - Dataset Information (Memo) - - - - - - - - 0 - 0 - - - - - 16777215 - 100 - - - - - - - - - - - - 10 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - OK - - - - - - - Cancel - - - - - - - - - - - - diff --git a/crikit/ui/qt5/ui_Mosaic.ui b/crikit/ui/qt5/ui_Mosaic.ui new file mode 100644 index 0000000..595c0fe --- /dev/null +++ b/crikit/ui/qt5/ui_Mosaic.ui @@ -0,0 +1,1185 @@ + + + MainWindow + + + + 0 + 0 + 1200 + 915 + + + + + 2000 + 16777215 + + + + Make Mosaic Dataset + + + Qt::ToolButtonTextUnderIcon + + + + + + + 0 + + + + + + 0 + 0 + + + + + 500 + 0 + + + + + 500 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + 1 + + + + + 0 + + + 0 + + + + + 0 + + + + + M Rows + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 1 + + + + + + + + + + + N Cols + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 1 + + + 300 + + + 1 + + + + + + + + + + + Qt::Vertical + + + + 20 + 15 + + + + + + + + Trim Row Start + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 500 + + + + + + + Qt::Vertical + + + + 20 + 15 + + + + + + + + Trim Row End + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 500 + + + + + + + Qt::Vertical + + + + 20 + 15 + + + + + + + + Trim Col Start + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 500 + + + + + + + Qt::Vertical + + + + 20 + 15 + + + + + + + + Trim Col End + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 500 + + + + + + + Compress + + + + + + + Qt::Vertical + + + + 20 + 5 + + + + + + + + Row / Column First + + + + + + + + 100 + 16777215 + + + + + Row + + + + + Column + + + + + + + + + 120 + 16777215 + + + + Flip Horizontally + + + + + + + + 110 + 16777215 + + + + Flip Vertically + + + + + + + + 110 + 16777215 + + + + Transpose + + + + + + + + + Order of Inputs (Drag to Move) + + + + + + + 2 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 16777215 + + + + + + + + :/icons/open-iconic-master/png/arrow-circle-top-4x.png:/icons/open-iconic-master/png/arrow-circle-top-4x.png + + + + + + + + 50 + 16777215 + + + + + + + + :/icons/open-iconic-master/png/arrow-circle-bottom-4x.png:/icons/open-iconic-master/png/arrow-circle-bottom-4x.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 16777215 + + + + + + + + :/icons/open-iconic-master/png/minus-4x.png:/icons/open-iconic-master/png/minus-4x.png + + + + + + + + 50 + 16777215 + + + + + + + + :/icons/open-iconic-master/png/plus-4x.png:/icons/open-iconic-master/png/plus-4x.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + + 120 + 20 + + + + + 1000 + 20 + + + + Frequency Pixel + + + Qt::AutoText + + + Qt::AlignCenter + + + 0 + + + + + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + Arial + 14 + 50 + false + false + + + + font: 14pt "Arial"; + + + + + + + true + + + + 100 + 30 + + + + + 100 + 30 + + + + + + + + + 198 + 198 + 198 + + + + + + + + + 198 + 198 + 198 + + + + + + + + + 240 + 240 + 240 + + + + + + + + + + + true + + + + + + + Estimated Frequency (cm-1) + + + + + + + + 200 + 30 + + + + 10 + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 500 + 0 + + + + + 500 + 16777215 + + + + 0 + + + + Spectral Calibration + + + + + + + 400 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + Wavelength Intercept (nm) + + + + + + + 10 + + + -100000000.000000000000000 + + + 100000000.000000000000000 + + + 832.551012000000014 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Wavelength Slope (nm/pix) + + + + + + + 10 + + + -100000000.000000000000000 + + + 100000000.000000000000000 + + + -0.165956000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Probe Wavelength (nm) + + + + + + + 5 + + + -1000000000.000000000000000 + + + 1000000000.000000000000000 + + + 771.461000000000013 + + + + + + + Calibration Wavelength (nm) + + + + + + + 10 + + + -100000000.000000000000000 + + + 10000000.000000000000000 + + + 700.000000000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Current Center Wavelength (nm) + + + + + + + 10 + + + -100000000.000000000000000 + + + 10000000.000000000000000 + + + 700.000000000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + false + + + + 10 + + + + Loaded from Data + + + + 20 + 20 + + + + true + + + + + + + + Spatial Calibration + + + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + X Step Size (um) + + + + + + + false + + + false + + + QAbstractSpinBox::NoButtons + + + 10 + + + -1.000000000000000 + + + 1000000.000000000000000 + + + 0.100000000000000 + + + -1.000000000000000 + + + + + + + Y Step Size (um) + + + + + + + false + + + false + + + QAbstractSpinBox::NoButtons + + + 10 + + + -1.000000000000000 + + + 1000000.000000000000000 + + + 0.100000000000000 + + + -1.000000000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + false + + + + 10 + + + + Loaded from Data + + + true + + + + + + + + + + + + + 0 + 0 + 1200 + 26 + + + + + File + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + :/icons/open-iconic-master/png/envelope-open-4x.png:/icons/open-iconic-master/png/envelope-open-4x.png + + + Add from HDF5 + + + Ctrl+O + + + + + + :/icons/open-iconic-master/png/envelope-closed-4x.png:/icons/open-iconic-master/png/envelope-closed-4x.png + + + Save to HDF5 + + + Ctrl+S + + + + + + :/icons/open-iconic-master/png/account-logout-4x.png + + + + Exit + + + + + + + + diff --git a/crikit/ui/qt5/ui_PlotEffect.ui b/crikit/ui/qt5/ui_PlotEffect.ui index 51c2c0f..6f97f1a 100644 --- a/crikit/ui/qt5/ui_PlotEffect.ui +++ b/crikit/ui/qt5/ui_PlotEffect.ui @@ -6,8 +6,8 @@ 0 0 - 640 - 977 + 650 + 200 diff --git a/crikit/ui/qt5/ui_PlotEffect_ALS.ui b/crikit/ui/qt5/ui_PlotEffect_ALS.ui index 9521f6a..cf1f947 100644 --- a/crikit/ui/qt5/ui_PlotEffect_ALS.ui +++ b/crikit/ui/qt5/ui_PlotEffect_ALS.ui @@ -6,7 +6,7 @@ 0 0 - 738 + 800 180 diff --git a/crikit/ui/qt5/ui_PlotEffect_ALS2.ui b/crikit/ui/qt5/ui_PlotEffect_ALS2.ui new file mode 100644 index 0000000..ec244ca --- /dev/null +++ b/crikit/ui/qt5/ui_PlotEffect_ALS2.ui @@ -0,0 +1,487 @@ + + + Form + + + + 0 + 0 + 800 + 282 + + + + Form + + + font: 10pt "Arial"; + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 0 + 140 + + + + QFrame::Plain + + + Qt::ScrollBarAsNeeded + + + 0 + + + true + + + 80 + + + false + + + 20 + + + true + + + + Start X + + + + + End X + + + + + P (Asymmetry) Value + + + + + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + Sub-Sampling Factor + + + + + + + 1 + + + 10000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Arial + 10 + 50 + false + false + + + + Lambda (smoothness) + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Fix End-Points + + + + + + + + 20 + 20 + + + + + + + true + + + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Define P (Asymmetry) + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + P Subsections + + + + + + + 5 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Fixed=P + + + + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + 0 + + + 0 + + + + + Max Iterations + + + + + + + 1 + + + 1000000 + + + 100 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Min Difference + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + QLayout::SetNoConstraint + + + + + 0 + + + 0 + + + + + 0 + + + + + Weighted (Subsections) + + + + + + + 5 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Weight Value + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 70 + + + + + 0 + 65 + + + + 80 + + + true + + + + Start X + + + + + + + + + + + + diff --git a/crikit/ui/qt5/ui_PlotEffect_Calibrate.ui b/crikit/ui/qt5/ui_PlotEffect_Calibrate.ui index b61e8ac..50eed61 100644 --- a/crikit/ui/qt5/ui_PlotEffect_Calibrate.ui +++ b/crikit/ui/qt5/ui_PlotEffect_Calibrate.ui @@ -6,8 +6,8 @@ 0 0 - 643 - 415 + 800 + 300 diff --git a/crikit/ui/qt_BlankLayout.py b/crikit/ui/qt_BlankLayout.py index 449d4a2..df9c9cc 100644 --- a/crikit/ui/qt_BlankLayout.py +++ b/crikit/ui/qt_BlankLayout.py @@ -2,26 +2,30 @@ # Form implementation generated from reading ui file '.\ui_BlankLayout.ui' # -# Created by: PyQt5 UI code generator 5.8.1 +# Created by: PyQt5 UI code generator 5.12 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") - Form.resize(802, 1128) + Form.resize(600, 54) self.verticalLayout_2 = QtWidgets.QVBoxLayout(Form) self.verticalLayout_2.setObjectName("verticalLayout_2") self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setContentsMargins(2, 2, 2, 2) - self.verticalLayout.setSpacing(2) + self.verticalLayout.setContentsMargins(10, 10, 10, 10) + self.verticalLayout.setSpacing(10) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout_2.addLayout(self.verticalLayout) self.gridLayout = QtWidgets.QGridLayout() + self.gridLayout.setContentsMargins(2, 2, 2, 2) self.gridLayout.setObjectName("gridLayout") self.verticalLayout_2.addLayout(self.gridLayout) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem) self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) @@ -30,3 +34,4 @@ def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Form")) + diff --git a/crikit/ui/qt_CRIkit.py b/crikit/ui/qt_CRIkit.py index fb4000f..b04ef61 100644 --- a/crikit/ui/qt_CRIkit.py +++ b/crikit/ui/qt_CRIkit.py @@ -2,16 +2,17 @@ # Form implementation generated from reading ui file '.\ui_CRIkit.ui' # -# Created by: PyQt5 UI code generator 5.8.1 +# Created by: PyQt5 UI code generator 5.12 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1691, 905) + MainWindow.resize(1200, 800) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(240, 240, 240)) brush.setStyle(QtCore.Qt.SolidPattern) @@ -51,7 +52,6 @@ def setupUi(self, MainWindow): self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.gridLayout_3 = QtWidgets.QGridLayout(self.tab) - self.gridLayout_3.setContentsMargins(0, 0, 0, 0) self.gridLayout_3.setObjectName("gridLayout_3") self.sweeperVL = QtWidgets.QVBoxLayout() self.sweeperVL.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) @@ -63,7 +63,6 @@ def setupUi(self, MainWindow): self.tabCompositeLarge = QtWidgets.QWidget() self.tabCompositeLarge.setObjectName("tabCompositeLarge") self.gridLayout_4 = QtWidgets.QGridLayout(self.tabCompositeLarge) - self.gridLayout_4.setContentsMargins(0, 0, 0, 0) self.gridLayout_4.setObjectName("gridLayout_4") self.sweeperVL_2 = QtWidgets.QVBoxLayout() self.sweeperVL_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) @@ -75,24 +74,43 @@ def setupUi(self, MainWindow): self.tabSettings = QtWidgets.QWidget() self.tabSettings.setObjectName("tabSettings") self.gridLayout_6 = QtWidgets.QGridLayout(self.tabSettings) - self.gridLayout_6.setContentsMargins(0, 0, 0, 0) self.gridLayout_6.setObjectName("gridLayout_6") self.gridLayout_5 = QtWidgets.QGridLayout() self.gridLayout_5.setObjectName("gridLayout_5") self.gridLayout_6.addLayout(self.gridLayout_5, 0, 0, 1, 1) self.tabMain.addTab(self.tabSettings, "") - self.tab_3 = QtWidgets.QWidget() - self.tab_3.setObjectName("tab_3") - self.gridLayout_2 = QtWidgets.QGridLayout(self.tab_3) - self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.tabHistory = QtWidgets.QWidget() + self.tabHistory.setObjectName("tabHistory") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tabHistory) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.tableWidgetHistory = QtWidgets.QTableWidget(self.tabHistory) + self.tableWidgetHistory.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) + self.tableWidgetHistory.setRowCount(0) + self.tableWidgetHistory.setColumnCount(2) + self.tableWidgetHistory.setObjectName("tableWidgetHistory") + item = QtWidgets.QTableWidgetItem() + self.tableWidgetHistory.setHorizontalHeaderItem(0, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidgetHistory.setHorizontalHeaderItem(1, item) + self.tableWidgetHistory.horizontalHeader().setCascadingSectionResizes(False) + self.tableWidgetHistory.horizontalHeader().setDefaultSectionSize(200) + self.tableWidgetHistory.horizontalHeader().setStretchLastSection(True) + self.tableWidgetHistory.verticalHeader().setVisible(False) + self.tableWidgetHistory.verticalHeader().setCascadingSectionResizes(False) + self.tableWidgetHistory.verticalHeader().setDefaultSectionSize(37) + self.verticalLayout_4.addWidget(self.tableWidgetHistory) + self.tabMain.addTab(self.tabHistory, "") + self.tabNotes = QtWidgets.QWidget() + self.tabNotes.setObjectName("tabNotes") + self.gridLayout_2 = QtWidgets.QGridLayout(self.tabNotes) self.gridLayout_2.setObjectName("gridLayout_2") self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setObjectName("gridLayout") - self.plainTextEdit = QtWidgets.QPlainTextEdit(self.tab_3) + self.plainTextEdit = QtWidgets.QPlainTextEdit(self.tabNotes) self.plainTextEdit.setObjectName("plainTextEdit") self.gridLayout.addWidget(self.plainTextEdit, 0, 0, 1, 1) self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) - self.tabMain.addTab(self.tab_3, "") + self.tabMain.addTab(self.tabNotes, "") self.verticalLayout_3.addWidget(self.tabMain) self.freqSlider = QtWidgets.QScrollBar(self.centralwidget) self.freqSlider.setMinimumSize(QtCore.QSize(400, 30)) @@ -168,7 +186,7 @@ def setupUi(self, MainWindow): self.gridLayout_7.addLayout(self.verticalLayout_3, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1691, 22)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 19)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") @@ -197,6 +215,8 @@ def setupUi(self, MainWindow): self.menuSettings.setObjectName("menuSettings") self.menuHelp = QtWidgets.QMenu(self.menubar) self.menuHelp.setObjectName("menuHelp") + self.menuNIST_Special = QtWidgets.QMenu(self.menubar) + self.menuNIST_Special.setObjectName("menuNIST_Special") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") @@ -416,15 +436,22 @@ def setupUi(self, MainWindow): self.actionUndo_Backup_Enabled.setChecked(True) self.actionUndo_Backup_Enabled.setObjectName("actionUndo_Backup_Enabled") self.actionLoad_NRB_Left_Side = QtWidgets.QAction(MainWindow) + self.actionLoad_NRB_Left_Side.setIcon(icon1) self.actionLoad_NRB_Left_Side.setObjectName("actionLoad_NRB_Left_Side") self.actionLoad_NRB_Right_Side = QtWidgets.QAction(MainWindow) + self.actionLoad_NRB_Right_Side.setIcon(icon1) self.actionLoad_NRB_Right_Side.setObjectName("actionLoad_NRB_Right_Side") self.actionNRB_from_ROI_Left_Side = QtWidgets.QAction(MainWindow) + self.actionNRB_from_ROI_Left_Side.setIcon(icon15) self.actionNRB_from_ROI_Left_Side.setObjectName("actionNRB_from_ROI_Left_Side") self.actionNRB_from_ROI_Right_Side = QtWidgets.QAction(MainWindow) + self.actionNRB_from_ROI_Right_Side.setIcon(icon15) self.actionNRB_from_ROI_Right_Side.setObjectName("actionNRB_from_ROI_Right_Side") self.actionMergeNRBs = QtWidgets.QAction(MainWindow) self.actionMergeNRBs.setEnabled(False) + icon24 = QtGui.QIcon() + icon24.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/wrench-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionMergeNRBs.setIcon(icon24) self.actionMergeNRBs.setObjectName("actionMergeNRBs") self.actionMerge_NRBs_KK_Preview = QtWidgets.QAction(MainWindow) self.actionMerge_NRBs_KK_Preview.setObjectName("actionMerge_NRBs_KK_Preview") @@ -448,24 +475,62 @@ def setupUi(self, MainWindow): self.actionShowOverlayLegend.setCheckable(True) self.actionShowOverlayLegend.setObjectName("actionShowOverlayLegend") self.actionHelpManual = QtWidgets.QAction(MainWindow) - icon24 = QtGui.QIcon() - icon24.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/question-mark-2x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.actionHelpManual.setIcon(icon24) + icon25 = QtGui.QIcon() + icon25.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/question-mark-2x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionHelpManual.setIcon(icon25) self.actionHelpManual.setObjectName("actionHelpManual") self.actionRamanPhantom = QtWidgets.QAction(MainWindow) - icon25 = QtGui.QIcon() - icon25.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/person-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.actionRamanPhantom.setIcon(icon25) + icon26 = QtGui.QIcon() + icon26.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/person-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionRamanPhantom.setIcon(icon26) self.actionRamanPhantom.setObjectName("actionRamanPhantom") self.actionBCARSPhantom = QtWidgets.QAction(MainWindow) - icon26 = QtGui.QIcon() - icon26.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/people-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.actionBCARSPhantom.setIcon(icon26) + icon27 = QtGui.QIcon() + icon27.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/people-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionBCARSPhantom.setIcon(icon27) self.actionBCARSPhantom.setObjectName("actionBCARSPhantom") + self.actionUsePreviewROI = QtWidgets.QAction(MainWindow) + self.actionUsePreviewROI.setCheckable(True) + self.actionUsePreviewROI.setChecked(True) + self.actionUsePreviewROI.setObjectName("actionUsePreviewROI") + self.actionSetPreviewROI = QtWidgets.QAction(MainWindow) + self.actionSetPreviewROI.setEnabled(False) + self.actionSetPreviewROI.setObjectName("actionSetPreviewROI") + self.actionDeletePreviewROI = QtWidgets.QAction(MainWindow) + self.actionDeletePreviewROI.setCheckable(False) + self.actionDeletePreviewROI.setEnabled(False) + self.actionDeletePreviewROI.setObjectName("actionDeletePreviewROI") + self.actionShowPreviewROI = QtWidgets.QAction(MainWindow) + self.actionShowPreviewROI.setCheckable(True) + self.actionShowPreviewROI.setObjectName("actionShowPreviewROI") + self.actionShowPreviewROILegend = QtWidgets.QAction(MainWindow) + self.actionShowPreviewROILegend.setCheckable(True) + self.actionShowPreviewROILegend.setObjectName("actionShowPreviewROILegend") + self.actionEstCalibration = QtWidgets.QAction(MainWindow) + self.actionEstCalibration.setEnabled(False) + icon28 = QtGui.QIcon() + icon28.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/compass-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionEstCalibration.setIcon(icon28) + self.actionEstCalibration.setObjectName("actionEstCalibration") + self.actionCreateMosaic = QtWidgets.QAction(MainWindow) + icon29 = QtGui.QIcon() + icon29.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/grid-three-up-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.On) + self.actionCreateMosaic.setIcon(icon29) + self.actionCreateMosaic.setObjectName("actionCreateMosaic") + self.actionUseImagData = QtWidgets.QAction(MainWindow) + self.actionUseImagData.setCheckable(True) + self.actionUseImagData.setChecked(True) + self.actionUseImagData.setObjectName("actionUseImagData") + self.actionOpenHDFNISTOOC = QtWidgets.QAction(MainWindow) + self.actionOpenHDFNISTOOC.setObjectName("actionOpenHDFNISTOOC") self.menuFile.addAction(self.actionOpenHDFNIST) self.menuFile.addAction(self.actionOpenDLMNIST) self.menuFile.addAction(self.actionSave) self.menuFile.addSeparator() + self.menuFile.addAction(self.actionOpenHDFNISTOOC) + self.menuFile.addSeparator() + self.menuFile.addAction(self.actionCreateMosaic) + self.menuFile.addSeparator() self.menuFile.addAction(self.actionSettings) self.menuPiece_wise_NRB.addAction(self.actionMergeNRBs) self.menuPiece_wise_NRB.addSeparator() @@ -526,15 +591,23 @@ def setupUi(self, MainWindow): self.menuView.addAction(self.actionPointSpectrum) self.menuView.addAction(self.actionROISpectrum) self.menuView.addSeparator() + self.menuView.addAction(self.actionSetPreviewROI) + self.menuView.addAction(self.actionDeletePreviewROI) + self.menuView.addAction(self.actionShowPreviewROI) + self.menuView.addAction(self.actionShowPreviewROILegend) + self.menuView.addSeparator() self.menuView.addAction(self.actionDarkSpectrum) self.menuView.addAction(self.actionNRBSpectrum) self.menuView.addAction(self.actionLeftSideNRBSpect) self.menuView.addAction(self.actionRightSideNRBSpect) self.menuSettings.addAction(self.actionUndo_Backup_Enabled) + self.menuSettings.addAction(self.actionUsePreviewROI) + self.menuSettings.addAction(self.actionUseImagData) self.menuHelp.addAction(self.actionHelpManual) self.menuHelp.addSeparator() self.menuHelp.addAction(self.actionRamanPhantom) self.menuHelp.addAction(self.actionBCARSPhantom) + self.menuNIST_Special.addAction(self.actionEstCalibration) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuEdit.menuAction()) self.menubar.addAction(self.menuView.menuAction()) @@ -542,6 +615,7 @@ def setupUi(self, MainWindow): self.menubar.addAction(self.menuPre_Process.menuAction()) self.menubar.addAction(self.menuAnalysis.menuAction()) self.menubar.addAction(self.menuSettings.menuAction()) + self.menubar.addAction(self.menuNIST_Special.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) self.retranslateUi(MainWindow) @@ -555,10 +629,15 @@ def retranslateUi(self, MainWindow): self.tabMain.setTabText(self.tabMain.indexOf(self.tab), _translate("MainWindow", "Single Frequency")) self.tabMain.setTabText(self.tabMain.indexOf(self.tabCompositeLarge), _translate("MainWindow", "Composite")) self.tabMain.setTabText(self.tabMain.indexOf(self.tabSettings), _translate("MainWindow", "Settings")) + item = self.tableWidgetHistory.horizontalHeaderItem(0) + item.setText(_translate("MainWindow", "Process Attributes")) + item = self.tableWidgetHistory.horizontalHeaderItem(1) + item.setText(_translate("MainWindow", "Value")) + self.tabMain.setTabText(self.tabMain.indexOf(self.tabHistory), _translate("MainWindow", "History")) self.plainTextEdit.setPlainText(_translate("MainWindow", "This is where you enter notes....\n" "\n" "This will be saved to the processed file.")) - self.tabMain.setTabText(self.tabMain.indexOf(self.tab_3), _translate("MainWindow", "Notes")) + self.tabMain.setTabText(self.tabMain.indexOf(self.tabNotes), _translate("MainWindow", "Notes")) self.labelFreqPixel.setText(_translate("MainWindow", "Freq Pixel")) self.labelWavenumber.setText(_translate("MainWindow", "Wavenumber (cm-1)")) self.menuFile.setTitle(_translate("MainWindow", "File")) @@ -573,6 +652,7 @@ def retranslateUi(self, MainWindow): self.menuToolbar.setTitle(_translate("MainWindow", "Toolbar")) self.menuSettings.setTitle(_translate("MainWindow", "Settings")) self.menuHelp.setTitle(_translate("MainWindow", "Help")) + self.menuNIST_Special.setTitle(_translate("MainWindow", "NIST Special")) self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) self.actionOpenHDFNIST.setText(_translate("MainWindow", "Open HDF (NIST)...")) self.actionOpenHDFNIST.setShortcut(_translate("MainWindow", "Ctrl+O")) @@ -632,10 +712,14 @@ def retranslateUi(self, MainWindow): self.actionLoadNRBDLM.setToolTip(_translate("MainWindow", "Load NRB (DLM)")) self.actionToolBarNIST1.setText(_translate("MainWindow", "NIST CRI Workflow (BCARS1)")) self.actionUndo_Backup_Enabled.setText(_translate("MainWindow", "Undo/Backup Enabled")) - self.actionLoad_NRB_Left_Side.setText(_translate("MainWindow", "Load NRB (HDF; Left-Side)")) - self.actionLoad_NRB_Right_Side.setText(_translate("MainWindow", "Load NRB (HDF; Right-Side)")) - self.actionNRB_from_ROI_Left_Side.setText(_translate("MainWindow", "NRB from ROI (Left-Side)")) - self.actionNRB_from_ROI_Right_Side.setText(_translate("MainWindow", "NRB from ROI (Right-Side)")) + self.actionLoad_NRB_Left_Side.setText(_translate("MainWindow", "Load NRB (HDF; Left)")) + self.actionLoad_NRB_Left_Side.setToolTip(_translate("MainWindow", "Load NRB (HDF; Left)")) + self.actionLoad_NRB_Right_Side.setText(_translate("MainWindow", "Load NRB (HDF; Right)")) + self.actionLoad_NRB_Right_Side.setToolTip(_translate("MainWindow", "Load NRB (HDF; Right)")) + self.actionNRB_from_ROI_Left_Side.setText(_translate("MainWindow", "NRB from ROI (Left)")) + self.actionNRB_from_ROI_Left_Side.setToolTip(_translate("MainWindow", "NRB from ROI (Left)")) + self.actionNRB_from_ROI_Right_Side.setText(_translate("MainWindow", "NRB from ROI (Right)")) + self.actionNRB_from_ROI_Right_Side.setToolTip(_translate("MainWindow", "NRB from ROI (Right)")) self.actionMergeNRBs.setText(_translate("MainWindow", "Merge NRBs")) self.actionMerge_NRBs_KK_Preview.setText(_translate("MainWindow", "Merge NRBs (KK Preview)")) self.actionLeftSideNRBSpect.setText(_translate("MainWindow", "Left-Side NRB Spect")) @@ -648,5 +732,15 @@ def retranslateUi(self, MainWindow): self.actionHelpManual.setShortcut(_translate("MainWindow", "F1")) self.actionRamanPhantom.setText(_translate("MainWindow", "Raman Numerical Phantom")) self.actionBCARSPhantom.setText(_translate("MainWindow", "BCARS Numerical Phantom")) + self.actionUsePreviewROI.setText(_translate("MainWindow", "Use Preview ROI(s)")) + self.actionSetPreviewROI.setText(_translate("MainWindow", "Set Preview ROI(s)")) + self.actionDeletePreviewROI.setText(_translate("MainWindow", "Delete Preview ROI(s)")) + self.actionShowPreviewROI.setText(_translate("MainWindow", "Show Preview ROI(s)")) + self.actionShowPreviewROILegend.setText(_translate("MainWindow", "Show Preview ROI Legend")) + self.actionEstCalibration.setText(_translate("MainWindow", "Est. Calibration")) + self.actionCreateMosaic.setText(_translate("MainWindow", "Create Mosaic")) + self.actionUseImagData.setText(_translate("MainWindow", "Use Imaginary if Exists")) + self.actionOpenHDFNISTOOC.setText(_translate("MainWindow", "Open HDF OOC (NIST)")) + from . import icons_all_rc diff --git a/crikit/ui/qt_CompositeColor.py b/crikit/ui/qt_CompositeColor.py index 6232e18..7cf1b7b 100644 --- a/crikit/ui/qt_CompositeColor.py +++ b/crikit/ui/qt_CompositeColor.py @@ -2,16 +2,17 @@ # Form implementation generated from reading ui file '.\ui_CompositeColor.ui' # -# Created by: PyQt5 UI code generator 5.8.1 +# Created by: PyQt5 UI code generator 5.12 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") - Form.resize(767, 594) + Form.resize(600, 100) Form.setStyleSheet("font: 10pt \"Arial\";") self.verticalLayout = QtWidgets.QVBoxLayout(Form) self.verticalLayout.setObjectName("verticalLayout") @@ -56,6 +57,8 @@ def setupUi(self, Form): self.verticalLayoutBGColor.addWidget(self.comboBoxBGColor) self.horizontalLayout.addLayout(self.verticalLayoutBGColor) self.verticalLayout.addWidget(self.frame) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem) self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) @@ -69,3 +72,4 @@ def retranslateUi(self, Form): self.comboBoxColorMode.setItemText(2, _translate("Form", "Absorption v2")) self.labelBGColor.setText(_translate("Form", "Background Color")) + diff --git a/crikit/ui/qt_HDFLoad.py b/crikit/ui/qt_HDFLoad.py deleted file mode 100644 index 7d3e15d..0000000 --- a/crikit/ui/qt_HDFLoad.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '.\ui_HDFLoad.ui' -# -# Created by: PyQt5 UI code generator 5.5.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(845, 588) - Dialog.setStyleSheet("font: 10pt \"Arial\";") - self.verticalLayout_2 = QtWidgets.QVBoxLayout(Dialog) - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint) - self.verticalLayout.setObjectName("verticalLayout") - self.topHL = QtWidgets.QHBoxLayout() - self.topHL.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint) - self.topHL.setObjectName("topHL") - self.dataSetVL = QtWidgets.QVBoxLayout() - self.dataSetVL.setObjectName("dataSetVL") - self.label_1 = QtWidgets.QLabel(Dialog) - self.label_1.setObjectName("label_1") - self.dataSetVL.addWidget(self.label_1) - self.dataGroupSelect = QtWidgets.QComboBox(Dialog) - self.dataGroupSelect.setObjectName("dataGroupSelect") - self.dataSetVL.addWidget(self.dataGroupSelect) - self.label_2 = QtWidgets.QLabel(Dialog) - self.label_2.setObjectName("label_2") - self.dataSetVL.addWidget(self.label_2) - self.dataSetList = QtWidgets.QListWidget(Dialog) - self.dataSetList.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed|QtWidgets.QAbstractItemView.SelectedClicked) - self.dataSetList.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) - self.dataSetList.setObjectName("dataSetList") - self.dataSetVL.addWidget(self.dataSetList) - self.label_3 = QtWidgets.QLabel(Dialog) - self.label_3.setObjectName("label_3") - self.dataSetVL.addWidget(self.label_3) - self.filterIncludeString = QtWidgets.QLineEdit(Dialog) - self.filterIncludeString.setObjectName("filterIncludeString") - self.dataSetVL.addWidget(self.filterIncludeString) - self.label_4 = QtWidgets.QLabel(Dialog) - self.label_4.setObjectName("label_4") - self.dataSetVL.addWidget(self.label_4) - self.filterExcludeString = QtWidgets.QLineEdit(Dialog) - self.filterExcludeString.setObjectName("filterExcludeString") - self.dataSetVL.addWidget(self.filterExcludeString) - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.filterButton = QtWidgets.QPushButton(Dialog) - self.filterButton.setObjectName("filterButton") - self.horizontalLayout.addWidget(self.filterButton) - self.resetFilter = QtWidgets.QPushButton(Dialog) - self.resetFilter.setObjectName("resetFilter") - self.horizontalLayout.addWidget(self.resetFilter) - self.dataSetVL.addLayout(self.horizontalLayout) - self.topHL.addLayout(self.dataSetVL) - self.attribVL = QtWidgets.QVBoxLayout() - self.attribVL.setObjectName("attribVL") - self.label_5 = QtWidgets.QLabel(Dialog) - self.label_5.setObjectName("label_5") - self.attribVL.addWidget(self.label_5) - self.currentDatasetText = QtWidgets.QTextBrowser(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.currentDatasetText.sizePolicy().hasHeightForWidth()) - self.currentDatasetText.setSizePolicy(sizePolicy) - self.currentDatasetText.setMaximumSize(QtCore.QSize(16777215, 100)) - self.currentDatasetText.setObjectName("currentDatasetText") - self.attribVL.addWidget(self.currentDatasetText) - self.label_6 = QtWidgets.QLabel(Dialog) - self.label_6.setObjectName("label_6") - self.attribVL.addWidget(self.label_6) - self.dataSetAttribs = QtWidgets.QTableWidget(Dialog) - self.dataSetAttribs.setStyleSheet("") - self.dataSetAttribs.setColumnCount(2) - self.dataSetAttribs.setObjectName("dataSetAttribs") - self.dataSetAttribs.setRowCount(0) - item = QtWidgets.QTableWidgetItem() - font = QtGui.QFont() - font.setPointSize(10) - item.setFont(font) - item.setBackground(QtGui.QColor(121, 121, 121)) - brush = QtGui.QBrush(QtGui.QColor(91, 91, 91)) - brush.setStyle(QtCore.Qt.SolidPattern) - item.setForeground(brush) - self.dataSetAttribs.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - item.setBackground(QtGui.QColor(123, 123, 123)) - brush = QtGui.QBrush(QtGui.QColor(91, 91, 91)) - brush.setStyle(QtCore.Qt.SolidPattern) - item.setForeground(brush) - self.dataSetAttribs.setHorizontalHeaderItem(1, item) - self.dataSetAttribs.horizontalHeader().setCascadingSectionResizes(True) - self.dataSetAttribs.horizontalHeader().setDefaultSectionSize(200) - self.dataSetAttribs.horizontalHeader().setHighlightSections(False) - self.dataSetAttribs.horizontalHeader().setSortIndicatorShown(True) - self.dataSetAttribs.horizontalHeader().setStretchLastSection(True) - self.dataSetAttribs.verticalHeader().setVisible(False) - self.dataSetAttribs.verticalHeader().setHighlightSections(False) - self.attribVL.addWidget(self.dataSetAttribs) - self.label_7 = QtWidgets.QLabel(Dialog) - self.label_7.setObjectName("label_7") - self.attribVL.addWidget(self.label_7) - self.dataSetMemo = QtWidgets.QTextBrowser(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.dataSetMemo.sizePolicy().hasHeightForWidth()) - self.dataSetMemo.setSizePolicy(sizePolicy) - self.dataSetMemo.setMaximumSize(QtCore.QSize(16777215, 100)) - self.dataSetMemo.setObjectName("dataSetMemo") - self.attribVL.addWidget(self.dataSetMemo) - self.topHL.addLayout(self.attribVL) - self.verticalLayout.addLayout(self.topHL) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setContentsMargins(-1, 10, -1, -1) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem) - self.pushButtonOk = QtWidgets.QPushButton(Dialog) - self.pushButtonOk.setObjectName("pushButtonOk") - self.horizontalLayout_2.addWidget(self.pushButtonOk) - self.pushButtonCancel = QtWidgets.QPushButton(Dialog) - self.pushButtonCancel.setObjectName("pushButtonCancel") - self.horizontalLayout_2.addWidget(self.pushButtonCancel) - self.verticalLayout.addLayout(self.horizontalLayout_2) - self.verticalLayout_2.addLayout(self.verticalLayout) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "HDF File Inspector")) - self.label_1.setText(_translate("Dialog", "Groups Containing Datasets")) - self.label_2.setText(_translate("Dialog", "Datasets")) - self.label_3.setText(_translate("Dialog", "

Include Entires with Substring (separate by \',\' [comma])

")) - self.label_4.setText(_translate("Dialog", "

Exclude Entires with Substring (separate by \',\' [comma])

")) - self.filterButton.setText(_translate("Dialog", "Filter List")) - self.resetFilter.setText(_translate("Dialog", "Reset List")) - self.label_5.setText(_translate("Dialog", "Current Selection")) - self.label_6.setText(_translate("Dialog", "Atrribute Table")) - self.dataSetAttribs.setSortingEnabled(True) - item = self.dataSetAttribs.horizontalHeaderItem(0) - item.setText(_translate("Dialog", "Attribute")) - item = self.dataSetAttribs.horizontalHeaderItem(1) - item.setText(_translate("Dialog", "Value")) - self.label_7.setText(_translate("Dialog", "Dataset Information (Memo)")) - self.pushButtonOk.setText(_translate("Dialog", "OK")) - self.pushButtonCancel.setText(_translate("Dialog", "Cancel")) - diff --git a/crikit/ui/qt_Mosaic.py b/crikit/ui/qt_Mosaic.py new file mode 100644 index 0000000..284bdd4 --- /dev/null +++ b/crikit/ui/qt_Mosaic.py @@ -0,0 +1,485 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '.\ui_Mosaic.ui' +# +# Created by: PyQt5 UI code generator 5.9.2 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1200, 915) + MainWindow.setMaximumSize(QtCore.QSize(2000, 16777215)) + MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout_2.setObjectName("gridLayout_2") + self.verticalLayout_5 = QtWidgets.QVBoxLayout() + self.verticalLayout_5.setContentsMargins(0, -1, -1, -1) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.frame = QtWidgets.QFrame(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMinimumSize(QtCore.QSize(500, 0)) + self.frame.setMaximumSize(QtCore.QSize(500, 16777215)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame.setObjectName("frame") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.frame) + self.verticalLayout_4.setContentsMargins(3, 3, 3, 3) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.verticalLayoutOptions = QtWidgets.QVBoxLayout() + self.verticalLayoutOptions.setSpacing(1) + self.verticalLayoutOptions.setObjectName("verticalLayoutOptions") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setContentsMargins(0, 0, -1, -1) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setContentsMargins(-1, 0, -1, -1) + self.verticalLayout.setObjectName("verticalLayout") + self.label_5 = QtWidgets.QLabel(self.frame) + self.label_5.setObjectName("label_5") + self.verticalLayout.addWidget(self.label_5, 0, QtCore.Qt.AlignRight) + self.spinBoxMRows = QtWidgets.QSpinBox(self.frame) + self.spinBoxMRows.setMinimumSize(QtCore.QSize(50, 0)) + self.spinBoxMRows.setMaximumSize(QtCore.QSize(50, 16777215)) + self.spinBoxMRows.setMinimum(1) + self.spinBoxMRows.setObjectName("spinBoxMRows") + self.verticalLayout.addWidget(self.spinBoxMRows, 0, QtCore.Qt.AlignRight) + self.horizontalLayout_2.addLayout(self.verticalLayout) + self.verticalLayout_3 = QtWidgets.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.label_6 = QtWidgets.QLabel(self.frame) + self.label_6.setObjectName("label_6") + self.verticalLayout_3.addWidget(self.label_6, 0, QtCore.Qt.AlignRight) + self.spinBoxNCols = QtWidgets.QSpinBox(self.frame) + self.spinBoxNCols.setMinimumSize(QtCore.QSize(50, 0)) + self.spinBoxNCols.setMaximumSize(QtCore.QSize(50, 16777215)) + self.spinBoxNCols.setMinimum(1) + self.spinBoxNCols.setMaximum(300) + self.spinBoxNCols.setProperty("value", 1) + self.spinBoxNCols.setObjectName("spinBoxNCols") + self.verticalLayout_3.addWidget(self.spinBoxNCols, 0, QtCore.Qt.AlignRight) + self.horizontalLayout_2.addLayout(self.verticalLayout_3) + self.verticalLayoutOptions.addLayout(self.horizontalLayout_2) + spacerItem = QtWidgets.QSpacerItem(20, 15, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayoutOptions.addItem(spacerItem) + self.label = QtWidgets.QLabel(self.frame) + self.label.setObjectName("label") + self.verticalLayoutOptions.addWidget(self.label, 0, QtCore.Qt.AlignRight) + self.spinBoxStartRow = QtWidgets.QSpinBox(self.frame) + self.spinBoxStartRow.setMinimumSize(QtCore.QSize(50, 0)) + self.spinBoxStartRow.setMaximumSize(QtCore.QSize(50, 16777215)) + self.spinBoxStartRow.setMaximum(500) + self.spinBoxStartRow.setObjectName("spinBoxStartRow") + self.verticalLayoutOptions.addWidget(self.spinBoxStartRow, 0, QtCore.Qt.AlignRight) + spacerItem1 = QtWidgets.QSpacerItem(20, 15, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayoutOptions.addItem(spacerItem1) + self.label_2 = QtWidgets.QLabel(self.frame) + self.label_2.setObjectName("label_2") + self.verticalLayoutOptions.addWidget(self.label_2, 0, QtCore.Qt.AlignRight) + self.spinBoxEndRow = QtWidgets.QSpinBox(self.frame) + self.spinBoxEndRow.setMinimumSize(QtCore.QSize(50, 0)) + self.spinBoxEndRow.setMaximumSize(QtCore.QSize(50, 16777215)) + self.spinBoxEndRow.setMaximum(500) + self.spinBoxEndRow.setObjectName("spinBoxEndRow") + self.verticalLayoutOptions.addWidget(self.spinBoxEndRow, 0, QtCore.Qt.AlignRight) + spacerItem2 = QtWidgets.QSpacerItem(20, 15, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayoutOptions.addItem(spacerItem2) + self.label_3 = QtWidgets.QLabel(self.frame) + self.label_3.setObjectName("label_3") + self.verticalLayoutOptions.addWidget(self.label_3, 0, QtCore.Qt.AlignRight) + self.spinBoxStartCol = QtWidgets.QSpinBox(self.frame) + self.spinBoxStartCol.setMinimumSize(QtCore.QSize(50, 0)) + self.spinBoxStartCol.setMaximumSize(QtCore.QSize(50, 16777215)) + self.spinBoxStartCol.setMaximum(500) + self.spinBoxStartCol.setObjectName("spinBoxStartCol") + self.verticalLayoutOptions.addWidget(self.spinBoxStartCol, 0, QtCore.Qt.AlignRight) + spacerItem3 = QtWidgets.QSpacerItem(20, 15, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayoutOptions.addItem(spacerItem3) + self.label_4 = QtWidgets.QLabel(self.frame) + self.label_4.setObjectName("label_4") + self.verticalLayoutOptions.addWidget(self.label_4, 0, QtCore.Qt.AlignRight) + self.spinBoxEndCol = QtWidgets.QSpinBox(self.frame) + self.spinBoxEndCol.setMinimumSize(QtCore.QSize(50, 0)) + self.spinBoxEndCol.setMaximumSize(QtCore.QSize(50, 16777215)) + self.spinBoxEndCol.setMaximum(500) + self.spinBoxEndCol.setObjectName("spinBoxEndCol") + self.verticalLayoutOptions.addWidget(self.spinBoxEndCol, 0, QtCore.Qt.AlignRight) + self.checkBoxCompress = QtWidgets.QCheckBox(self.frame) + self.checkBoxCompress.setObjectName("checkBoxCompress") + self.verticalLayoutOptions.addWidget(self.checkBoxCompress, 0, QtCore.Qt.AlignRight) + spacerItem4 = QtWidgets.QSpacerItem(20, 5, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayoutOptions.addItem(spacerItem4) + self.label_8 = QtWidgets.QLabel(self.frame) + self.label_8.setObjectName("label_8") + self.verticalLayoutOptions.addWidget(self.label_8, 0, QtCore.Qt.AlignLeft) + self.comboBoxRowCol = QtWidgets.QComboBox(self.frame) + self.comboBoxRowCol.setMaximumSize(QtCore.QSize(100, 16777215)) + self.comboBoxRowCol.setObjectName("comboBoxRowCol") + self.comboBoxRowCol.addItem("") + self.comboBoxRowCol.addItem("") + self.verticalLayoutOptions.addWidget(self.comboBoxRowCol, 0, QtCore.Qt.AlignLeft) + self.checkBoxFlipH = QtWidgets.QCheckBox(self.frame) + self.checkBoxFlipH.setMaximumSize(QtCore.QSize(120, 16777215)) + self.checkBoxFlipH.setObjectName("checkBoxFlipH") + self.verticalLayoutOptions.addWidget(self.checkBoxFlipH, 0, QtCore.Qt.AlignLeft) + self.checkBoxFlipV = QtWidgets.QCheckBox(self.frame) + self.checkBoxFlipV.setMaximumSize(QtCore.QSize(110, 16777215)) + self.checkBoxFlipV.setObjectName("checkBoxFlipV") + self.verticalLayoutOptions.addWidget(self.checkBoxFlipV, 0, QtCore.Qt.AlignLeft) + self.checkBoxTranspose = QtWidgets.QCheckBox(self.frame) + self.checkBoxTranspose.setMaximumSize(QtCore.QSize(110, 16777215)) + self.checkBoxTranspose.setObjectName("checkBoxTranspose") + self.verticalLayoutOptions.addWidget(self.checkBoxTranspose, 0, QtCore.Qt.AlignLeft) + self.verticalLayout_4.addLayout(self.verticalLayoutOptions) + self.label_7 = QtWidgets.QLabel(self.frame) + self.label_7.setObjectName("label_7") + self.verticalLayout_4.addWidget(self.label_7, 0, QtCore.Qt.AlignLeft) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setContentsMargins(-1, 0, -1, -1) + self.horizontalLayout_3.setSpacing(2) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem5) + self.pushButtonMoveUp = QtWidgets.QPushButton(self.frame) + self.pushButtonMoveUp.setMaximumSize(QtCore.QSize(50, 16777215)) + self.pushButtonMoveUp.setText("") + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/arrow-circle-top-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButtonMoveUp.setIcon(icon) + self.pushButtonMoveUp.setObjectName("pushButtonMoveUp") + self.horizontalLayout_3.addWidget(self.pushButtonMoveUp) + self.pushButtonMoveDown = QtWidgets.QPushButton(self.frame) + self.pushButtonMoveDown.setMaximumSize(QtCore.QSize(50, 16777215)) + self.pushButtonMoveDown.setText("") + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/arrow-circle-bottom-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButtonMoveDown.setIcon(icon1) + self.pushButtonMoveDown.setObjectName("pushButtonMoveDown") + self.horizontalLayout_3.addWidget(self.pushButtonMoveDown) + spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem6) + self.pushButtonDeleteDataset = QtWidgets.QPushButton(self.frame) + self.pushButtonDeleteDataset.setMaximumSize(QtCore.QSize(50, 16777215)) + self.pushButtonDeleteDataset.setText("") + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/minus-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButtonDeleteDataset.setIcon(icon2) + self.pushButtonDeleteDataset.setObjectName("pushButtonDeleteDataset") + self.horizontalLayout_3.addWidget(self.pushButtonDeleteDataset) + self.pushButtonAddDataset = QtWidgets.QPushButton(self.frame) + self.pushButtonAddDataset.setMaximumSize(QtCore.QSize(50, 16777215)) + self.pushButtonAddDataset.setText("") + icon3 = QtGui.QIcon() + icon3.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/plus-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButtonAddDataset.setIcon(icon3) + self.pushButtonAddDataset.setObjectName("pushButtonAddDataset") + self.horizontalLayout_3.addWidget(self.pushButtonAddDataset) + spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem7) + self.verticalLayout_4.addLayout(self.horizontalLayout_3) + self.verticalLayout_5.addWidget(self.frame, 0, QtCore.Qt.AlignRight) + spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_5.addItem(spacerItem8) + self.gridLayout_2.addLayout(self.verticalLayout_5, 0, 2, 1, 1) + self.gridLayout_3 = QtWidgets.QGridLayout() + self.gridLayout_3.setObjectName("gridLayout_3") + self.labelWavenumber_2 = QtWidgets.QLabel(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.labelWavenumber_2.sizePolicy().hasHeightForWidth()) + self.labelWavenumber_2.setSizePolicy(sizePolicy) + self.labelWavenumber_2.setMinimumSize(QtCore.QSize(120, 20)) + self.labelWavenumber_2.setMaximumSize(QtCore.QSize(1000, 20)) + self.labelWavenumber_2.setTextFormat(QtCore.Qt.AutoText) + self.labelWavenumber_2.setAlignment(QtCore.Qt.AlignCenter) + self.labelWavenumber_2.setObjectName("labelWavenumber_2") + self.gridLayout_3.addWidget(self.labelWavenumber_2, 1, 0, 1, 1, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom) + self.lineEditPix = QtWidgets.QLineEdit(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEditPix.sizePolicy().hasHeightForWidth()) + self.lineEditPix.setSizePolicy(sizePolicy) + self.lineEditPix.setMinimumSize(QtCore.QSize(100, 30)) + self.lineEditPix.setMaximumSize(QtCore.QSize(100, 30)) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(14) + font.setBold(False) + font.setItalic(False) + font.setWeight(50) + self.lineEditPix.setFont(font) + self.lineEditPix.setStyleSheet("font: 14pt \"Arial\";") + self.lineEditPix.setObjectName("lineEditPix") + self.gridLayout_3.addWidget(self.lineEditPix, 0, 0, 1, 1, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom) + self.lineEditFreq = QtWidgets.QLineEdit(self.centralwidget) + self.lineEditFreq.setEnabled(True) + self.lineEditFreq.setMinimumSize(QtCore.QSize(100, 30)) + self.lineEditFreq.setMaximumSize(QtCore.QSize(100, 30)) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(198, 198, 198)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush) + brush = QtGui.QBrush(QtGui.QColor(198, 198, 198)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush) + brush = QtGui.QBrush(QtGui.QColor(240, 240, 240)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush) + self.lineEditFreq.setPalette(palette) + self.lineEditFreq.setText("") + self.lineEditFreq.setReadOnly(True) + self.lineEditFreq.setObjectName("lineEditFreq") + self.gridLayout_3.addWidget(self.lineEditFreq, 0, 1, 1, 1, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom) + self.label_9 = QtWidgets.QLabel(self.centralwidget) + self.label_9.setObjectName("label_9") + self.gridLayout_3.addWidget(self.label_9, 1, 1, 1, 1, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom) + self.sliderFreq = QtWidgets.QScrollBar(self.centralwidget) + self.sliderFreq.setMinimumSize(QtCore.QSize(200, 30)) + self.sliderFreq.setProperty("value", 10) + self.sliderFreq.setOrientation(QtCore.Qt.Horizontal) + self.sliderFreq.setObjectName("sliderFreq") + self.gridLayout_3.addWidget(self.sliderFreq, 2, 0, 1, 2, QtCore.Qt.AlignBottom) + spacerItem9 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.gridLayout_3.addItem(spacerItem9, 3, 0, 1, 1) + self.gridLayout_2.addLayout(self.gridLayout_3, 2, 0, 1, 1) + self.frameMosaicImg = QtWidgets.QFrame(self.centralwidget) + self.frameMosaicImg.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frameMosaicImg.setFrameShadow(QtWidgets.QFrame.Plain) + self.frameMosaicImg.setObjectName("frameMosaicImg") + self.gridLayout = QtWidgets.QGridLayout(self.frameMosaicImg) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayoutMPL = QtWidgets.QVBoxLayout() + self.verticalLayoutMPL.setObjectName("verticalLayoutMPL") + spacerItem10 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.verticalLayoutMPL.addItem(spacerItem10) + self.gridLayout.addLayout(self.verticalLayoutMPL, 0, 0, 1, 1) + spacerItem11 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.gridLayout.addItem(spacerItem11, 1, 0, 1, 1) + self.gridLayout_2.addWidget(self.frameMosaicImg, 0, 0, 1, 1) + self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) + self.tabWidget.setMinimumSize(QtCore.QSize(500, 0)) + self.tabWidget.setMaximumSize(QtCore.QSize(500, 16777215)) + self.tabWidget.setObjectName("tabWidget") + self.tab_3 = QtWidgets.QWidget() + self.tab_3.setObjectName("tab_3") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.tab_3) + self.horizontalLayout.setObjectName("horizontalLayout") + self.frame_2 = QtWidgets.QFrame(self.tab_3) + self.frame_2.setMaximumSize(QtCore.QSize(400, 16777215)) + self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame_2.setObjectName("frame_2") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame_2) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.label_10 = QtWidgets.QLabel(self.frame_2) + self.label_10.setObjectName("label_10") + self.verticalLayout_2.addWidget(self.label_10) + self.spinBoxIntercept = QtWidgets.QDoubleSpinBox(self.frame_2) + self.spinBoxIntercept.setDecimals(10) + self.spinBoxIntercept.setMinimum(-100000000.0) + self.spinBoxIntercept.setMaximum(100000000.0) + self.spinBoxIntercept.setProperty("value", 832.551012) + self.spinBoxIntercept.setObjectName("spinBoxIntercept") + self.verticalLayout_2.addWidget(self.spinBoxIntercept) + spacerItem12 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem12) + self.label_11 = QtWidgets.QLabel(self.frame_2) + self.label_11.setObjectName("label_11") + self.verticalLayout_2.addWidget(self.label_11) + self.spinBoxSlope = QtWidgets.QDoubleSpinBox(self.frame_2) + self.spinBoxSlope.setDecimals(10) + self.spinBoxSlope.setMinimum(-100000000.0) + self.spinBoxSlope.setMaximum(100000000.0) + self.spinBoxSlope.setProperty("value", -0.165956) + self.spinBoxSlope.setObjectName("spinBoxSlope") + self.verticalLayout_2.addWidget(self.spinBoxSlope) + spacerItem13 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem13) + self.label_12 = QtWidgets.QLabel(self.frame_2) + self.label_12.setObjectName("label_12") + self.verticalLayout_2.addWidget(self.label_12) + self.spinBoxProbe = QtWidgets.QDoubleSpinBox(self.frame_2) + self.spinBoxProbe.setDecimals(5) + self.spinBoxProbe.setMinimum(-1000000000.0) + self.spinBoxProbe.setMaximum(1000000000.0) + self.spinBoxProbe.setProperty("value", 771.461) + self.spinBoxProbe.setObjectName("spinBoxProbe") + self.verticalLayout_2.addWidget(self.spinBoxProbe) + self.label_13 = QtWidgets.QLabel(self.frame_2) + self.label_13.setObjectName("label_13") + self.verticalLayout_2.addWidget(self.label_13) + self.spinBoxCalibWL = QtWidgets.QDoubleSpinBox(self.frame_2) + self.spinBoxCalibWL.setDecimals(10) + self.spinBoxCalibWL.setMinimum(-100000000.0) + self.spinBoxCalibWL.setMaximum(10000000.0) + self.spinBoxCalibWL.setProperty("value", 700.0) + self.spinBoxCalibWL.setObjectName("spinBoxCalibWL") + self.verticalLayout_2.addWidget(self.spinBoxCalibWL) + spacerItem14 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem14) + self.label_14 = QtWidgets.QLabel(self.frame_2) + self.label_14.setObjectName("label_14") + self.verticalLayout_2.addWidget(self.label_14) + self.spinBoxCenterWL = QtWidgets.QDoubleSpinBox(self.frame_2) + self.spinBoxCenterWL.setDecimals(10) + self.spinBoxCenterWL.setMinimum(-100000000.0) + self.spinBoxCenterWL.setMaximum(10000000.0) + self.spinBoxCenterWL.setProperty("value", 700.0) + self.spinBoxCenterWL.setObjectName("spinBoxCenterWL") + self.verticalLayout_2.addWidget(self.spinBoxCenterWL) + spacerItem15 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem15) + self.horizontalLayout.addWidget(self.frame_2) + self.checkBoxSpectFromData = QtWidgets.QCheckBox(self.tab_3) + self.checkBoxSpectFromData.setEnabled(False) + font = QtGui.QFont() + font.setPointSize(10) + self.checkBoxSpectFromData.setFont(font) + self.checkBoxSpectFromData.setIconSize(QtCore.QSize(20, 20)) + self.checkBoxSpectFromData.setCheckable(True) + self.checkBoxSpectFromData.setObjectName("checkBoxSpectFromData") + self.horizontalLayout.addWidget(self.checkBoxSpectFromData) + self.tabWidget.addTab(self.tab_3, "") + self.tab_4 = QtWidgets.QWidget() + self.tab_4.setObjectName("tab_4") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.tab_4) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.frame_3 = QtWidgets.QFrame(self.tab_4) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame_3.setObjectName("frame_3") + self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.frame_3) + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_15 = QtWidgets.QLabel(self.frame_3) + self.label_15.setObjectName("label_15") + self.verticalLayout_6.addWidget(self.label_15) + self.spinBoxXStepSize = QtWidgets.QDoubleSpinBox(self.frame_3) + self.spinBoxXStepSize.setEnabled(False) + self.spinBoxXStepSize.setReadOnly(False) + self.spinBoxXStepSize.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.spinBoxXStepSize.setDecimals(10) + self.spinBoxXStepSize.setMinimum(-1.0) + self.spinBoxXStepSize.setMaximum(1000000.0) + self.spinBoxXStepSize.setSingleStep(0.1) + self.spinBoxXStepSize.setProperty("value", -1.0) + self.spinBoxXStepSize.setObjectName("spinBoxXStepSize") + self.verticalLayout_6.addWidget(self.spinBoxXStepSize) + self.label_16 = QtWidgets.QLabel(self.frame_3) + self.label_16.setObjectName("label_16") + self.verticalLayout_6.addWidget(self.label_16) + self.spinBoxYStepSize = QtWidgets.QDoubleSpinBox(self.frame_3) + self.spinBoxYStepSize.setEnabled(False) + self.spinBoxYStepSize.setReadOnly(False) + self.spinBoxYStepSize.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.spinBoxYStepSize.setDecimals(10) + self.spinBoxYStepSize.setMinimum(-1.0) + self.spinBoxYStepSize.setMaximum(1000000.0) + self.spinBoxYStepSize.setSingleStep(0.1) + self.spinBoxYStepSize.setProperty("value", -1.0) + self.spinBoxYStepSize.setObjectName("spinBoxYStepSize") + self.verticalLayout_6.addWidget(self.spinBoxYStepSize) + spacerItem16 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_6.addItem(spacerItem16) + self.horizontalLayout_4.addWidget(self.frame_3) + self.checkBoxSpaceFromData = QtWidgets.QCheckBox(self.tab_4) + self.checkBoxSpaceFromData.setEnabled(False) + font = QtGui.QFont() + font.setPointSize(10) + self.checkBoxSpaceFromData.setFont(font) + self.checkBoxSpaceFromData.setCheckable(True) + self.checkBoxSpaceFromData.setObjectName("checkBoxSpaceFromData") + self.horizontalLayout_4.addWidget(self.checkBoxSpaceFromData) + self.tabWidget.addTab(self.tab_4, "") + self.gridLayout_2.addWidget(self.tabWidget, 2, 2, 1, 1, QtCore.Qt.AlignRight) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 26)) + self.menubar.setObjectName("menubar") + self.menuFile = QtWidgets.QMenu(self.menubar) + self.menuFile.setObjectName("menuFile") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + self.toolBar = QtWidgets.QToolBar(MainWindow) + self.toolBar.setObjectName("toolBar") + MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) + self.actionAddFromHDF = QtWidgets.QAction(MainWindow) + icon4 = QtGui.QIcon() + icon4.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/envelope-open-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionAddFromHDF.setIcon(icon4) + self.actionAddFromHDF.setObjectName("actionAddFromHDF") + self.actionSaveToHDF5 = QtWidgets.QAction(MainWindow) + icon5 = QtGui.QIcon() + icon5.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/envelope-closed-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionSaveToHDF5.setIcon(icon5) + self.actionSaveToHDF5.setObjectName("actionSaveToHDF5") + self.actionExit = QtWidgets.QAction(MainWindow) + icon6 = QtGui.QIcon() + icon6.addPixmap(QtGui.QPixmap(":/icons/open-iconic-master/png/account-logout-4x.png"), QtGui.QIcon.Normal, QtGui.QIcon.On) + self.actionExit.setIcon(icon6) + self.actionExit.setObjectName("actionExit") + self.menuFile.addAction(self.actionAddFromHDF) + self.menuFile.addAction(self.actionSaveToHDF5) + self.menuFile.addSeparator() + self.menuFile.addAction(self.actionExit) + self.menubar.addAction(self.menuFile.menuAction()) + self.toolBar.addAction(self.actionAddFromHDF) + self.toolBar.addAction(self.actionSaveToHDF5) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionExit) + + self.retranslateUi(MainWindow) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "Make Mosaic Dataset")) + self.label_5.setText(_translate("MainWindow", "M Rows")) + self.label_6.setText(_translate("MainWindow", "N Cols")) + self.label.setText(_translate("MainWindow", "Trim Row Start")) + self.label_2.setText(_translate("MainWindow", "Trim Row End")) + self.label_3.setText(_translate("MainWindow", "Trim Col Start")) + self.label_4.setText(_translate("MainWindow", "Trim Col End")) + self.checkBoxCompress.setText(_translate("MainWindow", "Compress")) + self.label_8.setText(_translate("MainWindow", "Row / Column First")) + self.comboBoxRowCol.setItemText(0, _translate("MainWindow", "Row")) + self.comboBoxRowCol.setItemText(1, _translate("MainWindow", "Column")) + self.checkBoxFlipH.setText(_translate("MainWindow", "Flip Horizontally")) + self.checkBoxFlipV.setText(_translate("MainWindow", "Flip Vertically")) + self.checkBoxTranspose.setText(_translate("MainWindow", "Transpose")) + self.label_7.setText(_translate("MainWindow", "Order of Inputs (Drag to Move)")) + self.labelWavenumber_2.setText(_translate("MainWindow", "Frequency Pixel")) + self.label_9.setText(_translate("MainWindow", "Estimated Frequency (cm-1)")) + self.label_10.setText(_translate("MainWindow", "Wavelength Intercept (nm)")) + self.label_11.setText(_translate("MainWindow", "Wavelength Slope (nm/pix)")) + self.label_12.setText(_translate("MainWindow", "Probe Wavelength (nm)")) + self.label_13.setText(_translate("MainWindow", "Calibration Wavelength (nm)")) + self.label_14.setText(_translate("MainWindow", "Current Center Wavelength (nm)")) + self.checkBoxSpectFromData.setText(_translate("MainWindow", "Loaded from Data")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Spectral Calibration")) + self.label_15.setText(_translate("MainWindow", "X Step Size (um)")) + self.label_16.setText(_translate("MainWindow", "Y Step Size (um)")) + self.checkBoxSpaceFromData.setText(_translate("MainWindow", "Loaded from Data")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "Spatial Calibration")) + self.menuFile.setTitle(_translate("MainWindow", "File")) + self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) + self.actionAddFromHDF.setText(_translate("MainWindow", "Add from HDF5")) + self.actionAddFromHDF.setShortcut(_translate("MainWindow", "Ctrl+O")) + self.actionSaveToHDF5.setText(_translate("MainWindow", "Save to HDF5")) + self.actionSaveToHDF5.setShortcut(_translate("MainWindow", "Ctrl+S")) + self.actionExit.setText(_translate("MainWindow", "Exit")) + +from . import icons_all_rc diff --git a/crikit/ui/qt_PlotEffect.py b/crikit/ui/qt_PlotEffect.py index f331c95..d59376d 100644 --- a/crikit/ui/qt_PlotEffect.py +++ b/crikit/ui/qt_PlotEffect.py @@ -1,17 +1,18 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '.\qt5-creator\ui_PlotEffect.ui' +# Form implementation generated from reading ui file '.\ui_PlotEffect.ui' # -# Created by: PyQt5 UI code generator 5.5.1 +# Created by: PyQt5 UI code generator 5.12 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") - Dialog.resize(640, 977) + Dialog.resize(650, 200) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() @@ -57,4 +58,5 @@ def retranslateUi(self, Dialog): self.pushButtonOk.setText(_translate("Dialog", "Ok")) self.pushButtonCancel.setText(_translate("Dialog", "Cancel")) + from . import icons_all_rc diff --git a/crikit/ui/qt_PlotEffect_ALS.py b/crikit/ui/qt_PlotEffect_ALS.py index 3cbc607..98c3c7c 100644 --- a/crikit/ui/qt_PlotEffect_ALS.py +++ b/crikit/ui/qt_PlotEffect_ALS.py @@ -2,16 +2,17 @@ # Form implementation generated from reading ui file '.\ui_PlotEffect_ALS.ui' # -# Created by: PyQt5 UI code generator 5.5.1 +# Created by: PyQt5 UI code generator 5.12 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") - Form.resize(738, 180) + Form.resize(800, 180) Form.setStyleSheet("font: 10pt \"Arial\";") self.gridLayout = QtWidgets.QGridLayout(Form) self.gridLayout.setObjectName("gridLayout") @@ -178,3 +179,4 @@ def retranslateUi(self, Form): self.label_2.setText(_translate("Form", "Lambda (smoothness)")) self.label_4.setText(_translate("Form", "Fix End-Points")) + diff --git a/crikit/ui/qt_PlotEffect_ALS2.py b/crikit/ui/qt_PlotEffect_ALS2.py new file mode 100644 index 0000000..a1baf3e --- /dev/null +++ b/crikit/ui/qt_PlotEffect_ALS2.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '.\ui_PlotEffect_ALS2.ui' +# +# Created by: PyQt5 UI code generator 5.12 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(800, 282) + Form.setStyleSheet("font: 10pt \"Arial\";") + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setObjectName("gridLayout") + self.tableWidgetAsym = QtWidgets.QTableWidget(Form) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tableWidgetAsym.sizePolicy().hasHeightForWidth()) + self.tableWidgetAsym.setSizePolicy(sizePolicy) + self.tableWidgetAsym.setMinimumSize(QtCore.QSize(0, 10)) + self.tableWidgetAsym.setBaseSize(QtCore.QSize(0, 140)) + self.tableWidgetAsym.setFrameShadow(QtWidgets.QFrame.Plain) + self.tableWidgetAsym.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) + self.tableWidgetAsym.setRowCount(0) + self.tableWidgetAsym.setObjectName("tableWidgetAsym") + self.tableWidgetAsym.setColumnCount(3) + item = QtWidgets.QTableWidgetItem() + self.tableWidgetAsym.setHorizontalHeaderItem(0, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidgetAsym.setHorizontalHeaderItem(1, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidgetAsym.setHorizontalHeaderItem(2, item) + self.tableWidgetAsym.horizontalHeader().setCascadingSectionResizes(True) + self.tableWidgetAsym.horizontalHeader().setDefaultSectionSize(80) + self.tableWidgetAsym.horizontalHeader().setHighlightSections(False) + self.tableWidgetAsym.horizontalHeader().setMinimumSectionSize(20) + self.tableWidgetAsym.horizontalHeader().setStretchLastSection(True) + self.gridLayout.addWidget(self.tableWidgetAsym, 3, 0, 1, 1) + self.frame_3 = QtWidgets.QFrame(Form) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame_3.setObjectName("frame_3") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_2.setContentsMargins(5, 5, 5, 5) + self.gridLayout_2.setObjectName("gridLayout_2") + self.verticalLayout_3 = QtWidgets.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.label_3 = QtWidgets.QLabel(self.frame_3) + self.label_3.setObjectName("label_3") + self.verticalLayout_3.addWidget(self.label_3, 0, QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.spinBoxRedux = QtWidgets.QSpinBox(self.frame_3) + self.spinBoxRedux.setMinimum(1) + self.spinBoxRedux.setMaximum(10000) + self.spinBoxRedux.setObjectName("spinBoxRedux") + self.verticalLayout_3.addWidget(self.spinBoxRedux, 0, QtCore.Qt.AlignTop) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_3.addItem(spacerItem) + self.gridLayout_2.addLayout(self.verticalLayout_3, 0, 1, 1, 1) + self.verticalLayout_2 = QtWidgets.QVBoxLayout() + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.label_2 = QtWidgets.QLabel(self.frame_3) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(10) + font.setBold(False) + font.setItalic(False) + font.setWeight(50) + self.label_2.setFont(font) + self.label_2.setObjectName("label_2") + self.verticalLayout_2.addWidget(self.label_2, 0, QtCore.Qt.AlignLeft) + spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem1) + self.gridLayout_2.addLayout(self.verticalLayout_2, 0, 0, 1, 1) + self.verticalLayout_4 = QtWidgets.QVBoxLayout() + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.label_4 = QtWidgets.QLabel(self.frame_3) + self.label_4.setObjectName("label_4") + self.verticalLayout_4.addWidget(self.label_4, 0, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) + self.checkBox = QtWidgets.QCheckBox(self.frame_3) + self.checkBox.setMinimumSize(QtCore.QSize(20, 20)) + self.checkBox.setText("") + self.checkBox.setChecked(True) + self.checkBox.setObjectName("checkBox") + self.verticalLayout_4.addWidget(self.checkBox, 0, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) + self.gridLayout_2.addLayout(self.verticalLayout_4, 1, 1, 1, 1) + self.gridLayout.addWidget(self.frame_3, 1, 1, 2, 1) + self.frame = QtWidgets.QFrame(Form) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame.setObjectName("frame") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.frame) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label, 0, QtCore.Qt.AlignLeft) + spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem2) + self.label_6 = QtWidgets.QLabel(self.frame) + self.label_6.setObjectName("label_6") + self.verticalLayout.addWidget(self.label_6) + self.spinBoxAsymSubSections = QtWidgets.QSpinBox(self.frame) + self.spinBoxAsymSubSections.setMaximum(5) + self.spinBoxAsymSubSections.setObjectName("spinBoxAsymSubSections") + self.verticalLayout.addWidget(self.spinBoxAsymSubSections) + spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem3) + self.horizontalLayout_2.addLayout(self.verticalLayout) + self.gridLayout.addWidget(self.frame, 1, 0, 1, 1) + self.label_5 = QtWidgets.QLabel(Form) + self.label_5.setObjectName("label_5") + self.gridLayout.addWidget(self.label_5, 0, 0, 1, 1) + self.frame_4 = QtWidgets.QFrame(Form) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame_4.setObjectName("frame_4") + self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.frame_4) + self.verticalLayout_8.setContentsMargins(5, 5, 5, 5) + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.verticalLayout_9 = QtWidgets.QVBoxLayout() + self.verticalLayout_9.setContentsMargins(-1, 0, -1, -1) + self.verticalLayout_9.setSpacing(0) + self.verticalLayout_9.setObjectName("verticalLayout_9") + self.label_9 = QtWidgets.QLabel(self.frame_4) + self.label_9.setObjectName("label_9") + self.verticalLayout_9.addWidget(self.label_9) + self.spinBoxMaxIter = QtWidgets.QSpinBox(self.frame_4) + self.spinBoxMaxIter.setMinimum(1) + self.spinBoxMaxIter.setMaximum(1000000) + self.spinBoxMaxIter.setProperty("value", 100) + self.spinBoxMaxIter.setObjectName("spinBoxMaxIter") + self.verticalLayout_9.addWidget(self.spinBoxMaxIter) + spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_9.addItem(spacerItem4) + self.label_10 = QtWidgets.QLabel(self.frame_4) + self.label_10.setObjectName("label_10") + self.verticalLayout_9.addWidget(self.label_10) + self.verticalLayout_8.addLayout(self.verticalLayout_9) + spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_8.addItem(spacerItem5) + self.gridLayout.addWidget(self.frame_4, 1, 3, 1, 1) + self.verticalLayout_5 = QtWidgets.QVBoxLayout() + self.verticalLayout_5.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setContentsMargins(-1, 0, 0, -1) + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setContentsMargins(-1, 0, -1, -1) + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_7 = QtWidgets.QLabel(Form) + self.label_7.setObjectName("label_7") + self.verticalLayout_6.addWidget(self.label_7) + self.spinBoxWSubSections = QtWidgets.QSpinBox(Form) + self.spinBoxWSubSections.setMaximum(5) + self.spinBoxWSubSections.setObjectName("spinBoxWSubSections") + self.verticalLayout_6.addWidget(self.spinBoxWSubSections) + spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_6.addItem(spacerItem6) + self.horizontalLayout.addLayout(self.verticalLayout_6) + self.verticalLayout_7 = QtWidgets.QVBoxLayout() + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.label_8 = QtWidgets.QLabel(Form) + self.label_8.setObjectName("label_8") + self.verticalLayout_7.addWidget(self.label_8) + spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem7) + self.horizontalLayout.addLayout(self.verticalLayout_7) + self.verticalLayout_5.addLayout(self.horizontalLayout) + self.tableWidgetWeights = QtWidgets.QTableWidget(Form) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tableWidgetWeights.sizePolicy().hasHeightForWidth()) + self.tableWidgetWeights.setSizePolicy(sizePolicy) + self.tableWidgetWeights.setMinimumSize(QtCore.QSize(0, 70)) + self.tableWidgetWeights.setBaseSize(QtCore.QSize(0, 65)) + self.tableWidgetWeights.setObjectName("tableWidgetWeights") + self.tableWidgetWeights.setColumnCount(2) + self.tableWidgetWeights.setRowCount(0) + item = QtWidgets.QTableWidgetItem() + self.tableWidgetWeights.setHorizontalHeaderItem(0, item) + self.tableWidgetWeights.horizontalHeader().setDefaultSectionSize(80) + self.tableWidgetWeights.horizontalHeader().setStretchLastSection(True) + self.verticalLayout_5.addWidget(self.tableWidgetWeights) + self.gridLayout.addLayout(self.verticalLayout_5, 3, 1, 1, 2) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + _translate = QtCore.QCoreApplication.translate + Form.setWindowTitle(_translate("Form", "Form")) + item = self.tableWidgetAsym.horizontalHeaderItem(0) + item.setText(_translate("Form", "Start X")) + item = self.tableWidgetAsym.horizontalHeaderItem(1) + item.setText(_translate("Form", "End X")) + item = self.tableWidgetAsym.horizontalHeaderItem(2) + item.setText(_translate("Form", "P (Asymmetry) Value")) + self.label_3.setText(_translate("Form", "Sub-Sampling Factor")) + self.label_2.setText(_translate("Form", "Lambda (smoothness)")) + self.label_4.setText(_translate("Form", "Fix End-Points")) + self.label.setText(_translate("Form", "Define P (Asymmetry)")) + self.label_6.setText(_translate("Form", "P Subsections")) + self.label_5.setText(_translate("Form", "Fixed=P")) + self.label_9.setText(_translate("Form", "Max Iterations")) + self.label_10.setText(_translate("Form", "Min Difference")) + self.label_7.setText(_translate("Form", "Weighted (Subsections)")) + self.label_8.setText(_translate("Form", "Weight Value")) + item = self.tableWidgetWeights.horizontalHeaderItem(0) + item.setText(_translate("Form", "Start X")) + + diff --git a/crikit/ui/qt_PlotEffect_Calibrate.py b/crikit/ui/qt_PlotEffect_Calibrate.py index 8b4d7a7..a95f182 100644 --- a/crikit/ui/qt_PlotEffect_Calibrate.py +++ b/crikit/ui/qt_PlotEffect_Calibrate.py @@ -2,16 +2,17 @@ # Form implementation generated from reading ui file '.\ui_PlotEffect_Calibrate.ui' # -# Created by: PyQt5 UI code generator 5.5.1 +# Created by: PyQt5 UI code generator 5.12 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") - Form.resize(643, 415) + Form.resize(800, 300) Form.setStyleSheet("font: 10pt \"Arial\";") self.horizontalLayout = QtWidgets.QHBoxLayout(Form) self.horizontalLayout.setObjectName("horizontalLayout") @@ -263,3 +264,4 @@ def retranslateUi(self, Form): self.label_15.setText(_translate("Form", "Measured WN")) self.label_16.setText(_translate("Form", "Correct WN")) + diff --git a/crikit/ui/subui_hdf_load.py b/crikit/ui/subui_hdf_load.py deleted file mode 100644 index 69458a2..0000000 --- a/crikit/ui/subui_hdf_load.py +++ /dev/null @@ -1,223 +0,0 @@ -""" -HDF5 LOAD DATA QDialog (crikit.vis.subguis.h5loadgui) -======================================================= - - H5LoadGUI : A graphical user interface (GUI) to select HDF5 dataset(s) - - Method : H5LoadGUI.getFileDataSets() - - Return (tuple) : (path [str], filename [str], dataset(s) [list], selection_made [bool]) - -""" - - -# Append sys path -import sys as _sys -import os as _os - -# Generic imports for QT-based programs -from PyQt5.QtWidgets import (QApplication as _QApplication, \ -QDialog as _QDialog, QFileDialog as _QFileDialog, \ -QTableWidgetItem as _QTableWidgetItem) - -# Other imports -import numpy as _np -import crikit.utils.h5 as _h5utils - -# Import from Designer-based GUI -from crikit.ui.qt_HDFLoad import Ui_Dialog ### EDIT ### - -class SubUiHDFLoad(_QDialog): ### EDIT ### - """ GUI Loader Class for H5 Files """ - - def __init__(self, parent = None): - - # Generic load/init designer-based GUI - super(SubUiHDFLoad, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - # Set static GUI parameters - - # Set signal(s)-slot(s) connection/actions - - self.ui.pushButtonOk.clicked.connect(self.accept) - self.ui.pushButtonCancel.clicked.connect(self.reject) - self.ui.dataGroupSelect.currentTextChanged.connect(self.datagroupchange) - self.ui.dataSetList.itemClicked.connect(self.datasetselected) - self.ui.filterButton.clicked.connect(self.filterlist) - self.ui.resetFilter.clicked.connect(self.datagroupchange) - # Setup GUI variables - self.path = None - self.filename = None - self.allselect=None - # Initial Actions - - @staticmethod - def getFileDataSets(start_path='./', parent = None): - """ - Retrieve the filename and datasets selected by the user (via GUI) - - Parameters - ---------- - start_path : str - Home directory to start in - - Returns - ---------- - out : (tuple) - path : str - filename : (str) - dataset(s) : (list[str]) - """ - if start_path is None: - start_path = './' - - dialog = SubUiHDFLoad(parent) - - ret_fileopen = dialog.fileopen(start_path) - - if ret_fileopen is None: - return None - - # Execute dialog, which defined by QDialog class returns - # QDialog.Accepted or QDialog.Rejected - ret_dset_select = dialog.exec_() - if ret_dset_select == _QDialog.Rejected: - return None - elif dialog.allselect is None: - return None - else: - return (dialog.path, dialog.filename, dialog.allselect) - - def fileopen(self, start_path='./'): - """ Select HDF5 File """ - - if start_path is None: - start_path = './' - - filename = _QFileDialog.getOpenFileName(self, "Open H5 File", - start_path,\ - "HDF5 Files (*.h5 *.hdf);;All Files (*.*)") - - if filename[0]: - self.filename = filename[0] - self.path = _os.path.dirname(self.filename) + '/' - self.filename = self.filename.split(_os.path.dirname(self.filename))[1][1::] - - self.group_dset_dict = _h5utils.retrieve_group_dataset_dict(self.path + self.filename) - self.ui.dataGroupSelect.clear() - for count in self.group_dset_dict: - self.ui.dataGroupSelect.addItem(count) - return [self.path, self.filename] - else: - return None - def datagroupchange(self): - """ Action : ComboBox containing Groups with DataSets has changed""" - - #self.dsetlist = QListWidget(self.verticalLayoutWidget) - self.ui.dataSetList.clear() - self.ui.dataSetList.addItems(self.group_dset_dict[self.ui.dataGroupSelect.currentText()]) - #print('Changed') - - def datasetselected(self): - """ Action : One or more DataSets were selected from the list """ - - #print('Selection changed') - self.currentdset = self.ui.dataGroupSelect.currentText() + '/' + \ - self.ui.dataSetList.currentItem().text() - -# print('Current Selection : {}'.format(self.currentdset)) - self.allselect = ['/' + str(self.ui.dataGroupSelect.currentText() +\ - '/' + i.text()) for i in self.ui.dataSetList.selectedItems()] - - - if len(self.allselect) == 0: - self.allselect = None - self.ui.currentDatasetText.setText('') - attrs = {} - self.ui.dataSetAttribs.setRowCount(0) - self.ui.dataSetMemo.setText('') - else: - if len(self.allselect) == 1: - self.ui.currentDatasetText.setText(self.currentdset) - else: - self.ui.currentDatasetText.setText(self.currentdset + ' ( + ' +\ - str(len(self.allselect)-1) + ' others)' ) - - self.ui.dataSetAttribs.setSortingEnabled(False) - self.ui.dataSetAttribs.setRowCount(0) - self.ui.dataSetAttribs.setColumnCount(2) - - attrs = _h5utils.retrieve_dataset_attribute_dict(self.path + self.filename,self.currentdset) - - for count, key in enumerate(attrs.keys()): - self.ui.dataSetAttribs.insertRow(self.ui.dataSetAttribs.rowCount()) - self.ui.dataSetAttribs.setItem(count,0,_QTableWidgetItem(str(key))) - temp = attrs[key] - if isinstance(temp,_np.bytes_): - self.ui.dataSetAttribs.setItem(count,1,_QTableWidgetItem(temp.decode())) - else: - self.ui.dataSetAttribs.setItem(count,1,_QTableWidgetItem(str(temp))) - - self.ui.dataSetAttribs.setSortingEnabled(True) - self.ui.dataSetAttribs.sortItems(0) - - try: - self.ui.dataSetMemo.setText(attrs['Memo'].decode()) - except: - pass - - def filterlist(self): - """ Action : Filter available dataset list (.ui.dataSetList) based on - include or exclude strings (or comma-separated strings) - """ - - temp_list = [] - - for count in range(self.ui.dataSetList.count()): - temp_list.append(self.ui.dataSetList.item(count).text()) - - temp_list_filt = temp_list - - # Has strings to Exclude - if self.ui.filterExcludeString.text() != '': - # Convert comma-separated string to list-of-strings - strexclude = str.split(self.ui.filterExcludeString.text(),',') - - # Strip white-space - strexclude = [str.strip(strexclude) for strexclude in strexclude] - - # Exclude Filter - for count in strexclude[0::]: - temp_list_filt = ([i for i in temp_list_filt if str.find(i,count) == -1]) - #print(count) - else: - pass - - # Has strings to Include - if self.ui.filterIncludeString.text() != '': - # Convert comma-separated string to list-of-strings - strinclude = str.split(self.ui.filterIncludeString.text(),',') - - # Strip white-space - strinclude = [str.strip(strinclude) for strinclude in strinclude] - - # Include Filter - for count in strinclude: - temp_list_filt = ([i for i in temp_list_filt if str.find(i,count) != -1]) - else: - pass - - # Update GUI - self.ui.dataSetList.clear() - self.ui.dataSetList.addItems(temp_list_filt) - -if __name__ == '__main__': - - app = _QApplication(_sys.argv) - #win = H5LoadGUI() ### EDIT ### - result = SubUiHDFLoad.getFileDataSets() - print('Result: {}'.format(result)) - - _sys.exit() diff --git a/crikit/ui/widget_ALS.py b/crikit/ui/widget_ALS.py index 2cee0b6..4696973 100644 --- a/crikit/ui/widget_ALS.py +++ b/crikit/ui/widget_ALS.py @@ -8,21 +8,24 @@ """ import numpy as _np +from PyQt5.QtWidgets import QTableWidgetItem as _QTableWidgetItem + from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin as _AbstractPlotEffectPlugin) -from crikit.ui.qt_PlotEffect_ALS import Ui_Form as _Ui_Form +from crikit.ui.qt_PlotEffect_ALS2 import Ui_Form as _Ui_Form from crikit.ui.widget_scientificspin import (ScientificDoubleSpinBox as _SciSpin) from crikit.preprocess.algorithms.als import AlsCvxopt as _Als +from crikit.utils.general import find_nearest as _find_nearest class widgetALS(_AbstractPlotEffectPlugin): """ Widget for PlotEffect that adjusts the parameters appropriate for asymmetric least squares (ALS) - + Parameters ---------- smoothness_param : float, optional (default, 1e3) @@ -30,131 +33,258 @@ class widgetALS(_AbstractPlotEffectPlugin): asym_param : float, optional (default, 1e-4) Assymetry parameter - + redux : int, optional (default, 1) Reduction parameter to sub-sample input signal - + order : int, optional (default, 2) Derivative regularization term. Order=2 for Whittaker-smoother - + fix_end_points : bool, optional (default, False) Weight the baseline endpoints to approach equally the end-points of the data. - + max_iter : int, optional (default, 100) Maximum number of least-squares iterations to perform - + min_diff : float, optional (default, 1e-5) Break iterative calculations if difference is less than min_diff - + parent: QObject Parent - + Methods ------- fcn : Perform ALS detrending - + Signals: changed : a value in the UI has changed """ - + # Parameter dict that will be returned from PlotEffect # Will be updated later in program to contain all parameters # to pass to underlying algorithm - parameters = {'name' : 'ALS', + parameters = {'name' : 'ALS', 'long_name' : 'Asymmetric least squares'} - + # Labeling options for original data plot labels_orig = { 'x_label' : 'Wavenumber (cm$^{-1}$)', 'y_label' : 'Input Int (au)', 'title' : 'Original' } - - # Labeling options for affected data plot + + # Labeling options for affected data plot labels_affected = { 'x_label' : labels_orig['x_label'], 'y_label' : 'Output Int (au)', 'title' : 'Detrended' } - - def __init__(self, asym_param=1e-3, smoothness_param=1, redux=10, - pstart=1e-2, pend=1e-3, fixed_p=True, fix_end_points=True, - max_iter=100, min_diff=1e-6, parent = None): - + + def __init__(self, x=None, rng=None, smoothness_param=1, asym_param=1e-3, redux=10, + order=2, fix_end_points=True, fix_const=1, fix_rng=None, + max_iter=100, min_diff=1e-6, verbose=False, sub_asym_list=None, + sub_w_list=None, parent = None): + super(widgetALS, self).__init__(parent) ### EDIT ### + + self._x = x + self.rng = rng + self.ui = _Ui_Form() self.ui.setupUi(self) - + + + self.sub_asym_list = sub_asym_list + self.sub_w_list = sub_w_list + + # ! Change this into its own function after + # ! the asym table widget is all setup + if not self.sub_asym_list: + self.parameters['asym_param'] = asym_param + else: + self.parameters['asym_param'] = 0*self.x + asym_param + # Update parameter dict self.parameters['smoothness_param'] = smoothness_param - self.parameters['asym_param'] = asym_param - self.parameters['fixed_p'] = fixed_p - self.parameters['asym_param_start'] = pstart - self.parameters['asym_param_end'] = pend + self.parameters['rng'] = rng self.parameters['redux'] = redux + self.parameters['order'] = order self.parameters['fix_end_points'] = fix_end_points + self.parameters['fix_rng'] = fix_rng + self.parameters['fix_const'] = fix_const self.parameters['max_iter'] = max_iter self.parameters['min_diff'] = min_diff - + self.parameters['verbose'] = verbose + self.setup_asym() # Setup controls for asymmetry parameter self.setup_smoothness() # Setup controls for smoothness parameter - + # Redux factor self.ui.spinBoxRedux.setValue(self.parameters['redux']) # Fixed ends self.ui.checkBox.setChecked(self.parameters['fix_end_points']) - + # Max iterations self.ui.spinBoxMaxIter.setValue(self.parameters['max_iter']) - + # Min Difference self.ui.spinBoxMinDiff = _SciSpin() self.ui.verticalLayout_9.insertWidget(4, self.ui.spinBoxMinDiff) self.ui.spinBoxMinDiff.setValue(self.parameters['min_diff']) - + # SIGNALS & SLOTS self.ui.spinBoxP.editingFinished.connect(self.spinBoxChanged) self.ui.spinBoxLambda.editingFinished.connect(self.spinBoxChanged) self.ui.spinBoxRedux.editingFinished.connect(self.spinBoxChanged) - - self.ui.spinBoxPStart.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxPEnd.editingFinished.connect(self.spinBoxChanged) + self.ui.spinBoxMaxIter.editingFinished.connect(self.spinBoxChanged) self.ui.spinBoxMinDiff.editingFinished.connect(self.spinBoxChanged) - - self.ui.radioButtonFixedP.clicked.connect(self.selectFixedOrLog) - self.ui.radioButtonLogLinearP.clicked.connect(self.selectFixedOrLog) + self.ui.checkBox.clicked.connect(self.selectFixedEnds) - - + + self.ui.spinBoxAsymSubSections.valueChanged.connect(self.asym_sub_val_change) + self.ui.spinBoxWSubSections.valueChanged.connect(self.weight_sub_val_change) + + self.ui.spinBoxWeight = _SciSpin() + self.ui.spinBoxWeight.setMinimum(0) + self.ui.spinBoxWeight.setMaximum(1e10) + self.ui.spinBoxWeight.setValue(1) + self.ui.spinBoxWeight.editingFinished.connect(self.weightspinboxchanged) + self.ui.verticalLayout_7.insertWidget(1, self.ui.spinBoxWeight) + + @property + def x(self): + if self.rng is None: + return self._x + else: + return self._x[self.rng] + + def weight_sub_val_change(self): + """ Weights Subsections spinbox has changed value """ + sbval = self.ui.spinBoxWSubSections.value() + n_rows = self.ui.tableWidgetWeights.rowCount() + n_cols = self.ui.tableWidgetWeights.columnCount() + + max_x = _np.max(self.x) + min_x = _np.min(self.x) + + if sbval > n_rows: + for nr in _np.arange(n_rows, sbval): + self.ui.tableWidgetWeights.setRowCount(sbval) + n_rows = self.ui.tableWidgetWeights.rowCount() + + # Start X + scispin = _SciSpin() + scispin.setMinimum(self._x.min()) + scispin.setMaximum(self._x.max()) + scispin.setValue(min_x) + scispin.editingFinished.connect(self.weightspinboxchanged) + self.ui.tableWidgetWeights.setCellWidget(nr, 0, scispin) + + # Stop X + scispin = _SciSpin() + scispin.setMinimum(self._x.min()) + scispin.setMaximum(self._x.max()) + scispin.setValue(max_x) + scispin.editingFinished.connect(self.weightspinboxchanged) + self.ui.tableWidgetWeights.setCellWidget(nr, 1, scispin) + + # Weight Parameter + # scispin = _SciSpin() + # scispin.setMinimum(0) + # scispin.setMaximum(1e4) + # scispin.setValue(1) + # scispin.editingFinished.connect(self.weightspinboxchanged) + # self.ui.tableWidgetWeights.setCellWidget(nr, 2, scispin) + elif sbval < n_rows: + for nr in _np.arange(sbval, n_rows): + for nc in range(n_cols): + sw = self.ui.tableWidgetWeights.cellWidget(nr, nc) + sw.editingFinished.disconnect() + + self.ui.tableWidgetWeights.setRowCount(sbval) + n_rows = self.ui.tableWidgetWeights.rowCount() + + self.weightspinboxchanged() + + def asym_sub_val_change(self): + """ P Subsections spinbox has changed value """ + sbval = self.ui.spinBoxAsymSubSections.value() + n_rows = self.ui.tableWidgetAsym.rowCount() + n_cols = self.ui.tableWidgetAsym.columnCount() + + max_x = _np.max(self.x) + min_x = _np.min(self.x) + + if sbval > n_rows: + for nr in _np.arange(n_rows, sbval): + self.ui.tableWidgetAsym.setRowCount(sbval) + n_rows = self.ui.tableWidgetAsym.rowCount() + + # Start X + scispin = _SciSpin() + scispin.setMinimum(self._x.min()) + scispin.setMaximum(self._x.max()) + scispin.setValue(min_x) + scispin.editingFinished.connect(self.asymspinboxchanged) + self.ui.tableWidgetAsym.setCellWidget(nr, 0, scispin) + + # Stop X + scispin = _SciSpin() + scispin.setMinimum(self._x.min()) + scispin.setMaximum(self._x.max()) + scispin.setValue(max_x) + scispin.editingFinished.connect(self.asymspinboxchanged) + self.ui.tableWidgetAsym.setCellWidget(nr, 1, scispin) + + # Asym Parameter + scispin = _SciSpin() + scispin.setMinimum(0) + scispin.setMaximum(1e20) + scispin.setValue(self.ui.spinBoxP.value()) + scispin.editingFinished.connect(self.asymspinboxchanged) + self.ui.tableWidgetAsym.setCellWidget(nr, 2, scispin) + elif sbval < n_rows: + for nr in _np.arange(sbval, n_rows): + for nc in range(n_cols): + sw = self.ui.tableWidgetAsym.cellWidget(nr, nc) + sw.editingFinished.disconnect() + + self.ui.tableWidgetAsym.setRowCount(sbval) + n_rows = self.ui.tableWidgetAsym.rowCount() + + self.asymspinboxchanged() + def fcn(self, data_in): """ If return list, [0] goes to original, [1] goes to affected """ - + data_out = _np.zeros(data_in.shape) baseline = _np.zeros(data_in.shape) - - if callable(self.parameters['asym_param']): - self.parameters['asym_param'] = \ - self.parameters['asym_param'](data_in.shape[-1]) - - smoothness_param = self.parameters['smoothness_param'] - asym_param = self.parameters['asym_param'] - redux = self.parameters['redux'] - fep = self.parameters['fix_end_points'] - max_iter = self.parameters['max_iter'] - min_diff = self.parameters['min_diff'] - - _als = _Als(smoothness_param=smoothness_param, - asym_param=asym_param, - redux=redux, fix_end_points=fep, - max_iter=max_iter, - min_diff=min_diff) - + + # if callable(self.parameters['asym_param']): + # self.parameters['asym_param'] = \ + # self.parameters['asym_param'](data_in.shape[-1]) + + # smoothness_param = self.parameters['smoothness_param'] + # asym_param = self.parameters['asym_param'] + # redux = self.parameters['redux'] + # fep = self.parameters['fix_end_points'] + # max_iter = self.parameters['max_iter'] + # min_diff = self.parameters['min_diff'] + # order = self.parameters['order'] + # rng = self.parameters['rng'] + # fix_rng = self.parameters['fix_rng'] + # smoothness_param=1e3, asym_param=1e-4, redux=1, + # order=2, rng=None, fix_end_points=False, fix_rng=None, + # fix_const=1, max_iter=100, min_diff=1e-5, verbose=False + + _als = _Als(**self.parameters) + if data_in.ndim == 1: baseline = _als.calculate(data_in) data_out = data_in - baseline @@ -163,121 +293,134 @@ def fcn(self, data_in): baseline[num,:] = _als.calculate(spectrum) data_out[num,:] = spectrum - baseline[num,:] return [baseline, data_out] - - + + def setup_smoothness(self): - """ + """ Lambda/smoothness parameter rlated """ - + self.ui.label_2.setText('{} (Smoothness)'.format(u'\u03BB')) self.ui.spinBoxLambda = _SciSpin() self.ui.verticalLayout_2.insertWidget(1, self.ui.spinBoxLambda) self.ui.spinBoxLambda.setValue(self.parameters['smoothness_param']) - + def setup_asym(self): """ P/asymmetry parameter related """ - - + self.ui.spinBoxP = _SciSpin() self.ui.verticalLayout.insertWidget(1, self.ui.spinBoxP) self.ui.spinBoxP.setValue(self.parameters['asym_param']) - if self.parameters['fixed_p']: - self.ui.radioButtonFixedP.setChecked(True) - self.ui.radioButtonLogLinearP.setChecked(False) - else: - self.ui.radioButtonFixedP.setChecked(False) - self.ui.radioButtonLogLinearP.setChecked(True) - self.selectFixedOrLog() - - self.ui.spinBoxPStart = _SciSpin() - self.ui.verticalLayout_5.insertWidget(1, self.ui.spinBoxPStart) - self.ui.spinBoxPStart.setValue(self.parameters['asym_param_start']) + + def asymspinboxchanged(self): + """ + Asymetry parameter-related values have changed + """ + n_rows = self.ui.tableWidgetAsym.rowCount() - self.ui.spinBoxPEnd = _SciSpin() - self.ui.verticalLayout_6.insertWidget(1, self.ui.spinBoxPEnd) - self.ui.spinBoxPEnd.setValue(self.parameters['asym_param_end']) + # * Currently, asym_param in ALS is in the full vector space + x = self._x + + self.sub_asym_list = [] + + if n_rows == 0: + self.parameters['asym_param'] = self.ui.spinBoxP.value() + else: + self.parameters['asym_param'] = self.ui.spinBoxP.value() + 0*x + for rc in range(n_rows): + xstart_pix = _find_nearest(x, + self.ui.tableWidgetAsym.cellWidget(rc, 0).value())[1] + xstop_pix = _find_nearest(x, + self.ui.tableWidgetAsym.cellWidget(rc, 1).value())[1] + asym = self.ui.tableWidgetAsym.cellWidget(rc, 2).value() + + self.parameters['asym_param'][xstart_pix:xstop_pix+1] = 1*asym + print('XStart: {}, XStop: {}, ASym: {}'.format(xstart_pix, xstop_pix, asym)) + self.sub_asym_list.append([xstart_pix, xstop_pix, asym]) + + print('---------') + self.changed.emit() + + def weightspinboxchanged(self): + """ + Weight parameter-related values have changed + """ + n_rows = self.ui.tableWidgetWeights.rowCount() + # * Currently, fix_rng (weight parameters) in ALS is in the rng vector space + x = self.x + + self.sub_w_list = [] + + if n_rows == 0: + self.parameters['fix_rng'] = None + else: + self.parameters['fix_rng'] = [] + for rc in range(n_rows): + xstart_pix = _find_nearest(x, + self.ui.tableWidgetWeights.cellWidget(rc, 0).value())[1] + xstop_pix = _find_nearest(x, + self.ui.tableWidgetWeights.cellWidget(rc, 1).value())[1] + weight = self.ui.spinBoxWeight.value() + + # self.parameters['fix_rng'].extend(_np.arange(xstart_pix, xstop_pix+1).tolist()) + self.parameters['fix_rng'].extend(_np.arange(xstart_pix, xstop_pix).tolist()) # No +1 + + # self.parameters['asym_param'][xstart_pix:xstop_pix+1] = 1*asym + # print('XStart: {}, XStop: {}, ASym: {}'.format(xstart_pix, xstop_pix, asym)) + self.sub_w_list.append([xstart_pix, xstop_pix, weight]) + self.parameters['fix_rng'] = _np.array(self.parameters['fix_rng']) + self.parameters['fix_const'] = self.ui.spinBoxWeight.value() + print('---------') + self.changed.emit() + def spinBoxChanged(self): """ Controller for all spinBoxes """ - sdr = self.sender() - - if sdr == self.ui.spinBoxPStart: - self.parameters['asym_param_start'] = self.ui.spinBoxPStart.value() - self.selectFixedOrLog() - - elif sdr == self.ui.spinBoxPEnd: - self.parameters['asym_param_end'] = self.ui.spinBoxPEnd.value() - self.selectFixedOrLog() - - elif sdr == self.ui.spinBoxLambda: + + if sdr == self.ui.spinBoxLambda: self.parameters['smoothness_param'] = self.ui.spinBoxLambda.value() - + elif sdr == self.ui.spinBoxP: - self.parameters['asym_param'] = self.ui.spinBoxP.value() - + self.asymspinboxchanged() + elif sdr == self.ui.spinBoxRedux: self.parameters['redux'] = self.ui.spinBoxRedux.value() - + elif sdr == self.ui.spinBoxMaxIter: self.parameters['max_iter'] = self.ui.spinBoxMaxIter.value() - + elif sdr == self.ui.spinBoxMinDiff: self.parameters['min_diff'] = self.ui.spinBoxMinDiff.value() - + self.changed.emit() - + def selectFixedEnds(self): """ Check selection of fixed end-points """ - + self.parameters['fix_end_points'] =self.ui.checkBox.isChecked() self.changed.emit() - - def selectFixedOrLog(self): - """ - Check fixed or log-linear asymmetry parameter - """ - - self.parameters['fixed_p'] = self.ui.radioButtonFixedP.isChecked() - if self.parameters['fixed_p']: - self.ui.radioButtonFixedP.setChecked(True) - self.ui.radioButtonLogLinearP.setChecked(False) - self.ui.frame_2.setEnabled(False) - self.ui.frame.setEnabled(True) -# self.p = lambda x: self.ui.spinBoxP.value() - self.parameters['asym_param'] = self.ui.spinBoxP.value() - - else: - self.ui.radioButtonFixedP.setChecked(False) - self.ui.radioButtonLogLinearP.setChecked(True) - self.ui.frame_2.setEnabled(True) - self.ui.frame.setEnabled(False) - self.parameters['asym_param'] = \ - lambda x: _np.logspace(_np.log10(self.parameters['asym_param_start']), - _np.log10(self.parameters['asym_param_end']),x) - self.changed.emit() - - + if __name__ == '__main__': import sys as _sys from PyQt5.QtWidgets import (QApplication as _QApplication) - - + + app = _QApplication(_sys.argv) app.setStyle('Cleanlooks') - winALS = widgetALS() - + x = _np.linspace(500, 4000, 1001) + winALS = widgetALS(x=x) + winALS.show() - + app.exec_() print(winALS.parameters) _sys.exit() \ No newline at end of file diff --git a/crikit/ui/widget_Jupyter.py b/crikit/ui/widget_Jupyter.py index 91eca55..cbdc455 100644 --- a/crikit/ui/widget_Jupyter.py +++ b/crikit/ui/widget_Jupyter.py @@ -23,9 +23,14 @@ class QJupyterWidget(RichJupyterWidget): """ Convenience class for a live IPython console widget. We can replace the standard banner using the customBanner argument""" def __init__(self,customBanner=None,*args,**kwargs): super(QJupyterWidget, self).__init__(*args,**kwargs) - if customBanner!=None: self.banner=customBanner + if customBanner!=None: + self.banner=customBanner self.kernel_manager = kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() + def _abort_queues(kernel): + # ! See IPython Issue: https://github.com/ipython/ipykernel/issues/370 + pass + kernel_manager.kernel._abort_queues = _abort_queues kernel_manager.kernel.gui = 'qt' self.kernel_client = kernel_client = self._kernel_manager.client() diff --git a/crikit/ui/widget_images.py b/crikit/ui/widget_images.py index b70cd1d..f4a3a41 100644 --- a/crikit/ui/widget_images.py +++ b/crikit/ui/widget_images.py @@ -39,7 +39,9 @@ # Generic imports for MPL-incorporation import matplotlib as _mpl from matplotlib.pyplot import colormaps as _plt_colormaps -import sciplot as _sciplot + +from sciplot.sciplotUI import SciPlotUI as _SciPlotUI + #import matplotlib.pyplot as _plt _mpl.use('Qt5Agg') @@ -81,7 +83,7 @@ def clear(self): Resets the ui to it's initial state """ self.ui.checkBoxDisable.setChecked(False) - + self.ui.spinBoxGain.setValue(1.0) self.ui.tabWidgetMath.setCurrentIndex(0) @@ -96,7 +98,7 @@ def clear(self): self.ui.comboBoxCondOps.setCurrentIndex(0) self.ui.comboBoxCondInEquality.setCurrentIndex(0) self.ui.spinBoxInEquality.setValue(0.0) - + def condOpsChange(self): index = self.ui.comboBoxCondOps.currentIndex() @@ -137,7 +139,7 @@ def operationchange(self): self.ui.pushButtonOpFreq3.setEnabled(True) class widgetPopSpectrumGS(_QWidget): - """ + """ Panel that let's user pop the current image, an average spectrum, or a grayscale image to SciPlot """ @@ -165,7 +167,7 @@ def __init__(self, parent=None, **kwargs): self.ui.setupUi(self) # Get all MPL named colors - color_list = ['red', 'green', 'blue', 'magenta', 'cyan', 'yellow', + color_list = ['red', 'green', 'blue', 'magenta', 'cyan', 'yellow', 'black', 'white', 'CUSTOM'] color_list.extend(sorted(set(_mpl.colors.cnames.keys()) - set(color_list))) self.ui.comboBoxBGColor.addItems(color_list) @@ -188,11 +190,11 @@ def __init__(self, parent = None, **kwargs): self.win = Ui_Blank() self.win.setupUi(self) self.win.gridLayout.setEnabled(False) - + self._img_defaults = {'showcbar': True, 'axison': True} self.gsinfo = widgetGrayScaleInfoBar(parent=self) - + self.colormode = widgetColorMode(parent=self) self.colormode.ui.comboBoxColorMode.setCurrentIndex(1) self.colormode.ui.comboBoxColormap.setVisible(True) @@ -213,9 +215,9 @@ def __init__(self, parent = None, **kwargs): self.win.horizLayout.setContentsMargins(2,2,2,2) self.win.verticalLayout.insertLayout(0, self.win.horizLayout) - - self.win.horizLayout.insertWidget(0, self.gsinfo, _QtCore.Qt.AlignHCenter) - self.win.horizLayout.insertWidget(0, self.colormode, _QtCore.Qt.AlignBottom) + + self.win.horizLayout.insertWidget(0, self.gsinfo, alignment=_QtCore.Qt.AlignHCenter) + self.win.horizLayout.insertWidget(0, self.colormode, alignment=_QtCore.Qt.AlignBottom) # Initialize underlying data self.initData() @@ -225,31 +227,34 @@ def __init__(self, parent = None, **kwargs): self.data.grayscaleimage = _np.dot(_np.ones([100,1]),_np.linspace(1,100,100)[None,:]) self.data.set_x(_np.linspace(1,400,self.data.xlen)) self.data.set_y(_np.linspace(1,400,self.data.ylen)) - + # Calculate extent of image winextent = (self.data.x.min(), self.data.x.max(), self.data.y.min(), self.data.y.max()) # MPL canvas self.mpl = _MplCanvas(**kwargs) self.mpl.cbar = None # Monkey patch on a cbar object - + # Create stand-image plot self.createImg(img=self.data.image, xunits=self.data.xunits, yunits=self.data.yunits, extent=winextent, cmap=self.colormode.ui.comboBoxColormap.currentText()) - self.mpl.fig.tight_layout() - + try: + self.mpl.fig.tight_layout() + except: + print('tight_layout failed (widget_images 1') + # Insert canvas widget into this widget - self.win.verticalLayout.insertWidget(0,self.mpl,_QtCore.Qt.AlignCenter) - self.win.verticalLayout.insertWidget(0,self.popimage,_QtCore.Qt.AlignCenter) - self.win.verticalLayout.insertWidget(0,self.mpl.toolbar, _QtCore.Qt.AlignHCenter) + self.win.verticalLayout.insertWidget(0,self.mpl, alignment=_QtCore.Qt.AlignCenter) + self.win.verticalLayout.insertWidget(0,self.popimage, alignment=_QtCore.Qt.AlignCenter) + self.win.verticalLayout.insertWidget(0,self.mpl.toolbar, alignment=_QtCore.Qt.AlignHCenter) # # SIGNAL & SLOTS self.ui.checkBoxFixed.stateChanged.connect(self.checkBoxFixed) self.ui.checkBoxRemOutliers.stateChanged.connect(self.checkBoxRemOutliers) self.ui.spinBoxStdDevs.editingFinished.connect(self.checkBoxRemOutliers) - + # New self.ui.comboBoxAboveMax.currentIndexChanged.connect(self.comboBoxCompress) self.ui.comboBoxBelowMin.currentIndexChanged.connect(self.comboBoxCompress) @@ -276,15 +281,15 @@ def createImg_Ext(self, img, xunits = None, yunits = None, Create new figure window and show image of img """ - self.external_plots.append(_sciplot.main(parent=parent)) - self.external_plots[-1].imshow(img, x_label=xunits, y_label=yunits, + self.external_plots.append(_SciPlotUI(parent=parent)) + self.external_plots[-1].imshow(img, x_label=xunits, y_label=yunits, cmap=cmap, cbar=showcbar, extent=extent) def createImg(self, img, xunits = None, yunits = None, extent = None, cmap = _mpl.cm.gray): self.mpl.ax.clear() self.mpl.img = self.mpl.ax.imshow(img, interpolation = 'none', - extent = extent, cmap = cmap, + extent = extent, cmap = cmap, origin='lower') if xunits is not None: self.mpl.ax.xaxis.set_label_text(xunits) @@ -304,13 +309,13 @@ def createImg(self, img, xunits = None, yunits = None, if self.ui.checkBoxFixed.isChecked() == False: self.ui.spinBoxMax.setValue(self.data.maxer) self.ui.spinBoxMin.setValue(self.data.minner) - + def spinBoxMinMaxSet(self): try: self.data.setmin = self.ui.spinBoxMin.value() self.data.setmax = self.ui.spinBoxMax.value() self.ui.checkBoxFixed.setChecked(True) - + # Spin-Box call from Outlier-related widgets? sent_by = self.sender() if ((sent_by == self.ui.checkBoxRemOutliers) | @@ -344,10 +349,10 @@ def checkBoxRemOutliers(self): self.ui.spinBoxMax.setValue(new_max) self.ui.spinBoxMin.setValue(new_min) self.spinBoxMinMaxSet() - + self.createImg(img=self.data.image, xunits=self.data.xunits, yunits=self.data.yunits, - extent=self.data.winextent, + extent=self.data.winextent, cmap=self.colormode.ui.comboBoxColormap.currentText()) self.mpl.draw() @@ -382,7 +387,7 @@ def checkBoxFixed(self): self.createImg(img=self.data.image, xunits=self.data.xunits, yunits=self.data.yunits, - extent=self.data.winextent, + extent=self.data.winextent, cmap=self.colormode.ui.comboBoxColormap.currentText()) self.mpl.draw() @@ -412,6 +417,8 @@ class widgetSglColor(widgetBWImg): """ def __init__(self, parent=None, **kwargs): super().__init__(parent) + self.win.gridLayout.setEnabled(False) + self._img_defaults = {'showcbar': False, 'axison': True} self.initData() self.data.grayscaleimage = _np.dot(_np.ones([100,1]),_np.linspace(1,100,100)[None,:]) @@ -419,13 +426,13 @@ def __init__(self, parent=None, **kwargs): self.data.set_y(_np.linspace(1,400,self.data.ylen)) self.changeColor() self.colormode.setMaximumHeight(130) - + self.math = widgetImageGainMath(parent=self) self.win.verticalLayout.insertWidget(3, self.math) # Disconnect colormap-related (from BW parent) self.colormode.ui.comboBoxColormap.currentIndexChanged.disconnect() - + self.colormode.ui.comboBoxColorMode.setCurrentIndex(0) self.colormode.ui.comboBoxColormap.setVisible(False) self.colormode.ui.labelColormap.setVisible(False) @@ -438,7 +445,7 @@ def __init__(self, parent=None, **kwargs): self.colormode.ui.comboBoxFGColor.currentIndexChanged.connect(self.changeColor) self.colormode.ui.comboBoxBGColor.currentIndexChanged.connect(self.changeColor) - self.math.ui.spinBoxGain.valueChanged.connect(self.applyGain) + self.math.ui.spinBoxGain.editingFinished.connect(self.applyGain) self.math.ui.pushButtonGain1.pressed.connect(self.gain1) self.math.ui.checkBoxDisable.stateChanged.connect(self.disabled) @@ -449,11 +456,11 @@ def __init__(self, parent=None, **kwargs): pass self.popimage.ui.pushButtonPop.pressed.connect(lambda: self.createImg_Ext(img = self.data.image, showcbar=False, - extent=self.data.winextent, + extent=self.data.winextent, xunits=self.data.xunits, yunits=self.data.yunits, parent=parent)) - + try: self.popimage.ui.pushButtonGSPop.pressed.disconnect() except TypeError: @@ -470,11 +477,11 @@ def initData(self): (Re)-initialize self.data """ self.data = SingleColor() - - + + def changeColor(self): # try: - + if self.sender() == self.colormode.ui.comboBoxFGColor: color_str = self.colormode.ui.comboBoxFGColor.currentText() if color_str == 'CUSTOM': @@ -496,12 +503,12 @@ def changeColor(self): else: self.data.bgcolor = _mpl.colors.colorConverter.to_rgb(_mpl.colors.cnames[bgcolor_str]) - + self.createImg(img = self.data.image, xunits = self.data.xunits, yunits = self.data.yunits, extent = self.data.winextent) self.mpl.draw() - + def applyGain(self): self.data.setgain = self.math.ui.spinBoxGain.value() self.changeColor() @@ -535,7 +542,7 @@ def __init__(self, sgl_color_widget_list = None, parent = None, **kwargs): self.data.grayscaleimage = _np.dot(_np.ones([100,1]),_np.linspace(1,100,100)[None,:]) self.data.set_x(_np.linspace(1,400,self.data.xlen)) self.data.set_y(_np.linspace(1,400,self.data.ylen)) - + winextent = (self.data.x.min(), self.data.x.max(), self.data.y.min(), self.data.y.max()) # Instantiate mpl widget @@ -549,7 +556,7 @@ def __init__(self, sgl_color_widget_list = None, parent = None, **kwargs): color_list.extend(sorted(set(_mpl.colors.cnames.keys()) - set(color_list))) self.ui.comboBoxBGColor.addItems(color_list) self.ui.comboBoxBGColor.setCurrentIndex(color_list.index('black')) - + # Emission/Absorption mode settings self.ui.comboBoxColorMode.setCurrentIndex(0) # Emission mode is default @@ -557,17 +564,20 @@ def __init__(self, sgl_color_widget_list = None, parent = None, **kwargs): self.createImg(img = self.data.image, xunits = self.data.xunits, yunits = self.data.yunits, extent = winextent) - self.mpl.fig.tight_layout() + try: + self.mpl.fig.tight_layout() + except: + print('tight_layout failed (widget_image: 3') # Insert mpl widget into this widget - self.ui.verticalLayout.insertWidget(0,self.mpl,_QtCore.Qt.AlignHCenter) - self.ui.verticalLayout.insertWidget(0,self.mpl.toolbar, _QtCore.Qt.AlignHCenter) + self.ui.verticalLayout.insertWidget(0,self.mpl, alignment=_QtCore.Qt.AlignHCenter) + self.ui.verticalLayout.insertWidget(0,self.mpl.toolbar, alignment=_QtCore.Qt.AlignHCenter) self.popimage = widgetPopSpectrumGS(self) - self.ui.verticalLayout.insertWidget(1, self.popimage, _QtCore.Qt.AlignLeft) + self.ui.verticalLayout.insertWidget(1, self.popimage, alignment=_QtCore.Qt.AlignHCenter) self.popimage.ui.pushButtonPop.pressed.connect(lambda: self.createImg_Ext(img = self.data.image, showcbar=False, - extent=self.data.winextent, + extent=self.data.winextent, xunits=self.data.xunits, yunits=self.data.yunits, parent=parent)) @@ -582,7 +592,7 @@ def initData(self, sgl_color_widget_list): """ (Re)-initialize self.data """ - + if sgl_color_widget_list is None: self.data = CompositeColor() else: @@ -618,8 +628,8 @@ def createImg_Ext(self, img, xunits = None, yunits = None, Create new figure window and show image of img """ - self.external_plots.append(_sciplot.main(parent=parent)) - self.external_plots[-1].imshow(img, x_label=xunits, y_label=yunits, + self.external_plots.append(_SciPlotUI(parent=parent)) + self.external_plots[-1].imshow(img, x_label=xunits, y_label=yunits, cmap=cmap, cbar=showcbar, extent=extent) # BROKEN -- May never work @@ -635,7 +645,7 @@ def createImg_Ext(self, img, xunits = None, yunits = None, # extent = self.data.winextent) # self.mpl.fig.tight_layout() # self.mpl.draw() - + def changeMode(self): self.data.mode = self.ui.comboBoxColorMode.currentIndex() # self.data.mode = _np.abs(self.data.mode - 1).astype(int) @@ -643,7 +653,10 @@ def changeMode(self): self.createImg(img = self.data.image, xunits = self.data.xunits, yunits = self.data.yunits, extent = self.data.winextent) - self.mpl.fig.tight_layout() + try: + self.mpl.fig.tight_layout() + except: + print('tight_layout failed (widget_image: 3') self.mpl.draw() @@ -655,7 +668,7 @@ def changeMode(self): winBWImg = widgetBWImg() winBWImg.setWindowTitle('BW Image') winBWImg.show() - + winSglColor = widgetSglColor() winSglColor.setWindowTitle('Single Color') winSglColor.colormode.ui.comboBoxBGColor.setCurrentIndex(7) @@ -666,8 +679,8 @@ def changeMode(self): winSglColor2.colormode.ui.comboBoxBGColor.setCurrentIndex(7) winSglColor2.setWindowTitle('Single Color') winSglColor2.show() - - + + winColorMath = widgetImageGainMath() winColorMath.setWindowTitle('Color Math') winColorMath.show() diff --git a/crikit/utils/breadcrumb.py b/crikit/utils/breadcrumb.py index 331b012..d88af19 100644 --- a/crikit/utils/breadcrumb.py +++ b/crikit/utils/breadcrumb.py @@ -14,11 +14,12 @@ import time as _time import copy as _copy import pickle as _pickle +from collections import OrderedDict as _OrderedDict class BCPre: """ Container that describes processing steps (ie it contains "breadcrumbs") - + Attributes ---------- process_list : list @@ -26,68 +27,70 @@ class BCPre: ['Process Name', 'Var1 Name', Val1, 'Var2 Name', Val2, ...]. The \ variable names and values may be input values to the pre-processing \ step. Only the Process Name is mnadatory: the rest are optional. - + backed_flag : list Flag identifying which steps were backed-up to disk (e.g., for undo) - + id_list : list (read-only) Unique identifier for each step. Can be used to name back-up/undo files cut_list : list (read-only) Identifier of id's cut with pop_to_last method - + num_steps : int Number of processing steps - + attr_dict : dict Dictionary-version of process_list that can be written to HDF5 dataset metadata (properties) - + Methods ------- add_step : Add a new processing step - + backed_up : Mark most recent process step as backed up in backed_flag list - + pop_to_last : Remove entries until nearest backup point (excluding current \ step). - + """ - - HDF_PREFIX = 'Processing.Steps' - + + PREFIX = 'Processing.Steps' + def __init__(self): self.process_list = [] self._id_list = [] self.backed_flag = [] self._cut_list = [] - + # PROPERTIES @property def id_list(self): - # Use shallow-copy to prevent ability to append + # Use shallow-copy to prevent ability to append # to _id_list via id_list return self._id_list.copy() - + @property def cut_list(self): - # Use shallow-copy to prevent ability to append + # Use shallow-copy to prevent ability to append # to _cut_list via cut_list return self._cut_list.copy() - + @cut_list.deleter def cut_list(self): self._cut_list = [] - + @property def num_steps(self): return len(self.process_list) - + @property def attr_dict(self): - temp = {} + temp = _OrderedDict() + temp[self.PREFIX] = self.num_steps + for num, item in enumerate(self.process_list): - temp_key_process_prefix = self.HDF_PREFIX + '.' + str(num+1) + '.' + str(item[0]) + temp_key_process_prefix = self.PREFIX + '.' + str(num+1) + '.' + str(item[0]) temp_val = 'NA' temp[temp_key_process_prefix] = temp_val if len(item) > 1: @@ -97,9 +100,9 @@ def attr_dict(self): temp_key = temp_key_process_prefix + '.' + str(var) temp_val = item[2*num_var+2] temp[temp_key] = temp_val - temp[self.HDF_PREFIX] = self.num_steps + return temp - + @property def dset_name_suffix(self): temp = '' @@ -116,14 +119,14 @@ def dset_name_suffix(self): return temp except: return None - + # METHODS @staticmethod def backup_pickle(data, fname, addl_attr = None): """ - Dump current state of data (class of type crikit.data.spectrum or - subclass)to pickle file (filename= fname). - + Dump current state of data (class of type crikit.data.spectrum or + subclass)to pickle file (filename= fname). + Can append additional attributes (addl_attr) to \ attribute dictionary (self.attr) """ @@ -137,7 +140,7 @@ def backup_pickle(data, fname, addl_attr = None): # Pickle with highest protocol # Surpasses the default protocol 3 4Gb limit _pickle.dump(data, f, protocol=-1) - + @staticmethod def load_pickle(fname): """ @@ -151,11 +154,11 @@ def load_pickle(fname): with open(fname, 'rb') as f: return _pickle.load(f) - + def add_step(self, process_desc): """ Adds a steps to the list - + Parameters ------ process_desc : list @@ -164,54 +167,59 @@ def add_step(self, process_desc): variable names and values may be input values to the \ pre-processing step. Only the Process Name is mnadatory: the rest \ are optional. - + Returns ------- None : None - + """ - assert isinstance(process_desc,list), 'The input need be a list' - assert len(process_desc)%2 != 0, 'The input needs to be an odd length (title, var name 1, var value 1, etc)' - - # Ensures unique IDs based on time. Note some systems only report in - # seconds, not sub-seconds + + if not isinstance(process_desc,list): + raise TypeError('Added step need be of type list') + + if len(process_desc)%2 == 0: + err_str = 'The input needs to be an odd length (title, var name 1, var value 1, etc)' + raise ValueError(err_str) + + # Ensures unique IDs based on time. Note some systems only report in + # seconds, not sub-seconds _time.sleep(1) self.process_list.append(process_desc) self._id_list.append(str(_time.time())) self.backed_flag.append(False) - + def backed_up(self): """ Marks most recent process step as backed up in backed_flag list - + Parameters ------ None : None - + Returns ------- None : None - + """ self.backed_flag[-1] = True - + def pop_to_last(self, all=False): """ - Remove entries until nearest backup point (excluding current step). + Remove entries until nearest backup point (excluding current step). That is, if current step IS a backup point, moves to previous one. If \ current step is NOT a backup point, moves to nearest point. - + If all = True, will cut everything """ temp = _copy.deepcopy(self.backed_flag) - backup_locs = [] + backup_locs = [] for num, val in enumerate(temp): if val is True: backup_locs.append(num) - + current_loc = len(temp) - 1 - + if all is False: if temp[-1] == True: # Current is backed-up, go to previous num_to_pop = backup_locs[-1] - backup_locs[-2] @@ -219,7 +227,7 @@ def pop_to_last(self, all=False): num_to_pop = current_loc - backup_locs[-1] else: num_to_pop = len(temp) - + for count in range(num_to_pop): self.process_list.pop() is_backed_up = self.backed_flag.pop() @@ -227,8 +235,8 @@ def pop_to_last(self, all=False): self._cut_list.append(self._id_list.pop()) else: self._id_list.pop() - - + + if __name__ == '__main__': import sys as _sys test = BCPre() @@ -240,41 +248,41 @@ def pop_to_last(self, all=False): test.add_step(['Test',1]) except: print('Expected Error\n') - + test.add_step(['Raw']) test.add_step(['SubDark','RangeStart',-1500,'RangeEnd',-400]) test.add_step(['NormKK','Amp',100.0,'Phase',10.0]) #test.add_step(['DeTrend','Lambda',1000.0,'p',0.001,'Method','ALS','Type','Phase']) #test.add_step(['DeTrend','Order',2,'win',601,'Method','sg','Type','Scale']) - + #print('Attempting to append \'1\' to the end of id_list (it should not work)') #test.id_list.append(1) #print(test.id_list) - + print('\nProcess list: {}'.format(test.process_list)) print('\nID list: {}'.format(test.id_list)) print('\nNumber of process steps: {}'.format(test.num_steps)) print('\n\nReturned attribute dict: {}'.format(test.attr_dict)) print('\n\nGenerated dataset name: {}'.format(test.dset_name_suffix)) _sys.exit() - + #[['Raw'], ['SubDark'], ['SubResidual', 'RangeStart', -1500, 'RangeEnd', -400]] - - + + # print('\n\n\nWritten to backup file: {}'.format(test.backed_flag)) # print('\n...Apply backed_up...') # test.backed_up() # print('\nWritten to backup file: {}'.format(test.backed_flag)) -# +# # print('\nAdjust backup') # test.backed_flag[0] = True # print('Written to backup file: {}'.format(test.backed_flag)) -# +# # print('\n Test Pop-to-last') # print('Process List: {}'.format(test.process_list)) # print('ID List: {}'.format(test.id_list)) # print('Written to backup file: {}\n'.format(test.backed_flag)) -# +# # test.pop_to_last() # print('Process List: {}'.format(test.process_list)) # print('ID List: {}'.format(test.id_list)) @@ -282,7 +290,7 @@ def pop_to_last(self, all=False): # print('Cut List:{}'.format(test.cut_list)) # del test.cut_list # print('Cut List:{}'.format(test.cut_list)) -# +# # print('\nCut all') # test.pop_to_last(all=True) # print('Process List: {}'.format(test.process_list)) @@ -291,4 +299,4 @@ def pop_to_last(self, all=False): # print('Cut List:{}'.format(test.cut_list)) # del test.cut_list # print('Cut List:{}'.format(test.cut_list)) -# \ No newline at end of file +# \ No newline at end of file diff --git a/crikit/utils/general.py b/crikit/utils/general.py index 0670914..6016323 100644 --- a/crikit/utils/general.py +++ b/crikit/utils/general.py @@ -9,11 +9,86 @@ find_nearest : Given a vector and a value, find the index and value of the closest match + pad : Wrapper around numpy.pad that also returns a window defining the + original signal + Notes ----- """ import numpy as _np +def pad(y, pad_width, mode): + """ + Pad array with either constants or edge values. + + Note: For N-D arrays, pads the -1 axis + + Parameters + ---------- + y : ndarray + Input array + + pad_width : int + Size of padding on each side of y + + mode : str + 'constant' (0), 'edge' currently accepted + + Returns + ------- + y_pad, window + Padded array and window. Window defines the region of the original signal + """ + if pad_width <= 0: + return y, _np.ones(y.shape[-1]) + else: + shaper = list(y.shape) + shaper_out = list(y.shape) + shaper_out[-1] += 2*pad_width + y_pad = _np.zeros(shaper_out, dtype=y.dtype) + window = _np.zeros(shaper_out[-1], dtype=_np.integer) + + y_pad[...,pad_width:shaper[-1]+pad_width] = 1*y + window[pad_width:shaper[-1]+pad_width] = 1 + + if (mode == 'zeros') | (mode == 'constant') | (mode == 'zero'): + pass + elif mode == 'edge': + y_pad[...,:pad_width] = _np.dot(y[...,0:1], _np.ones((1, pad_width))) + y_pad[..., -pad_width:] = _np.dot(y[...,-1:-2:-1], _np.ones((1, pad_width))) + + return y_pad, window + +def pad_dual(y, edge_pad_width, constant_pad_width): + """ + Pad array with edge values followed by constant 0's. + + Note: For N-D arrays, pads the -1 axis + + Parameters + ---------- + y : ndarray + Input array + + edge_pad_width : int + Size of edge-value padding on each side of y + + constant_pad_width : int + Size of 0-padding on each side of y after edge-value padding + + Returns + ------- + y_pad, window + Padded array and window. Window defines the region of the original signal + """ + y_pad_edge, win_edge = pad(y, edge_pad_width, 'edge') + y_pad, win_constant = pad(y_pad_edge, constant_pad_width, 'constant') + + window = 0*win_constant + window[_np.where(win_constant == 1)[0][win_edge == 1]] = 1 + + return y_pad, window + def np_fcn_nd_to_1d(fcn, data, axis=-1): """ Take in an n-dimensional array and return a 1D version operated on by fcn.\ @@ -172,7 +247,7 @@ def lin_from_row_col(row, col, sh): x = _np.random.rand(10,11) for ct in range(x.size): - row, col = lin_count_row_col(ct, x.shape) + row, col = row_col_from_lin(ct, x.shape) print('R: {} C: {}'.format(row,col)) print('Total number iterated through: {}'.format(ct+1)) @@ -202,7 +277,7 @@ def lin_from_row_col(row, col, sh): space_shp = _np.array(x.shape)[0:-1] num_sp = space_shp.prod() for num in range(num_sp): - rc, cc = lin_count_row_col(num, space_shp) + rc, cc = row_col_from_lin(num, space_shp) y[rc, cc, :] = _np.fft.fft(x[rc, cc, :]) tmr -= _timeit.default_timer() print('Time with 1 for-loops: {:.3g} sec'.format(-tmr)) diff --git a/crikit/utils/h5.py b/crikit/utils/h5.py deleted file mode 100644 index 3ba637a..0000000 --- a/crikit/utils/h5.py +++ /dev/null @@ -1,436 +0,0 @@ -""" -hdf5 utilities (crikit.utils.h5) -======================================================= - - Utilities for for reading and writing data to HDF5 files - -Methods --------- - convert_to_np_dtype : convert from HDF5 dataset to numpy ndarray with \ - numpy-builtin and native datatype - - retrieve_group_dataset_dict : Retrieve dictionary describing groups that \ - contain data [key] and the datasets [value]. {group : [dataset(s)]} - - retrieve_dataset_attribute_dict : Retrieve dictionary describing \ - attributes that contain data [key] and the datasets [value]. \ - {group : [dataset(s)]} - -""" - -import h5py as _h5py -_h5py.get_config().complex_names = ('Re','Im') - -import numpy as _np - -def convert_to_np_dtype(dset): - """ - Given an HDF5 dataset, return the values in a numpy-builtin datatype - - Parameters - ---------- - dset : h5py.Dataset - HDF5 (h5py) dataset - - Returns - ------- - out : numpy.ndarray (dtype = numpy built-in) - - Notes - ----- - The software accounts for big-/little-endianness, and the inability of \ - hdf5 to natively store complex numbers. - - """ - assert isinstance(dset, _h5py.Dataset), 'Input is not of type h5py.Dataset' - # Single datatype - if len(dset.dtype) == 0: - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - if issubclass(converted.dtype.type, _np.integer): # Integer to float - converted = converted.astype(_np.float) - return converted - #Compound datatype of length 2-- assumed ('Re','Im') - elif len(dset.dtype) == 2: - print('Warning: h5py.complex_names set incorrectly using \'{}\' and \'{}\' \ -for Re and Im, respectively'.format(dset.dtype.names[0], dset.dtype.names[1])) - _h5py.get_config().complex_names = (dset.dtype.names[0],dset.dtype.names[1]) - dset = dset.file[dset.name] - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - # Unknown datatype - else: - print('Warning: Unknown datatype. Returning dataset values as is.') - return dset.value - return converted - - -def retrieve_group_dataset_dict(filename): - """ - Given an HDF5 filename, return a dictionary with keys named with full \ - paths to datasets (values) - - Parameters - ---------- - filename : str - filename of HDF5 file - - Returns - ------- - out : dict - {group path : [dataset list]} - - Notes - ----- - - """ - try: - f = _h5py.File(filename,'r') - except OSError as err: - print(err) - else: - list_of_items = ['/'] - f.visit(list_of_items.append) - - groups_all = [] - datasets_all = [] - - for count in list_of_items: - if isinstance(f[count],_h5py.Group) == True: - groups_all.append(count) - if isinstance(f[count],_h5py.Dataset) == True: - datasets_all.append(count) - - groups_with_datasets = [] - - for group_count in groups_all: - for item_count in f[group_count]: - if isinstance(f[group_count][item_count],_h5py.Dataset): - groups_with_datasets.append(group_count) - break - - # Setup dictionary group_with_dataset : datasetnames - group_dataset_dict = [] - for group_count in groups_with_datasets: - dataset_list = [] - for item_count in f[group_count]: - if isinstance(f[group_count][item_count],_h5py.Dataset): - dataset_list.append(item_count) - group_dataset_dict.append([group_count,dataset_list]) - - group_dataset_dict = dict(group_dataset_dict) - - #print('Returning {0} groups covering {1} datasets'.format\ - # (len(groups_with_datasets), len(datasets_all))) - - - - f.close() - return group_dataset_dict - -def retrieve_dataset_attribute_dict(filename,datasetfullname): - """ - Given an HDF5 filename and dataset, return a dictionary with keys named \ - with parameters and values - - Parameters - ---------- - filename : str - filename of HDF5 file - - datasetfullname : str - full pathname to dataset (e.g., /group/subgroup/dataset) - - Returns - ------- - out : dict - {parameter : value} - - Notes - ----- - - """ - try: - f = _h5py.File(filename,'r') - except OSError as err: - print(err) - else: - try: - attrs = f[datasetfullname].attrs - temp = dict(attrs) - except: - print('Error in attributes... Usually an empty one') - temp = {} - for count in attrs: - try: - temp[count] = attrs[count] - except: - pass - return temp - f.close() - return None - -def special_exclude_datasets(filename, str_excl = '_background', new_filename = None): - """ - Removes any datasets with '_background' in the name. Creates a new - h5 file with '_excl*_.h5' appended (unless specified) - - Parameters - ---------- - filename (str) : name of file to analyze/repack/copy - - str_excl (str) : (default: '_background') exclude datasets with this string in the name - - new_filename (str) : (Optional) Output filename - - Returns - ------- - str : filename of new HDF5 file - - Writes a new file filename(-.h5) + '_excl_' + str_exclude + '.h5' - - Notes - ----- - SPECIAL : Only likely useful for the NIST developers - - """ - - if new_filename == None: - new_filename = str.strip(filename,'.h5') + '_excl_' + str_excl.strip('_') + '.h5' - else: - pass - - dataset_dict = retrieve_group_dataset_dict(filename) - - f_input = _h5py.File(filename, 'r') - f_output = _h5py.File(new_filename, 'w-') - - try: - # Interate trhough groups/subgroups - for groups in dataset_dict: - dsets_in_group = dataset_dict[groups] - - # Iterate through each filename in this group - for dset_name in dsets_in_group: - if str.find(dset_name,str_excl) == -1: - temp_name = groups + '/' + dset_name - loc = f_output.require_group(f_input[temp_name].parent.name) - print('Copying: {}'.format(temp_name)) - f_input.copy(temp_name,loc) - del temp_name - except: - print('There was an error') - return None - f_input.close() - f_output.close() - return new_filename - -def special_repack(filename, repack_str = '_Movie_', new_filename = None): - """ - Find datasets (1D) with a given repack_str and concatenates them into - a larger array. Other datasets are copied as is. - - Creates a new h5 file with '_repack_' + repack_str(-'_') + .h5' appended - - Parameters - ---------- - filename (str) : name of file to analyze/repack/copy - - repack_str (str) : string to find in datasets to concatenate - - new_filename (str) : (Optional) Output filename - - Returns - ------- - str : filename of new HDF5 file - - Writes a new file filename + '_repack_' + repack_str(-'_') + .h5' - - Notes - ----- - The output file cannot already exist - - SPECIAL : Only likely useful for the NIST developers - - """ - - if new_filename == None: - new_filename = str.strip(filename,'.h5') + '_repack_' + \ - repack_str.strip('_') + '.h5' - else: - pass - - dataset_dict = retrieve_group_dataset_dict(filename) - - f_input = _h5py.File(filename, 'r') - f_output = _h5py.File(new_filename, 'w-') - - try: - # Iterate through each data-containing group - for groups in dataset_dict: - dsets_in_group = dataset_dict[groups] - # Turn dataset list into one long string and look for - # repack_str if there are none, copy the whole group - if str(dsets_in_group).find(repack_str) == -1: - loc = f_output.require_group(groups) - for dset in dsets_in_group: - name = groups + '/' + dset - f_input.copy(name,loc) - else: - # Create a set from the list to remove identical entries - unique_dset_prefix_list = \ - list(set([str.split(dset_names,repack_str)[0] \ - for dset_names in dsets_in_group])) - - for unique_dset_prefix in unique_dset_prefix_list: - dset_w_prefix = [dset_names for dset_names in \ - dsets_in_group \ - if dset_names.find(unique_dset_prefix) != -1] - - name = groups + '/' + dset_w_prefix[0] - - # Init larger array with expanded size, same dtype - repack_array = _np.ndarray([len(dset_w_prefix), \ - f_input[name].value.shape[0]], dtype = \ - f_input[name].dtype) - - # Fill in columns - for count in enumerate(dset_w_prefix): - name = groups + '/' + count[1] - repack_array[count[0],:] = f_input[name].value - - loc = f_output.require_group(groups) - f_output[str(groups + '/' + unique_dset_prefix)] = repack_array - name = groups + '/' + dset_w_prefix[0] - input_attrs = f_input[str(groups + '/' + \ - dset_w_prefix[0])].attrs - - # Copy attribute from first dataset to the repack_array - for attr in input_attrs: - try: - f_output[str(groups + '/' + \ - unique_dset_prefix)].attrs.create(attr, \ - input_attrs[attr]) - except: - pass - except: - print('There was an error') - - f_input.close() - f_output.close() - - return new_filename - -def special_shrink_datasets(filename, dset_path, dset_name, stepsize, - xstep_attr='RasterScanParams.FastAxisSteps', - xstep_size_attr='RasterScanParams.FastAxisStepSize', - ystep_attr='RasterScanParams.SlowAxisSteps', - ystep_size_attr='RasterScanParams.SlowAxisStepSize'): - """ - Find a particular dataset and shrink it by stepping over pixels - - Parameters - ---------- - filename : str - Name of file to analyze/repack/copy - - dset_path : str - Path to dataset - - dset_attr : str - Dataset name - - stepsize : int - Step size to take (1::stepsize) - - xstep_attr : str - Name of HDF attribute that describes number of steps in the \ - X-direction - - xstep_size_attr : str - Name of HDF attribute that describes step size in the \ - X-direction - - ystep_attr : str - Name of HDF attribute that describes number of steps in the \ - Y-direction - - ystep_size_attr : str - Name of HDF attribute that describes step size in the \ - Y-direction - - Returns - ------- - str : filename of new HDF5 file - - Writes a new file filename + '_repack_' + repack_str(-'_') + .h5' - - Notes - ----- - The output file cannot already exist - - SPECIAL : Only likely useful for the NIST developers - - Example - ------- - _shrink('../mP2_w_small.h5','/BCARSImage/mP2_3_5ms_Pos_2_0/','mP2_3_5ms_Pos_2_0',10) - - """ - - f = _h5py.File(filename,'r') - - try: - dset_fullname = dset_path + dset_name - - dset_name_small = dset_name + '_small' - dset_fullname_small = dset_path + dset_name_small - - temp = _np.zeros(f[dset_fullname].shape, dtype=f[dset_fullname].dtype) - - - f[dset_fullname].read_direct(temp) - f.close() - - f = _h5py.File(filename,'r+') - temp2 = temp[0::stepsize,0::stepsize,:] - - lg_xsteps = temp.shape[1] - lg_ysteps = temp.shape[0] - sm_xsteps = temp2.shape[1] - sm_ysteps = temp2.shape[0] - - - ds = f[dset_path] - ds.create_dataset(dset_name_small, data = temp2) - except: - print('Failed') - else: - input_attrs = f[dset_fullname].attrs - - # Copy attribute from first dataset to the repack_array - for attr in input_attrs: - try: - if attr == xstep_attr: - f[dset_fullname_small].attrs.create(attr, \ - sm_xsteps) - elif attr == xstep_size_attr: - temp = input_attrs[attr] - - f[dset_fullname_small].attrs.create(attr, \ - temp*(lg_xsteps/sm_xsteps)) - - elif attr == ystep_attr: - f[dset_fullname_small].attrs.create(attr, \ - sm_ysteps) - elif attr == ystep_size_attr: - temp = input_attrs[attr] - - f[dset_fullname_small].attrs.create(attr, \ - temp*(lg_ysteps/sm_ysteps)) - else: - f[dset_fullname_small].attrs.create(attr, \ - input_attrs[attr]) - except: - pass - finally: - f.close() \ No newline at end of file diff --git a/crikit/utils/tests/test_breadcrumb.py b/crikit/utils/tests/test_breadcrumb.py new file mode 100644 index 0000000..2a64db2 --- /dev/null +++ b/crikit/utils/tests/test_breadcrumb.py @@ -0,0 +1,23 @@ +import numpy as np + +import pytest + +from crikit.utils.breadcrumb import BCPre + +def test_breadcrumb(): + + atrdict = BCPre() + prefix = BCPre.PREFIX + + with pytest.raises(TypeError): + atrdict.add_step('Test1') + with pytest.raises(ValueError): + atrdict.add_step(['Test',1]) + + atrdict.add_step(['Raw']) + atrdict.add_step(['SubDark','RangeStart',-1500,'RangeEnd',-400]) + atrdict.add_step(['NormKK','Amp',100.0,'Phase',10.0]) + + assert atrdict.attr_dict[prefix] == 3 + + \ No newline at end of file diff --git a/crikit/utils/tests/test_general.py b/crikit/utils/tests/test_general.py new file mode 100644 index 0000000..a05dccc --- /dev/null +++ b/crikit/utils/tests/test_general.py @@ -0,0 +1,130 @@ +import numpy as np + +import pytest + +from crikit.utils.general import pad, pad_dual + +def test_pad_1d(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + + y_pad_edge, window_edge = pad(y, 10, 'edge') + assert np.allclose(y_pad_edge[10:-10], y) + assert np.allclose(y_pad_edge[:10], y[0]) + assert np.allclose(y_pad_edge[-10:], y[-1]) + + assert np.allclose(window_edge[10:-10], 1) + assert np.allclose(window_edge[:10], 0) + assert np.allclose(window_edge[-10:], 0) + + assert np.allclose(y_pad_edge[..., window_edge==1], y) + + y_pad_constant, window_constant = pad(y, 10, 'constant') + assert np.allclose(y_pad_constant[10:-10], y) + assert np.allclose(y_pad_constant[:10], 0) + assert np.allclose(y_pad_constant[-10:], 0) + + assert np.allclose(window_constant[10:-10], 1) + assert np.allclose(window_constant[:10], 0) + assert np.allclose(window_constant[-10:], 0) + + assert np.allclose(y_pad_constant[..., window_constant==1], y) + +def test_pad_1d_0_width(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + + y_pad_edge, window_edge = pad(y, 0, 'edge') + assert np.allclose(y_pad_edge, y) + assert np.allclose(y_pad_edge[..., window_edge==1], y) + assert np.allclose(window_edge, 1) + + y_pad_constant, window_constant = pad(y, 0, 'constant') + assert np.allclose(y_pad_constant, y) + assert np.allclose(y_pad_constant[..., window_constant==1], y) + assert np.allclose(window_constant, 1) + +def test_pad_2d(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + y = np.vstack((y, y)) + + assert y.shape[0] == 2 + assert y.shape[-1] == x.size + + y_pad_edge, window_edge = pad(y, 10, 'edge') + assert np.allclose(y_pad_edge[..., 10:-10], y) + + assert np.allclose(y_pad_edge[..., :10], np.dot(y[..., 0:1], np.ones((1, 10)))) + assert np.allclose(y_pad_edge[..., -10:], np.dot(y[..., -1:-2:-1], np.ones((1, 10)))) + + assert np.allclose(window_edge[10:-10], 1) + assert np.allclose(window_edge[:10], 0) + assert np.allclose(window_edge[-10:], 0) + + assert np.allclose(y_pad_edge[..., window_edge==1], y) + + y_pad_constant, window_constant = pad(y, 10, 'constant') + assert np.allclose(y_pad_constant[..., 10:-10], y) + assert np.allclose(y_pad_constant[..., :10], 0) + assert np.allclose(y_pad_constant[..., -10:], 0) + + assert np.allclose(window_constant[10:-10], 1) + assert np.allclose(window_constant[:10], 0) + assert np.allclose(window_constant[-10:], 0) + + assert np.allclose(y_pad_constant[..., window_constant==1], y) + +def test_pad_2d_0_width(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + y = np.vstack((y, y)) + + assert y.shape[0] == 2 + assert y.shape[-1] == x.size + + y_pad_edge, window_edge = pad(y, 0, 'edge') + assert np.allclose(y_pad_edge, y) + assert np.allclose(window_edge, 1) + assert np.allclose(y_pad_edge[..., window_edge==1], y) + + y_pad_constant, window_constant = pad(y, 0, 'constant') + assert np.allclose(y_pad_constant, y) + assert np.allclose(window_constant, 1) + assert np.allclose(y_pad_constant[..., window_constant==1], y) + + +def test_pad_dual_1d(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + + y_pad, window = pad_dual(y, 10, 20) + + assert np.allclose(y_pad[..., window==1], y) + assert np.allclose(y_pad[..., :20], 0) + assert np.allclose(y_pad[..., -20:], 0) + assert np.allclose(y_pad[..., 20:30], y[0]) + assert np.allclose(y_pad[..., -30:-20], y[-1]) + +def test_pad_dual_1d_all_0s(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + + y_pad, window = pad_dual(y, 0, 0) + + assert np.allclose(y_pad[..., window==1], y) + assert np.allclose(window, 1) + +def test_pad_dual_2d(): + x = np.arange(-1000,1001) + y = np.real(1/(-500 - x - 1j*100)) + y = np.vstack((y,y)) + + y_pad, window = pad_dual(y, 10, 20) + + assert np.allclose(y_pad[..., window==1], y) + assert np.allclose(y_pad[..., :20], 0) + assert np.allclose(y_pad[..., -20:], 0) + assert np.allclose(y_pad[..., 20:30], np.dot(y[..., 0:1], np.ones((1, 10)))) + assert np.allclose(y_pad[..., -30:-20], np.dot(y[..., -1:-2:-1], np.ones((1, 10)))) + diff --git a/docs/build/doctrees/algorithms.doctree b/docs/build/doctrees/algorithms.doctree deleted file mode 100644 index 7b82936..0000000 Binary files a/docs/build/doctrees/algorithms.doctree and /dev/null differ diff --git a/docs/build/doctrees/api.doctree b/docs/build/doctrees/api.doctree deleted file mode 100644 index f35477b..0000000 Binary files a/docs/build/doctrees/api.doctree and /dev/null differ diff --git a/docs/build/doctrees/cri_walkthru.doctree b/docs/build/doctrees/cri_walkthru.doctree deleted file mode 100644 index 48fb53f..0000000 Binary files a/docs/build/doctrees/cri_walkthru.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.cri.algorithms.doctree b/docs/build/doctrees/crikit.cri.algorithms.doctree deleted file mode 100644 index f085f03..0000000 Binary files a/docs/build/doctrees/crikit.cri.algorithms.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.cri.doctree b/docs/build/doctrees/crikit.cri.doctree deleted file mode 100644 index caa6ddb..0000000 Binary files a/docs/build/doctrees/crikit.cri.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.cri.tests.doctree b/docs/build/doctrees/crikit.cri.tests.doctree deleted file mode 100644 index 917d7d4..0000000 Binary files a/docs/build/doctrees/crikit.cri.tests.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.data.doctree b/docs/build/doctrees/crikit.data.doctree deleted file mode 100644 index 587d27c..0000000 Binary files a/docs/build/doctrees/crikit.data.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.datasets.doctree b/docs/build/doctrees/crikit.datasets.doctree deleted file mode 100644 index 7c71aa9..0000000 Binary files a/docs/build/doctrees/crikit.datasets.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.doctree b/docs/build/doctrees/crikit.doctree deleted file mode 100644 index df5541f..0000000 Binary files a/docs/build/doctrees/crikit.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.io.doctree b/docs/build/doctrees/crikit.io.doctree deleted file mode 100644 index 4cdf1ea..0000000 Binary files a/docs/build/doctrees/crikit.io.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.measurement.doctree b/docs/build/doctrees/crikit.measurement.doctree deleted file mode 100644 index 71dadd3..0000000 Binary files a/docs/build/doctrees/crikit.measurement.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.measurement.tests.doctree b/docs/build/doctrees/crikit.measurement.tests.doctree deleted file mode 100644 index f0a9955..0000000 Binary files a/docs/build/doctrees/crikit.measurement.tests.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.preprocess.algorithms.doctree b/docs/build/doctrees/crikit.preprocess.algorithms.doctree deleted file mode 100644 index bdbfd99..0000000 Binary files a/docs/build/doctrees/crikit.preprocess.algorithms.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.preprocess.doctree b/docs/build/doctrees/crikit.preprocess.doctree deleted file mode 100644 index b2a5153..0000000 Binary files a/docs/build/doctrees/crikit.preprocess.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.transform.doctree b/docs/build/doctrees/crikit.transform.doctree deleted file mode 100644 index e9c7681..0000000 Binary files a/docs/build/doctrees/crikit.transform.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.ui.doctree b/docs/build/doctrees/crikit.ui.doctree deleted file mode 100644 index ce5d398..0000000 Binary files a/docs/build/doctrees/crikit.ui.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.ui.utils.doctree b/docs/build/doctrees/crikit.ui.utils.doctree deleted file mode 100644 index f734ed5..0000000 Binary files a/docs/build/doctrees/crikit.ui.utils.doctree and /dev/null differ diff --git a/docs/build/doctrees/crikit.utils.doctree b/docs/build/doctrees/crikit.utils.doctree deleted file mode 100644 index 181abf6..0000000 Binary files a/docs/build/doctrees/crikit.utils.doctree and /dev/null differ diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree deleted file mode 100644 index deb3b83..0000000 Binary files a/docs/build/doctrees/index.doctree and /dev/null differ diff --git a/docs/build/doctrees/installing.doctree b/docs/build/doctrees/installing.doctree deleted file mode 100644 index e66818b..0000000 Binary files a/docs/build/doctrees/installing.doctree and /dev/null differ diff --git a/docs/build/doctrees/io.doctree b/docs/build/doctrees/io.doctree deleted file mode 100644 index 9b92ede..0000000 Binary files a/docs/build/doctrees/io.doctree and /dev/null differ diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree deleted file mode 100644 index 4b5cf04..0000000 Binary files a/docs/build/doctrees/modules.doctree and /dev/null differ diff --git a/docs/build/doctrees/nonlicense.doctree b/docs/build/doctrees/nonlicense.doctree deleted file mode 100644 index 7bb2657..0000000 Binary files a/docs/build/doctrees/nonlicense.doctree and /dev/null differ diff --git a/docs/build/doctrees/running.doctree b/docs/build/doctrees/running.doctree deleted file mode 100644 index 04ab3a6..0000000 Binary files a/docs/build/doctrees/running.doctree and /dev/null differ diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo deleted file mode 100644 index 3b34bc3..0000000 --- a/docs/build/html/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 9d3bb4c42bd6495330a5a78a206afb2e -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/.doctrees/algorithms.doctree b/docs/build/html/.doctrees/algorithms.doctree deleted file mode 100644 index 2057af3..0000000 Binary files a/docs/build/html/.doctrees/algorithms.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/api.doctree b/docs/build/html/.doctrees/api.doctree deleted file mode 100644 index 8c2d4bf..0000000 Binary files a/docs/build/html/.doctrees/api.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/cri_walkthru.doctree b/docs/build/html/.doctrees/cri_walkthru.doctree deleted file mode 100644 index ac74933..0000000 Binary files a/docs/build/html/.doctrees/cri_walkthru.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.cri.algorithms.doctree b/docs/build/html/.doctrees/crikit.cri.algorithms.doctree deleted file mode 100644 index 23d99e5..0000000 Binary files a/docs/build/html/.doctrees/crikit.cri.algorithms.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.cri.doctree b/docs/build/html/.doctrees/crikit.cri.doctree deleted file mode 100644 index 4081c60..0000000 Binary files a/docs/build/html/.doctrees/crikit.cri.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.cri.tests.doctree b/docs/build/html/.doctrees/crikit.cri.tests.doctree deleted file mode 100644 index 6e5824c..0000000 Binary files a/docs/build/html/.doctrees/crikit.cri.tests.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.data.doctree b/docs/build/html/.doctrees/crikit.data.doctree deleted file mode 100644 index 5dd3ea6..0000000 Binary files a/docs/build/html/.doctrees/crikit.data.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.datasets.doctree b/docs/build/html/.doctrees/crikit.datasets.doctree deleted file mode 100644 index 5d1c83e..0000000 Binary files a/docs/build/html/.doctrees/crikit.datasets.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.doctree b/docs/build/html/.doctrees/crikit.doctree deleted file mode 100644 index 65ece40..0000000 Binary files a/docs/build/html/.doctrees/crikit.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.io.doctree b/docs/build/html/.doctrees/crikit.io.doctree deleted file mode 100644 index 0d69860..0000000 Binary files a/docs/build/html/.doctrees/crikit.io.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.measurement.doctree b/docs/build/html/.doctrees/crikit.measurement.doctree deleted file mode 100644 index db30bf1..0000000 Binary files a/docs/build/html/.doctrees/crikit.measurement.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.measurement.tests.doctree b/docs/build/html/.doctrees/crikit.measurement.tests.doctree deleted file mode 100644 index eed3231..0000000 Binary files a/docs/build/html/.doctrees/crikit.measurement.tests.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.preprocess.algorithms.doctree b/docs/build/html/.doctrees/crikit.preprocess.algorithms.doctree deleted file mode 100644 index 60432de..0000000 Binary files a/docs/build/html/.doctrees/crikit.preprocess.algorithms.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.preprocess.doctree b/docs/build/html/.doctrees/crikit.preprocess.doctree deleted file mode 100644 index 920944d..0000000 Binary files a/docs/build/html/.doctrees/crikit.preprocess.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.transform.doctree b/docs/build/html/.doctrees/crikit.transform.doctree deleted file mode 100644 index ad7bfdc..0000000 Binary files a/docs/build/html/.doctrees/crikit.transform.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.ui.doctree b/docs/build/html/.doctrees/crikit.ui.doctree deleted file mode 100644 index cdbce31..0000000 Binary files a/docs/build/html/.doctrees/crikit.ui.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.ui.utils.doctree b/docs/build/html/.doctrees/crikit.ui.utils.doctree deleted file mode 100644 index bd37486..0000000 Binary files a/docs/build/html/.doctrees/crikit.ui.utils.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/crikit.utils.doctree b/docs/build/html/.doctrees/crikit.utils.doctree deleted file mode 100644 index 2abff2b..0000000 Binary files a/docs/build/html/.doctrees/crikit.utils.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/index.doctree b/docs/build/html/.doctrees/index.doctree deleted file mode 100644 index d3f8360..0000000 Binary files a/docs/build/html/.doctrees/index.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/installing.doctree b/docs/build/html/.doctrees/installing.doctree deleted file mode 100644 index 3351ac5..0000000 Binary files a/docs/build/html/.doctrees/installing.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/io.doctree b/docs/build/html/.doctrees/io.doctree deleted file mode 100644 index 71f0a90..0000000 Binary files a/docs/build/html/.doctrees/io.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/modules.doctree b/docs/build/html/.doctrees/modules.doctree deleted file mode 100644 index fa78b31..0000000 Binary files a/docs/build/html/.doctrees/modules.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/nonlicense.doctree b/docs/build/html/.doctrees/nonlicense.doctree deleted file mode 100644 index a4dea36..0000000 Binary files a/docs/build/html/.doctrees/nonlicense.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/running.doctree b/docs/build/html/.doctrees/running.doctree deleted file mode 100644 index 4d2d7fe..0000000 Binary files a/docs/build/html/.doctrees/running.doctree and /dev/null differ diff --git a/docs/build/html/_images/ALS.png b/docs/build/html/_images/ALS.png deleted file mode 100644 index 4e4a5d1..0000000 Binary files a/docs/build/html/_images/ALS.png and /dev/null differ diff --git a/docs/build/html/_images/Anscombe.png b/docs/build/html/_images/Anscombe.png deleted file mode 100644 index 34c2407..0000000 Binary files a/docs/build/html/_images/Anscombe.png and /dev/null differ diff --git a/docs/build/html/_images/CRIkit2_Logo.png b/docs/build/html/_images/CRIkit2_Logo.png deleted file mode 100644 index b3cde5e..0000000 Binary files a/docs/build/html/_images/CRIkit2_Logo.png and /dev/null differ diff --git a/docs/build/html/_images/Calibration.png b/docs/build/html/_images/Calibration.png deleted file mode 100644 index cb4fc4d..0000000 Binary files a/docs/build/html/_images/Calibration.png and /dev/null differ diff --git a/docs/build/html/_images/CompositeColorExample.png b/docs/build/html/_images/CompositeColorExample.png deleted file mode 100644 index 9bb1a93..0000000 Binary files a/docs/build/html/_images/CompositeColorExample.png and /dev/null differ diff --git a/docs/build/html/_images/Elastin.png b/docs/build/html/_images/Elastin.png deleted file mode 100644 index 5a0cd3f..0000000 Binary files a/docs/build/html/_images/Elastin.png and /dev/null differ diff --git a/docs/build/html/_images/KKInteractive.png b/docs/build/html/_images/KKInteractive.png deleted file mode 100644 index 081ca0e..0000000 Binary files a/docs/build/html/_images/KKInteractive.png and /dev/null differ diff --git a/docs/build/html/_images/KKOptions.png b/docs/build/html/_images/KKOptions.png deleted file mode 100644 index 9eec813..0000000 Binary files a/docs/build/html/_images/KKOptions.png and /dev/null differ diff --git a/docs/build/html/_images/LoadModel.png b/docs/build/html/_images/LoadModel.png deleted file mode 100644 index 5f2d790..0000000 Binary files a/docs/build/html/_images/LoadModel.png and /dev/null differ diff --git a/docs/build/html/_images/Nuclei.png b/docs/build/html/_images/Nuclei.png deleted file mode 100644 index 0c6be9d..0000000 Binary files a/docs/build/html/_images/Nuclei.png and /dev/null differ diff --git a/docs/build/html/_images/Open.png b/docs/build/html/_images/Open.png deleted file mode 100644 index 0e07a76..0000000 Binary files a/docs/build/html/_images/Open.png and /dev/null differ diff --git a/docs/build/html/_images/OpenDark.png b/docs/build/html/_images/OpenDark.png deleted file mode 100644 index a71710f..0000000 Binary files a/docs/build/html/_images/OpenDark.png and /dev/null differ diff --git a/docs/build/html/_images/OpenNRB.png b/docs/build/html/_images/OpenNRB.png deleted file mode 100644 index a61157a..0000000 Binary files a/docs/build/html/_images/OpenNRB.png and /dev/null differ diff --git a/docs/build/html/_images/Overview.png b/docs/build/html/_images/Overview.png deleted file mode 100644 index 2c3fdee..0000000 Binary files a/docs/build/html/_images/Overview.png and /dev/null differ diff --git a/docs/build/html/_images/Overview_post_gen_BCARS.png b/docs/build/html/_images/Overview_post_gen_BCARS.png deleted file mode 100644 index c50d18a..0000000 Binary files a/docs/build/html/_images/Overview_post_gen_BCARS.png and /dev/null differ diff --git a/docs/build/html/_images/Phenylalanine.png b/docs/build/html/_images/Phenylalanine.png deleted file mode 100644 index 79275f2..0000000 Binary files a/docs/build/html/_images/Phenylalanine.png and /dev/null differ diff --git a/docs/build/html/_images/RoiRawSpectra.png b/docs/build/html/_images/RoiRawSpectra.png deleted file mode 100644 index 4257c7d..0000000 Binary files a/docs/build/html/_images/RoiRawSpectra.png and /dev/null differ diff --git a/docs/build/html/_images/SG.png b/docs/build/html/_images/SG.png deleted file mode 100644 index 3dd2bdc..0000000 Binary files a/docs/build/html/_images/SG.png and /dev/null differ diff --git a/docs/build/html/_images/SVD_Ui.png b/docs/build/html/_images/SVD_Ui.png deleted file mode 100644 index 2902f79..0000000 Binary files a/docs/build/html/_images/SVD_Ui.png and /dev/null differ diff --git a/docs/build/html/_images/Save.png b/docs/build/html/_images/Save.png deleted file mode 100644 index ddaa265..0000000 Binary files a/docs/build/html/_images/Save.png and /dev/null differ diff --git a/docs/build/html/_images/SingleColorExample.png b/docs/build/html/_images/SingleColorExample.png deleted file mode 100644 index c26904a..0000000 Binary files a/docs/build/html/_images/SingleColorExample.png and /dev/null differ diff --git a/docs/build/html/_images/Spectrum_Before_After_SVD.png b/docs/build/html/_images/Spectrum_Before_After_SVD.png deleted file mode 100644 index f260446..0000000 Binary files a/docs/build/html/_images/Spectrum_Before_After_SVD.png and /dev/null differ diff --git a/docs/build/html/_images/StructuralProtein.png b/docs/build/html/_images/StructuralProtein.png deleted file mode 100644 index 7c2629c..0000000 Binary files a/docs/build/html/_images/StructuralProtein.png and /dev/null differ diff --git a/docs/build/html/_images/Sub_dark_dialogs.png b/docs/build/html/_images/Sub_dark_dialogs.png deleted file mode 100644 index a920fac..0000000 Binary files a/docs/build/html/_images/Sub_dark_dialogs.png and /dev/null differ diff --git a/docs/build/html/_modules/crikit/CRIkitUI.html b/docs/build/html/_modules/crikit/CRIkitUI.html deleted file mode 100644 index 095208b..0000000 --- a/docs/build/html/_modules/crikit/CRIkitUI.html +++ /dev/null @@ -1,3383 +0,0 @@ - - - - - - - - - - - crikit.CRIkitUI — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.CRIkitUI

-"""
-CRIKit2: Hyperspectral imaging toolkit
-==============================================================
-
-CRIKit2, formerly the Coherent Raman Imaging toolKit, is a hyperspectral
-imaging (HSI) platform (user interface, UI).
-
-HSI Processing:
-    * Dark subtraction
-    * Detrending
-    * Denoising
-
-Coherent Raman-Specific Processing:
-    * Kramers-Kronig phase retrieval
-    * Phase- and scale-error correction
-
-Analysis:
-    * Coming soon
-
-Usage
------
-From ./crikit2 directory
-python3 main.py
-
-Authors
--------
-* Charles H. Camp Jr. <charles.camp@nist.gov>
-"""
-
-import copy as _copy
-import os as _os
-import sys as _sys
-import webbrowser as _webbrowser
-
-import h5py as _h5py
-import matplotlib as _mpl
-import numpy as _np
-
-import PyQt5.QtCore as _QtCore
-
-from PyQt5.QtGui import QCursor as _QCursor
-from PyQt5.QtWidgets import QApplication as _QApplication
-from PyQt5.QtWidgets import QFileDialog as _QFileDialog
-from PyQt5.QtWidgets import QInputDialog as _QInputDialog
-from PyQt5.QtWidgets import QMainWindow as _QMainWindow
-from PyQt5.QtWidgets import QMessageBox as _QMessageBox
-from PyQt5.QtWidgets import QWidget as _QWidget
-from scipy.signal import savgol_filter as _sg
-
-
-from crikit.cri.error_correction import \
-    PhaseErrCorrectALS as _PhaseErrCorrectALS
-from crikit.cri.error_correction import ScaleErrCorrectSG as _ScaleErrCorrectSG
-from crikit.cri.kk import KramersKronig
-from crikit.cri.merge_nrbs import MergeNRBs as _MergeNRBs
-
-from crikit.data.frequency import calib_pix_wn as _calib_pix_wn
-from crikit.data.hsi import Hsi
-from crikit.data.spectra import Spectra
-from crikit.data.spectrum import Spectrum
-
-from crikit.datasets.model import Model as _Model
-
-from crikit.io.hdf5 import hdf_is_valid_dsets
-from crikit.io.macros import import_csv_nist_special1 as io_nist_dlm
-from crikit.io.macros import import_hdf_nist_special as io_nist
-
-import crikit.measurement.peakamps as _peakamps
-
-from crikit.preprocess.crop import ZeroColumn as _ZeroColumn
-from crikit.preprocess.crop import ZeroRow as _ZeroRow
-from crikit.preprocess.denoise import SVDDecompose, SVDRecompose
-from crikit.preprocess.standardize import Anscombe as _Anscombe
-from crikit.preprocess.standardize import AnscombeInverse as _AnscombeInverse
-from crikit.preprocess.subtract_baseline import \
-    SubtractBaselineALS as _SubtractBaselineALS
-from crikit.preprocess.subtract_dark import SubtractDark
-from crikit.preprocess.subtract_mean import SubtractMeanOverRange
-
-from crikit.ui.dialog_kkOptions import DialogKKOptions
-from crikit.ui.dialog_model import DialogModel
-from crikit.ui.dialog_ploteffect import \
-    DialogPlotEffectFuture as _DialogPlotEffect
-from crikit.ui.dialog_save import DialogSave
-from crikit.ui.dialog_varstabAnscombeOptions import DialogAnscombeOptions
-from crikit.ui.qt_CRIkit import Ui_MainWindow
-from crikit.ui.subui_hdf_load import SubUiHDFLoad
-from crikit.ui.utils.roi import roimask as _roimask
-from crikit.ui.widget_Calibrate import widgetCalibrate as _widgetCalibrate
-from crikit.ui.widget_DeTrending import widgetALS as _widgetALS
-from crikit.ui.widget_DeTrending import widgetArPLS as _widgetArPLS
-from crikit.ui.widget_DeTrending import widgetDeTrending as _widgetDeTrending
-from crikit.ui.widget_images import (widgetBWImg, widgetCompositeColor, widgetSglColor)
-
-from crikit.ui.widget_mergeNRBs import widgetMergeNRBs as _widgetMergeNRBs
-from crikit.ui.widget_SG import widgetSG as _widgetSG
-
-from crikit.utils.breadcrumb import BCPre as _BCPre
-from crikit.utils.general import find_nearest, mean_nd_to_1d
-
-from sciplot.sciplotUI import SciPlotUI as _SciPlotUI
-
-_h5py.get_config().complex_names = ('Re', 'Im')
-
-force_not_sw = False
-
-try:
-    import crikit2_sw
-except:
-    __sw_installed = False
-    print('SW package not installed, using standard')
-    from crikit.ui.dialog_SVD import DialogSVD
-else:
-    __sw_installed = True
-
-    if force_not_sw:
-        print('SW package installed, but forced off -- using standard')
-        from crikit.ui.dialog_SVD import DialogSVD
-    else:
-        print('SW package installed, let\'s rock!')
-        from crikit2_sw.ui.dialog_SVD import DialogSVD
-
-
-_mpl.use('Qt5Agg')
-_mpl.rcParams['font.family'] = 'sans-serif'
-_mpl.rcParams['font.size'] = 12
-
-jupyter_flag = 0
-try:
-    from crikit.ui.widget_Jupyter import QJupyterWidget
-    jupyter_flag = 1
-except:
-    print('No appropriate Jupyter/IPython installation found. Console will not be available')
-    jupyter_flag = -1
-
-help_index = _os.path.abspath(_os.path.join(_os.path.dirname(__file__), 
-                              '../docs/build/html/index.html'))
-
-if _os.path.exists(help_index):
-    pass
-else:
-    help_index = None
-
-
[docs]class CRIkitUI_process(_QMainWindow): - """ - CRIkitUI_process : CRIkitUI for image (pre-)processing - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - """ - - NUMCOLORS = 4 # Number of single-color windows to auto-generate - - def __init__(self, **kwargs): - - # Generic load/init designer-based GUI - parent = kwargs.get('parent') - - super(CRIkitUI_process, self).__init__(parent) ### EDIT ### - - - self.parent = parent - - self.filename = kwargs.get('filename') - self.path = kwargs.get('path') - self.dataset_name = kwargs.get('dataset_name') - - self.hsi = kwargs.get('hsi') - if not isinstance(self.hsi, Hsi): - self.hsi = Hsi() - - self.bcpre = _BCPre() - - self.dark = Spectra() - self.nrb = Spectra() - - # Overlays - self.overlays = [] - self.show_overlays = True - - # Piecewise NRB's (not always used) - self.nrb_left = Spectra() - self.nrb_right = Spectra() - - # Internal Parameters - self._anscombe_params = None - - - self.plotter = _SciPlotUI(show=False, parent=self.parent) - self._mpl_v2 = self.plotter._mpl_v2 - - self.ui = Ui_MainWindow() ### EDIT ### - - - self.ui.setupUi(self) ### EDIT ### - - # Match UI Show overlays to attribute of this class - self.ui.actionShowOverlays.setChecked(self.show_overlays) - - - # Initialize Intensity image (single frequency B&W) - self.img_BW = widgetBWImg(parent=self, figfacecolor=[1, 1, 1]) - if self.img_BW.ui.checkBoxFixed.checkState() == 0: - self.img_BW.ui.spinBoxMax.setValue(self.img_BW.data.maxer) - self.img_BW.ui.spinBoxMin.setValue(self.img_BW.data.minner) - - self.ui.sweeperVL.insertWidget(0, self.img_BW) - self.img_BW.mpl.fig.tight_layout(pad=2) - # ID used for matplotlib to connect to a figure - self.cid = None - - # Initialize Single-Color RGB widgets - self.img_RGB_list = [] - - for count in range(self.NUMCOLORS): - self.img_RGB_list.append(widgetSglColor(figfacecolor=[1, 1, 1], - parent=self)) - - # Split from previous for-loop for compactness of code - for count, rgb_img in enumerate(self.img_RGB_list): - color_str = rgb_img.colormode.ui.comboBoxFGColor.itemText(count) - - # Note: colors.to_rgb exists in MPL 2*, but is under colorConverter - # in MPL < 2. - rgb_img.data.colormap = _mpl.colors.colorConverter.to_rgb(_mpl.colors.cnames[color_str]) - rgb_img.colormode.ui.comboBoxFGColor.setCurrentIndex(count) - - rgb_img.popimage.ui.pushButtonSpectrum.setEnabled(False) - self.ui.tabColors.addTab(rgb_img, 'Color ' + str(count)) - - - rgb_img.math.ui.pushButtonBasicMath.setEnabled(False) - rgb_img.math.ui.pushButtonScripting.setEnabled(False) - - rgb_img.math.ui.pushButtonOpFreq1.pressed.connect(self.setOpFreq1) - rgb_img.math.ui.pushButtonOpFreq2.pressed.connect(self.setOpFreq2) - rgb_img.math.ui.pushButtonOpFreq3.pressed.connect(self.setOpFreq3) - rgb_img.math.ui.comboBoxOperations.currentIndexChanged.connect(self.opChange) - rgb_img.math.ui.pushButtonCondFreq1.pressed.connect(self.setCondFreq1) - rgb_img.math.ui.pushButtonCondFreq2.pressed.connect(self.setCondFreq2) - rgb_img.math.ui.pushButtonCondFreq3.pressed.connect(self.setCondFreq3) - rgb_img.math.ui.comboBoxCondOps.currentIndexChanged.connect(self.condOpChange) - rgb_img.math.ui.comboBoxCondInEquality.currentIndexChanged.connect(self.condInEqualityChange) - rgb_img.math.ui.spinBoxInEquality.editingFinished.connect(self.spinBoxInEqualityChange) - rgb_img.math.ui.pushButtonBasicMath.pressed.connect(self.doMath) - rgb_img.ui.spinBoxMax.editingFinished.connect(self.doComposite) - rgb_img.ui.spinBoxMin.editingFinished.connect(self.doComposite) - rgb_img.math.ui.spinBoxGain.valueChanged.connect(self.doComposite) - - - self.img_Composite = widgetCompositeColor(self.img_RGB_list, - figfacecolor=[1, 1, 1]) - self.img_Composite2 = widgetCompositeColor(self.img_RGB_list, - figfacecolor=[1, 1, 1]) - - self.ui.tabColors.addTab(self.img_Composite, 'Composite Image') - - self.ui.sweeperVL_2.insertWidget(0, self.img_Composite2) - - self.ui.tabColors.currentChanged.connect(self.checkCompositeUpdate) - - - # SIGNALS & SLOTS - - # Load Data - self.ui.actionOpenHDFNIST.triggered.connect(self.fileOpenHDFNIST) - self.ui.actionLoadNRB.triggered.connect(self.loadNRB) - self.ui.actionLoadDark.triggered.connect(self.loadDark) - - self.ui.actionOpenDLMNIST.triggered.connect(self.fileOpenDLMNIST) - self.ui.actionLoadNRBDLM.triggered.connect(self.loadNRBDLM) - self.ui.actionLoadDarkDLM.triggered.connect(self.loadDarkDLM) - - self.ui.actionNRB_from_ROI.triggered.connect(self.nrbFromROI) - self.ui.actionAppend_NRB_from_ROI.triggered.connect(self.nrbFromROI) - - self.ui.actionLoad_NRB_Left_Side.triggered.connect(self.loadNRB) - self.ui.actionNRB_from_ROI_Left_Side.triggered.connect(self.nrbFromROI) - - self.ui.actionLoad_NRB_Right_Side.triggered.connect(self.loadNRB) - self.ui.actionNRB_from_ROI_Right_Side.triggered.connect(self.nrbFromROI) - - self.ui.actionMergeNRBs.triggered.connect(self.mergeNRBs) - - # Settings - self.ui.actionSettings.triggered.connect(self.settings) - - # Undo - self.ui.actionUndo.triggered.connect(self.doUndo) - - # Close event - self.ui.closeEvent = self.closeEvent - - # Subtract DARK-Related - self.ui.actionDarkSubtract.triggered.connect(self.subDark) - self.ui.actionResidualSubtract.triggered.connect(self.subResidual) - - - # ZERO first column or row - self.ui.actionZeroFirstColumn.triggered.connect(self.zeroFirstColumn) - self.ui.actionZeroFirstRow.triggered.connect(self.zeroFirstRow) - self.ui.actionZeroLastColumn.triggered.connect(self.zeroLastColumn) - self.ui.actionZeroLastRow.triggered.connect(self.zeroLastRow) - - # Set frequency WINDOW - self.ui.actionFreqWindow.triggered.connect(self.freqWindow) - - # Calibrate Wavenumber - self.ui.actionCalibrate.triggered.connect(self.calibrate) - self.ui.actionResetCalibration.triggered.connect(self.calibrationReset) - - # Perform KK - self.ui.actionKramersKronig.triggered.connect(self.doKK) - - self.ui.actionKKSpeedTest.setEnabled(False) - - # Variance Stabilize - self.ui.actionAnscombe.triggered.connect(self.anscombe) - self.ui.actionInverseAnscombe.triggered.connect(self.inverseAnscombe) - - # DeNoise - self.ui.actionDeNoise.triggered.connect(self.deNoise) - self.ui.actionDeNoiseNRB.triggered.connect(self.deNoiseNRB) - self.ui.actionDeNoiseDark.triggered.connect(self.deNoiseDark) - - # Error Correction - self.ui.actionPhaseErrorCorrection.triggered.connect(self.errorCorrectPhase) - self.ui.actionScaleErrorCorrection.triggered.connect(self.errorCorrectScale) - self.ui.actionAmpErrorCorrection.triggered.connect(self.errorCorrectAmp) - self.ui.actionSubtractROI.triggered.connect(self.subtractROIStart) - - # SAVE - - self.ui.actionSave.triggered.connect(self.save) - - # Plotting spectra-related - self.ui.actionPointSpectrum.triggered.connect(self.pointSpectrum) - self.ui.actionROISpectrum.triggered.connect(self.roiSpectrum) - - self.ui.actionDarkSpectrum.triggered.connect(self.plotDarkSpectrum) - self.ui.actionNRBSpectrum.triggered.connect(self.plotNRBSpectrum) - self.ui.actionLeftSideNRBSpect.triggered.connect(self.plotLeftNRBSpectrum) - self.ui.actionRightSideNRBSpect.triggered.connect(self.plotRightNRBSpectrum) - self.ui.actionShowPlotter.triggered.connect(self.plotter_show) - - # Overlays - self.plotter.modelLine.dataDeleted.connect(self.updateOverlays) - self.plotter.modelLine.dataChanged.connect(self.updateOverlays) - self.plotter.all_cleared.connect(self.deleteOverlays) - self.ui.actionShowOverlays.triggered.connect(self.checkShowOverlays) - self.ui.actionShowOverlayLegend.triggered.connect(self.changeSlider) - - # Frequency-slider related - self.ui.freqSlider.valueChanged.connect(self.changeSlider) - self.ui.freqSlider.sliderPressed.connect(self.sliderPressed) - self.ui.freqSlider.sliderReleased.connect(self.sliderReleased) - self.ui.freqSlider.setTracking(True) - - # Frequency-slider display boxes - self.ui.lineEditFreq.editingFinished.connect(self.lineEditFreqChanged) - self.ui.lineEditPix.editingFinished.connect(self.lineEditPixChanged) - self.ui.lineEditPix.setVisible(False) - self.ui.labelFreqPixel.setVisible(False) - - # Help - if help_index is not None: - self.ui.actionHelpManual.triggered.connect(lambda: _webbrowser.open('file:///' + help_index, new=1)) - else: - self.ui.actionHelpManual.setEnabled(False) - - self.ui.actionRamanPhantom.triggered.connect(self.makeRamanPhantom) - self.ui.actionBCARSPhantom.triggered.connect(self.makeBCARSPhantom) - - # Jupyter console - - if jupyter_flag == 1: - try: - self.jupyterConsole = QJupyterWidget(customBanner='Welcome to the ' - 'embedded ipython console\n\n') - except: - print('Error loading embedded IPython Notebook') - else: - self.ui.tabMain.addTab(self.jupyterConsole, 'Jupyter/IPython Console') - - self.jupyterConsole.pushVariables({'ui':self.ui, - 'bcpre':self.bcpre, - 'dark':self.dark, - 'nrb':self.nrb, - 'crikit_data':self}) - self.ui.tabMain.currentChanged.connect(self.tabMainChange) - - - # Temporary toolbar setup - self.ui.toolBar.setVisible(True) - self.ui.toolBar.setToolButtonStyle(_QtCore.Qt.ToolButtonTextUnderIcon) - self.ui.actionToolBarNIST1.triggered.connect(self.toolbarSetting) - self.ui.actionToolBarNIST2.triggered.connect(self.toolbarSetting) - self.ui.actionToolBarNone.triggered.connect(self.toolbarSetting) - - # Default toolbar is NIST Workflow - self.ui.actionToolBarNIST2.trigger() - - # COMMAND LINE INTERPRETATION - - # file and dset info provided - if hdf_is_valid_dsets(self.path, self.filename, self.dataset_name): - self.fileOpenHDFNIST(dialog=False) - - # Hsi provided - temp = kwargs.get('hsi') - if temp is not None: - try: - self.fileOpenSuccess(True) - except: - print('Error in input hsi') - self.hsi = Hsi() - - # x-array provided - temp = kwargs.get('x') - if temp is not None: - try: - self.hsi.x = temp - self.hsi._x_rep.units = kwargs.get('x_units') - self.hsi._x_rep.label = kwargs.get('x_label') - except: - print('Error in input x-array') - self.hsi.x = None - - # y-array provided - temp = kwargs.get('y') - if temp is not None: - try: - self.hsi.y = temp - self.hsi._y_rep.units = kwargs.get('y_units') - self.hsi._y_rep.label = kwargs.get('y_label') - except: - print('Error in input y-array') - self.hsi.y = None - - # freq-array provided - temp = kwargs.get('f') - if temp is not None: - try: - self.hsi.freq._data = temp - self.hsi.freq._units = kwargs.get('f_units') - self.hsi.freq._label = kwargs.get('f_label') - except: - print('Error in input freq-array (f)') - self.hsi.freq._data = None - - # data provided - if isinstance(kwargs.get('data'), _np.ndarray): - try: - self.hsi.data = kwargs.get('data') - self.hsi.check() - self.fileOpenSuccess(True) - except: - print('Error in input data') - self.hsi = Hsi() - -
[docs] def plotter_show(self): - self.plotter.show() - self.plotter.raise_()
- -
[docs] def toolbarSetting(self): - """ - Toolbar settings through View menu. - """ - toolbar_actions = [self.ui.actionToolBarNone, - self.ui.actionToolBarNIST2, - self.ui.actionToolBarNIST1] - - sndr = self.sender() - for tb in toolbar_actions: - if sndr == tb: - tb.setChecked(True) - else: - tb.setChecked(False) - - # Hide toolbar if None - if sndr == self.ui.actionToolBarNone: - self.ui.toolBar.setVisible(False) - else: - self.ui.toolBar.clear() - self.ui.toolBar.setVisible(True) - - # So far only NIST toolbar setup - if sndr == self.ui.actionToolBarNIST2: - self.ui.actionToolBarNIST2.setChecked(True) - self.ui.toolBar.addActions([self.ui.actionOpenHDFNIST, - self.ui.actionSave]) - - self.ui.toolBar.addSeparator() - self.ui.toolBar.addActions([self.ui.actionPointSpectrum, - self.ui.actionROISpectrum]) - self.ui.toolBar.addSeparator() - self.ui.toolBar.addAction(self.ui.actionUndo) - - self.ui.toolBar.addSeparator() - self.ui.toolBar.addActions([self.ui.actionLoadDark, - self.ui.actionLoadNRB]) - - self.ui.toolBar.addSeparator() - self.ui.toolBar.addActions([self.ui.actionDarkSubtract, - self.ui.actionResidualSubtract, - self.ui.actionFreqWindow, - self.ui.actionAnscombe, - self.ui.actionDeNoise, - self.ui.actionInverseAnscombe, - self.ui.actionKramersKronig, - self.ui.actionPhaseErrorCorrection, - self.ui.actionScaleErrorCorrection, - self.ui.actionSubtractROI, - self.ui.actionCalibrate, - self.ui.actionAmpErrorCorrection]) - - elif sndr == self.ui.actionToolBarNIST1: - self.ui.actionToolBarNIST2.setChecked(True) - self.ui.toolBar.addActions([self.ui.actionOpenDLMNIST, - self.ui.actionSave]) - - self.ui.toolBar.addSeparator() - self.ui.toolBar.addActions([self.ui.actionPointSpectrum, - self.ui.actionROISpectrum]) - self.ui.toolBar.addSeparator() - self.ui.toolBar.addAction(self.ui.actionUndo) - - self.ui.toolBar.addSeparator() - self.ui.toolBar.addActions([self.ui.actionLoadDarkDLM, - self.ui.actionLoadNRBDLM]) - - self.ui.toolBar.addSeparator() - self.ui.toolBar.addActions([self.ui.actionDarkSubtract, - self.ui.actionResidualSubtract, - self.ui.actionFreqWindow, - self.ui.actionAnscombe, - self.ui.actionDeNoise, - self.ui.actionInverseAnscombe, - self.ui.actionKramersKronig, - self.ui.actionPhaseErrorCorrection, - self.ui.actionScaleErrorCorrection, - self.ui.actionSubtractROI, - self.ui.actionCalibrate, - self.ui.actionAmpErrorCorrection])
- -
[docs] def save(self): - suffix = self.bcpre.dset_name_suffix - - try: - ret = DialogSave.dialogSave(parent=self, - current_filename=self.filename, - current_path=self.path, - current_dataset_name=self.dataset_name[0], - suffix=suffix) - if ret is None: - pass # Save canceled - else: - self.save_filename = ret[0] - self.save_path = ret[1] - self.save_dataset_name = ret[2] - - self.save_grp = self.save_dataset_name.rpartition('/')[0] - self.save_dataset_name_no_grp = self.save_dataset_name.rpartition('/')[-1] - - - - try: - f_out = _h5py.File(self.save_path + self.save_filename, 'a') - loc = f_out.require_group(self.save_grp) - dset = loc.create_dataset(self.save_dataset_name_no_grp, data=self.hsi.data) - - meta = self.hsi.meta - for attr_key in meta: - val = meta[attr_key] - if isinstance(val, str): - dset.attrs[attr_key] = val - else: - try: - dset.attrs.create(attr_key, self.hsi.meta[attr_key]) - except: - print('Error in HSI attributes: {}'.format(attr_key)) - - bc_attr_dict = self.bcpre.attr_dict - - for attr_key in bc_attr_dict: - val = bc_attr_dict[attr_key] - if isinstance(val, str): - dset.attrs[attr_key] = val - else: - try: - dset.attrs.create(attr_key, bc_attr_dict[attr_key]) - except: - print('Could not create attribute') - - except: - print('Something went wrong while saving') - else: - print('Saved without issues') - finally: - f_out.close() - self.setWindowTitle('{} -> {}'.format(self.windowTitle(), self.save_filename)) - - except: - print('Couldn\'t open save dialog')
- -
[docs] def tabMainChange(self): - if self.ui.tabMain.currentIndex() == 4: # Jupyter console - self.jupyterConsole._control.setFocus()
- -
[docs] def closeEvent(self, event): - print('Closing') - app = _QApplication.instance() - app.closeAllWindows() - app.quit() - self.bcpre.pop_to_last(all=True) - - del_flag = 0 - - for count in self.bcpre.cut_list: - try: - _os.remove(count + '.pickle') - except: - print('Error in deleting old pickle files') - else: - del_flag += 1 - if del_flag == len(self.bcpre.cut_list): - del self.bcpre.cut_list - else: - print('Did not delete pickle file cut list... Something went wrong')
- -
[docs] def fileOpenHDFNIST(self, *args, dialog=True): - """ - Open and load HDF5 File - - dialog : bool - Present a gui for file and dataset selection - """ - - # Get data and load into CRI_HSI class - # This will need to change to accomodate multiple-file selection - - if dialog: - try: - to_open = SubUiHDFLoad.getFileDataSets(self.path) - print('to_open: {}'.format(to_open)) - if to_open is not None: - self.path, self.filename, self.dataset_name = to_open - except: - print('Could not open file. Corrupt or not appropriate file format.') - else: - if to_open is not None: - self.hsi = Hsi() - success = io_nist(self.path, self.filename, self.dataset_name, - self.hsi) - self.fileOpenSuccess(success) - else: - self.hsi = Hsi() - success = io_nist(self.path, self.filename, self.dataset_name, - self.hsi) - self.fileOpenSuccess(success)
- -
[docs] def fileOpenDLMNIST(self): - """ - Open and load DLM File - """ - - # Get data and load into CRI_HSI class - # This will need to change to accomodate multiple-file selection - filename_header,_ = _QFileDialog.getOpenFileName(self, 'Open Header File', - './', 'All Files (*.*)') - - - if filename_header != '': - self.path = _os.path.dirname(filename_header) + '/' - filename_data,_ = _QFileDialog.getOpenFileName(self, 'Open Data File', - self.path, - 'All Files (*.*)') - - if filename_data != '': - self.path = _os.path.dirname(filename_data) + '/' - self.filename = filename_data.split(_os.path.dirname(filename_data))[1][1::] - self.filename_header = filename_header - - success = io_nist_dlm(self.path, self.filename_header, - self.filename, - self.hsi) - self.fileOpenSuccess(success)
- -
[docs] def fileOpenSuccess(self, success): - """ - Executed after a file is loaded. Checks success and appropriately - activates or deactivates action (buttons) - """ - if success: - self.setWindowTitle('{}: {}'.format(self.windowTitle(), self.filename)) - # FILE - self.ui.actionSave.setEnabled(True) - - # EDIT - self.ui.actionZeroFirstColumn.setEnabled(True) - self.ui.actionZeroFirstRow.setEnabled(True) - self.ui.actionZeroLastColumn.setEnabled(True) - self.ui.actionZeroLastRow.setEnabled(True) - self.ui.actionFreqWindow.setEnabled(True) - self.ui.actionCalibrate.setEnabled(True) - self.ui.actionResetCalibration.setEnabled(True) - - # VIEW - self.ui.actionPointSpectrum.setEnabled(True) - self.ui.actionROISpectrum.setEnabled(True) - - # IMPORT/LOAD - self.ui.actionLoadDark.setEnabled(True) - self.ui.actionLoadNRB.setEnabled(True) - self.ui.actionLoadDarkDLM.setEnabled(True) - self.ui.actionLoadNRBDLM.setEnabled(True) - self.ui.actionNRB_from_ROI.setEnabled(True) - # self.ui.actionAppend_NRB_from_ROI.setEnabled(True) - self.ui.menuPiece_wise_NRB.setEnabled(True) - - # PREPROCESS - self.ui.actionResidualSubtract.setEnabled(True) - self.ui.actionAnscombe.setEnabled(True) - self.ui.actionInverseAnscombe.setEnabled(True) - self.ui.actionDeNoise.setEnabled(True) - self.ui.actionAmpErrorCorrection.setEnabled(True) - self.ui.actionSubtractROI.setEnabled(True) - self.ui.actionNRB_from_ROI.setEnabled(True) - self.ui.menuVariance_Stabilize.setEnabled(True) - - # ANALYSIS - - - is_complex = _np.iscomplexobj(self.hsi.data) - if is_complex: - self.ui.actionPhaseErrorCorrection.setEnabled(True) - self.ui.actionScaleErrorCorrection.setEnabled(True) - else: - self.ui.actionLoadDark.setEnabled(False) - self.ui.actionLoadNRB.setEnabled(False) - self.ui.actionZeroFirstColumn.setEnabled(False) - self.ui.actionZeroFirstRow.setEnabled(False) - self.ui.actionZeroLastColumn.setEnabled(False) - self.ui.actionZeroLastRow.setEnabled(False) - - # Backup for Undo - self.bcpre.add_step(['Raw']) - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - - # Set frequency slider and associated displays - self.ui.freqSlider.setMinimum(self.hsi.freq.op_range_pix[0]) - self.ui.freqSlider.setMaximum(self.hsi.freq.op_range_pix[-1]) - self.ui.freqSlider.setSliderPosition(self.hsi.freq.op_range_pix[0]) - pos = self.ui.freqSlider.sliderPosition() - self.ui.lineEditPix.setText(str(self.ui.freqSlider.sliderPosition())) - self.ui.lineEditFreq.setText(str(round(self.hsi.f[0], 2))) - # Set BW Class Data - self.img_BW.initData() - self.img_BW.data.grayscaleimage = self.hsi.data_imag_over_real[:, :, pos] - - val_extrema = _np.max([_np.abs(self.hsi.data_imag_over_real.max()), - _np.abs(self.hsi.data_imag_over_real.min())]) - self.img_BW.ui.spinBoxMin.setMinimum(-1.1*val_extrema) - self.img_BW.ui.spinBoxMin.setMaximum(1.1*val_extrema) - self.img_BW.ui.spinBoxMax.setMinimum(-1.1*val_extrema) - self.img_BW.ui.spinBoxMax.setMaximum(1.1*val_extrema) - - xlabel = '' - if isinstance(self.hsi.x_rep.label, str): - xlabel += self.hsi.x_rep.label.strip() - if isinstance(self.hsi.x_rep.units, str): - xlabel += ' (' - xlabel += self.hsi.x_rep.units.strip() - xlabel += ')' - - # print('Xlabel: {}'.format(xlabel)) - ylabel = '' - if isinstance(self.hsi.y_rep.label, str): - ylabel += self.hsi.y_rep.label.strip() - if isinstance(self.hsi.y_rep.units, str): - ylabel += ' (' - ylabel += self.hsi.y_rep.units.strip() - ylabel += ')' - # xlabel = r'{} ({})'.format(self.hsi.x_rep.label.strip(), self.hsi.x_rep.units.strip()) - # ylabel = r'{} ({})'.format(self.hsi.y_rep.label.strip(), self.hsi.y_rep.units.strip()) - - # print('Ylabel: {}'.format(ylabel)) - self.img_BW.data.set_x(self.hsi.x, xlabel) - self.img_BW.data.set_y(self.hsi.y, ylabel) - # Set min/max, fixed, compress, etc buttons to defaults - self.img_BW.ui.checkBoxFixed.setChecked(False) - # self.img_BW.ui.checkBoxCompress.setChecked(False) - self.img_BW.ui.comboBoxAboveMax.setCurrentIndex(0) - self.img_BW.ui.checkBoxRemOutliers.setChecked(False) - self.createImgBW(self.img_BW.data.image) - self.img_BW.mpl.draw() - # RGB images - temp = 0*self.img_BW.data.grayscaleimage - - # Re-initialize RGB images - - for num, rgb_img in enumerate(self.img_RGB_list): - rgb_img.initData() - rgb_img.math.clear() - rgb_img.data.grayscaleimage = temp - rgb_img.data.set_x(self.hsi.x, xlabel) - rgb_img.data.set_y(self.hsi.y, ylabel) - - color_str = rgb_img.colormode.ui.comboBoxFGColor.itemText(num) - rgb_img.data.colormap = _mpl.colors.colorConverter.to_rgb(_mpl.colors.cnames[color_str]) - rgb_img.colormode.ui.comboBoxFGColor.setCurrentIndex(num) - - # Cute way of setting the colormap to last setting and replotting - rgb_img.changeColor() - - # Enable Math - # rgb_img.math.ui.pushButtonDoMath.setEnabled(True) - rgb_img.math.ui.pushButtonBasicMath.setEnabled(True) - - # Enable mean spectrum from RGB images - # Note: if load new file after one has already loaded, need to disconnect - # signal then reconnect (or could have ignored, but this is easier) - try: - rgb_img.popimage.ui.pushButtonSpectrum.pressed.disconnect() - except: - pass - - rgb_img.popimage.ui.pushButtonSpectrum.pressed.connect(self.spectrumColorImg) - - rgb_img.popimage.ui.pushButtonSpectrum.setEnabled(True) - - rgb_img.gsinfo.ui.spinBoxMin.setMinimum(-1.1*val_extrema) - rgb_img.gsinfo.ui.spinBoxMin.setMaximum(1.1*val_extrema) - rgb_img.gsinfo.ui.spinBoxMax.setMinimum(-1.1*val_extrema) - rgb_img.gsinfo.ui.spinBoxMax.setMaximum(1.1*val_extrema) - - # Set X- and Y- scales, labels, etc for composite color images - self.img_Composite.data.set_x(self.hsi.x, xlabel) - self.img_Composite.data.set_y(self.hsi.y, ylabel) - self.img_Composite2.data.set_x(self.hsi.x, xlabel) - self.img_Composite2.data.set_y(self.hsi.y, ylabel)
- -
[docs] def loadDark(self): - """ - Open HDF file and load dark spectrum(a) - """ - - to_open = SubUiHDFLoad.getFileDataSets(self.path) - print('To_open: {}'.format(to_open)) - - if to_open is not None: - pth, filename, datasets = to_open - success = io_nist(pth, filename, datasets, self.dark) - - if success: - if self.dark.shape[-1] == self.hsi.freq.size: - self.ui.actionDarkSubtract.setEnabled(True) - self.ui.actionDarkSpectrum.setEnabled(True) - self.ui.actionDeNoiseDark.setEnabled(True) - else: - self.dark = Spectra() - print('Dark was the wrong shape') - else: - self.dark = Spectra() - self.ui.actionDarkSubtract.setEnabled(False) - self.ui.actionDarkSpectrum.setEnabled(False) - self.ui.actionDeNoiseDark.setEnabled(False)
- - -
[docs] def loadDarkDLM(self): - """ - Open DLM file and load dark spectrum(a) - """ - - - filename,_ = _QFileDialog.getOpenFileName(self, 'Open Dark File', - self.path, - 'All Files (*.*)') - if filename != '': - filename = filename.split(_os.path.dirname(filename))[1][1::] - - - # Spectra first - self.dark = Spectra() - success = io_nist_dlm(self.path, self.filename_header, filename, - self.dark) - if not success: # Maybe Spectrum - self.dark = Spectrum() - success = io_nist_dlm(self.path, self.filename_header, filename, - self.dark) - - - if success: - if self.dark.shape[-1] == self.hsi.freq.size: - self.ui.actionDarkSubtract.setEnabled(True) - self.ui.actionDarkSpectrum.setEnabled(True) - else: - self.dark = Spectra() - print('Dark was the wrong shape') - else: - self.dark = Spectra() - self.ui.actionDarkSubtract.setEnabled(False) - self.ui.actionDarkSpectrum.setEnabled(False)
- - -
[docs] def loadNRB(self): - """ - Open HDF file and load NRB spectrum(a) - """ - - sender = self.sender() - - if sender == self.ui.actionLoadNRB: - nrb = self.nrb - elif sender == self.ui.actionLoad_NRB_Left_Side: - nrb = self.nrb_left - elif sender == self.ui.actionLoad_NRB_Right_Side: - nrb = self.nrb_right - - - to_open = SubUiHDFLoad.getFileDataSets(self.path) - if to_open is not None: - pth, filename, datasets = to_open - - success = io_nist(pth, filename, datasets, nrb) - if success: - if nrb.shape[-1] == self.hsi.freq.size: - if sender == self.ui.actionLoadNRB: - self.ui.menuCoherent_Raman_Imaging.setEnabled(True) - self.ui.actionKramersKronig.setEnabled(True) - self.ui.actionKKSpeedTest.setEnabled(True) - self.ui.actionNRBSpectrum.setEnabled(True) - self.ui.actionDeNoiseNRB.setEnabled(True) - elif sender == self.ui.actionLoad_NRB_Left_Side: - self.ui.actionLeftSideNRBSpect.setEnabled(True) - if ((self.nrb_left.data is not None) and - (self.nrb_right.data is not None)): - if self.nrb_right.mean().size == self.nrb_left.mean().size: - self.ui.actionMergeNRBs.setEnabled(True) - elif sender == self.ui.actionLoad_NRB_Right_Side: - self.ui.actionRightSideNRBSpect.setEnabled(True) - if ((self.nrb_left.data is not None) and - (self.nrb_right.data is not None)): - if self.nrb_right.mean().size == self.nrb_left.mean().size: - self.ui.actionMergeNRBs.setEnabled(True) - else: - nrb = Spectra() - print('NRB was the wrong shape') - else: - nrb = Spectra() - if sender == self.ui.actionLoadNRB: - self.ui.actionKramersKronig.setEnabled(False) - self.ui.actionKKSpeedTest.setEnabled(False) - self.ui.actionNRBSpectrum.setEnabled(False)
- -
[docs] def loadNRBDLM(self): - """ - Open DLM file and load NRB spectrum(a) - """ - - - filename, _ = _QFileDialog.getOpenFileName(self, 'Open NRB File', - self.path, - 'All Files (*.*)') - if filename != '': - filename = filename.split(_os.path.dirname(filename))[1][1::] - - - # Spectra first - self.nrb = Spectra() - success = io_nist_dlm(self.path, self.filename_header, filename, - self.nrb) - if not success: # Maybe Spectrum - self.nrb = Spectrum() - success = io_nist_dlm(self.path, self.filename_header, filename, - self.nrb) - print('Success: {}'.format(success)) - - if success: - if self.dark.shape[-1] == self.hsi.freq.size: - self.ui.actionKramersKronig.setEnabled(True) - self.ui.actionKKSpeedTest.setEnabled(True) - self.ui.actionNRBSpectrum.setEnabled(True) - self.ui.actionDeNoiseNRB.setEnabled(True) - else: - self.nrb = Spectra() - print('NRB was the wrong shape') - else: - self.nrb = Spectra() - self.ui.actionKramersKronig.setEnabled(False) - self.ui.actionKKSpeedTest.setEnabled(False) - self.ui.actionNRBSpectrum.setEnabled(False) - self.ui.actionDeNoiseNRB.setEnabled(False)
- -
[docs] def mergeNRBs(self): - """ - Interactive merge of the left- and right-side NRB - """ - if self.nrb_left is not None and self.nrb_right is not None: - rng = self.hsi.freq.op_range_pix - - - rand_spectra = self.hsi.get_rand_spectra(2, pt_sz=3, quads=True) - - plugin = _widgetMergeNRBs(wn_vec=self.hsi.f, - nrb_left=self.nrb_left.mean()[rng], - nrb_right=self.nrb_right.mean()[rng]) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(data=rand_spectra, - x=self.hsi.f, - plugin=plugin) - - if winPlotEffect is not None: - print('NRB merge pixel: {}'.format(winPlotEffect.parameters['pix_switchpt'])) - print('NRB merge WN: {}'.format(winPlotEffect.parameters['wn_switchpt'])) - print('NRB merge scale left side: {}'.format(winPlotEffect.parameters['scale_left'])) - - self.nrb.data = _np.squeeze(0*self.nrb_left.mean()) - print('nrb shape: {}'.format(self.nrb.shape)) - - inst_nrb_merge = _MergeNRBs(nrb_left=self.nrb_left.mean()[rng], - nrb_right=self.nrb_right.mean()[rng], - pix=winPlotEffect.parameters['pix_switchpt'], - left_side_scale=winPlotEffect.parameters['scale_left']) - nrb_merge = inst_nrb_merge.calculate() - - # Need 2D because of class Spectra NOT Spectrum - self.nrb.data[:, self.hsi.freq.op_range_pix] = nrb_merge - - self.ui.actionNRBSpectrum.setEnabled(True) - self.ui.actionKramersKronig.setEnabled(True) - self.ui.actionKKSpeedTest.setEnabled(True) - self.ui.menuCoherent_Raman_Imaging.setEnabled(True) - self.ui.actionDeNoiseNRB.setEnabled(True) - - wn, pix = find_nearest(self.hsi.f_full, \ - self.hsi.f[winPlotEffect.parameters['pix_switchpt']]) - - # Backup for Undo - self.bcpre.add_step(['MergeNRBs', - 'pix_switchpt', pix, - 'wn_switchpt', - winPlotEffect.parameters['wn_switchpt'], - 'scale_left', - winPlotEffect.parameters['scale_left']]) - - else: - pass
- -
[docs] def settings(self): - """ - Go to settings tab - """ - index = self.ui.tabMain.indexOf(self.ui.tabSettings) - self.ui.tabMain.setCurrentIndex(index)
- -
[docs] def calibrate(self): - """ - Calibrate spectra - """ - - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, full=True) - if _np.iscomplexobj(rand_spectra): - rand_spectra = rand_spectra.imag - - plugin = _widgetCalibrate(calib_dict=self.hsi.freq.calib) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, - x=self.hsi.f_full, - plugin=plugin, - parent=self) - - if winPlotEffect is not None: - #print('New Calibration Dictionary: {}'.format(winPlotEffect.new_calib_dict)) - self.hsi.freq.calib = winPlotEffect.parameters['new_calib_dict'] - self.hsi.freq.update() - self.changeSlider()
- - -
[docs] def calibrationReset(self): - """ - Set self.hsi.freqcalib back to self.hsi.freqcaliborig - """ - self.hsi.freq.calib = None - self.hsi.freq.update() - self.changeSlider()
- -
[docs] def plotDarkSpectrum(self): - """ - Plot dark spectrum - """ - if self.dark.data is None: - pass - else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.dark.data), - label='Mean Dark Spectrum') - - self.plotter.show() - self.plotter.raise_()
- -
[docs] def plotNRBSpectrum(self): - """ - Plot NRB spectrum - """ - if self.nrb.data is None: - pass - else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb.data), - label='Mean NRB Spectrum') - - self.plotter.show() - self.plotter.raise_()
- -
[docs] def plotLeftNRBSpectrum(self): - """ - Plot Left-Side NRB spectrum - """ - if self.nrb_left.data is None: - pass - else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb_left.data), - label='Mean Left-Side NRB Spectrum') - - self.plotter.show() - self.plotter.raise_()
- -
[docs] def plotRightNRBSpectrum(self): - """ - Plot NRB spectrum - """ - if self.nrb_right.data is None: - pass - else: - self.plotter.plot(self.hsi.f_full, mean_nd_to_1d(self.nrb_right.data), - label='Mean Right-Side NRB Spectrum') - - self.plotter.show() - self.plotter.raise_()
- -
[docs] def pointSpectrum(self): - """ - Get spectrum of selected point. - - Note: This function just sets up the signal-slot connection for the \ - MPL window. It executes all the way through - - Action: - Left mouse-click : Select vertex point - """ - if self.cid is None: - self.cid = self.img_BW.mpl.mpl_connect('button_press_event', - lambda event: self._pointClick(event, self._pointSpectrumPlot)) - - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) - self.setCursor(_QCursor(_QtCore.Qt.CrossCursor))
- -
[docs] def subtractROIStart(self): - """ - Acquire an average spectrum from a user-selected ROI and subtract. - - Note: This function just sets up the signal-slot connection for the \ - MPL window. It executes all the way through - - """ - - if self.cid is None: - # Updated by _roiClick - self.x_loc_list = [] - self.y_loc_list = [] - - - self.cid = self.img_BW.mpl.mpl_connect('button_press_event', - lambda event: self._roiClick(event, self._roiSubtract)) - - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) - self.setCursor(_QCursor(_QtCore.Qt.CrossCursor))
- -
[docs] def _roiSubtract(self, locs): - """ - Acquire an average spectrum from a user-selected ROI and subtract. - - """ - x_loc_list, y_loc_list = locs - - x_pix = find_nearest(self.hsi.x, x_loc_list)[1] - y_pix = find_nearest(self.hsi.y, y_loc_list)[1] - - mask, path = _roimask(self.hsi.x, self.hsi.y, - x_loc_list, y_loc_list) - - - mask_hits = _np.sum(mask) - - - if mask_hits > 0: # Len(mask) > 0 - - spectra = self.hsi.data[mask == 1] - - if mask_hits > 1: - spectrum = _np.mean(spectra, axis=0) - else: - spectrum = spectra - spectrum = spectrum.astype(self.hsi.data.dtype) - self.hsi.data -= spectrum[..., :] - self.changeSlider() - - - # Backup for Undo - self.bcpre.add_step(['SubtractROI', 'Spectrum', spectrum]) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - - - del spectrum - - del x_pix - del y_pix
- -
[docs] def nrbFromROI(self): - """ - Acquire an average spectrum from a user-selected ROI and apply to the \ - NRB-- either as the new NRB or averaged with the existing (sender- \ - dependent) - - Note: This function just sets up the signal-slot connection for the \ - MPL window. It executes all the way through - - """ - - # I found that the objectName is a better way than a reference to the - # actual action (e.g., self.ui.action_*) as the reference may change - # depending on the call location or how this method is called - sender = self.sender().objectName() - - if ((sender == 'actionNRB_from_ROI') or - (sender == 'actionAppend_NRB_from_ROI') or - (sender == 'actionNRB_from_ROI_Left_Side') or - (sender == 'actionNRB_from_ROI_Right_Side')): - # Updated by _roiClick - self.x_loc_list = [] - self.y_loc_list = [] - - # Need to send sender as the text name as the actual object - # will change - if self.cid is None: - self.cid = self.img_BW.mpl.mpl_connect('button_press_event', - lambda event: self._roiClick(event, self._roiNRB, sender)) - - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) - self.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) - - else: - print('Unknown action send to nrbFromROI')
- -
[docs] def _roiNRB(self, locs, sender): - """ - Acquire an average spectrum from a user-selected ROI and subtract. - - """ - # Sender was sent as a text reference to the actual sender - # the pass of sender put it in a tuple; thus the [0] - sender = sender[0] - - x_loc_list, y_loc_list = locs - - x_pix = find_nearest(self.hsi.x, x_loc_list)[1] - y_pix = find_nearest(self.hsi.y, y_loc_list)[1] - - mask, path = _roimask(self.hsi.x, self.hsi.y, - x_loc_list, y_loc_list) - - - mask_hits = _np.sum(mask) - if mask_hits > 0: # Len(mask) > 0 - spectra = self.hsi.data_imag_over_real[mask == 1] - - if mask_hits > 1: - spectrum = _np.mean(spectra, axis=0) - else: - spectrum = spectra - - spectrum = spectrum.astype(self.hsi.data.dtype) - if sender == 'actionNRB_from_ROI': - self.nrb.data = spectrum - self.ui.actionKramersKronig.setEnabled(True) - self.ui.actionKKSpeedTest.setEnabled(True) - self.ui.actionNRBSpectrum.setEnabled(True) - self.ui.menuCoherent_Raman_Imaging.setEnabled(True) - - elif sender == 'actionAppend_NRB_from_ROI': - if self.nrb.size == 0: - self.nrb.data = spectrum - else: - self.nrb.data = (self.nrb.data + spectrum)/2 - self.ui.actionKramersKronig.setEnabled(True) - self.ui.actionNRBSpectrum.setEnabled(True) - elif sender == 'actionNRB_from_ROI_Left_Side': - self.nrb_left.data = spectrum - self.ui.actionLeftSideNRBSpect.setEnabled(True) - if ((self.nrb_left.data is not None) and - (self.nrb_right.data is not None)): - if self.nrb_right.mean().size == self.nrb_left.mean().size: - self.ui.actionMergeNRBs.setEnabled(True) - - elif sender == 'actionNRB_from_ROI_Right_Side': - self.nrb_right.data = spectrum - self.ui.actionRightSideNRBSpect.setEnabled(True) - if ((self.nrb_left.data is not None) and - (self.nrb_right.data is not None)): - if self.nrb_right.mean().size == self.nrb_left.mean().size: - self.ui.actionMergeNRBs.setEnabled(True) - else: - print('Unknown action sent to _roiNRB') - - del spectrum - - del x_pix - del y_pix
- -
[docs] def roiSpectrum(self): - """ - Plot spectrum over selected region-of-interest (ROI). - - Note: This function just sets up the signal-slot connection for the \ - MPL window. It executes all the way through - - Action: - Left mouse-click : Select vertex point - Right mouse-click : Close polygon - """ - if self.cid is None: - # Updated by _roiClick - self.x_loc_list = [] - self.y_loc_list = [] - - - self.cid = self.img_BW.mpl.mpl_connect('button_press_event', - lambda event: self._roiClick(event, self._roiSpectrumPlot)) - - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.CrossCursor)) - self.setCursor(_QCursor(_QtCore.Qt.CrossCursor))
- -
[docs] def _pointClick(self, event, pass_fcn): - """ - Capture single mouse click location in MPL window. - - After this function completes, it sends the data (x_pt, y_pt) on to \ - the pass_fcn function. - """ - if event.button == 1: - if event.inaxes == self.img_BW.mpl.ax: - #self.tempverts += [[event.xdata, event.ydata]] - x_loc = event.xdata - y_loc = event.ydata - - # Send on to a function that will use the collected data - pass_fcn((x_loc, y_loc)) - - self.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) - self.img_BW.mpl.mpl_disconnect(self.cid) - self.cid = None - else: # Clicked out-of-bounds - pass - - else: # Right-or-middle clicked; thus, cancel - self.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) - self.img_BW.mpl.mpl_disconnect(self.cid) - self.cid = None
- -
[docs] def _pointSpectrumPlot(self, locs): - """ - Add a plot (in plotter) of a point spectrum - """ - - x_loc, y_loc = locs - x_pix = find_nearest(self.hsi.x, x_loc)[1] - y_pix = find_nearest(self.hsi.y, y_loc)[1] - - self.changeSlider() - - plot_num = self.plotter.n_lines - label = 'Point ' + str(plot_num) - - rng = self.hsi.freq.op_range_pix - - meta = {'x': x_loc, 'y': y_loc, 'x_pix': x_pix, 'y_pix': y_pix, - 'overlay': True} - - self.plotter.plot(self.hsi.f, - self.hsi.data_imag_over_real[y_pix, x_pix, rng], - label=label, meta=meta) - - - self.plotter.show() - self.plotter.raise_() - self.updateOverlays()
- -
[docs] def _roiSpectrumPlot(self, locs): - """ - Add a plot (in plotter) of the mean spectrum over a region - """ - x_loc_list, y_loc_list = locs - - x_pix = find_nearest(self.hsi.x, x_loc_list)[1] - y_pix = find_nearest(self.hsi.y, y_loc_list)[1] - - - mask, path = _roimask(self.hsi.x, self.hsi.y, - x_loc_list, y_loc_list) - - - mask_hits = _np.sum(mask) - if mask_hits > 0: # Len(mask) > 0 - rng = self.hsi.freq.op_range_pix - - spectra = self.hsi.data_imag_over_real[mask == 1] - - if mask_hits > 1: - spectrum = _np.mean(spectra[..., rng], axis=0) - stddev = _np.std(spectra[..., rng], axis=0) - else: - spectrum = spectra[..., rng] - - plot_num = self.plotter.n_lines - - label_plot = 'ROI {} ({})'.format(plot_num, mask_hits) - label_std = r'$\pm$1 Std. Dev. ROI {} ({})'.format(plot_num, mask_hits) - - # Plot line - meta = {'x': x_loc_list, 'y': y_loc_list, 'x_pix': x_pix, - 'y_pix': y_pix, 'overlay': True} - self.plotter.plot(self.hsi.f, spectrum, label=label_plot, meta=meta) - - # Check color of line b/c uses color cycler-- for fill_b/w - color = self.plotter.list_all[-1].style_dict['color'] - - - # Alternative - #color = self.plotter.modelLine._model_data[-1]['color'] - - # Plot +-1 std. dev. - if mask_hits > 1: - self.plotter.fill_between(self.hsi.f, spectrum-stddev, - spectrum+stddev, color=color, - alpha=0.25, - label=label_std, - meta=meta) - - del spectrum - self.plotter.show() - self.plotter.raise_() - self.updateOverlays() - - - del x_pix - del y_pix
- -
[docs] def _roiClick(self, event, pass_fcn, *args): - """ - Capture region-of-interest mouse click locations in MPL window. - """ - - - if event.button == 1: - if event.inaxes == self.img_BW.mpl.ax: - - self.x_loc_list.append(event.xdata) - self.y_loc_list.append(event.ydata) - - getx = self.img_BW.mpl.ax.get_xlim() - gety = self.img_BW.mpl.ax.get_ylim() - - if len(self.x_loc_list) == 1: - self.img_BW.mpl.ax.plot(self.x_loc_list, self.y_loc_list, - markerfacecolor=[.9, .9, 0], - markeredgecolor=[.9, .9, 0], - marker='+', - markersize=10, - linestyle='None') - self.img_BW.mpl.ax.set_xlim(getx) - self.img_BW.mpl.ax.set_ylim(gety) - self.img_BW.mpl.draw() - else: - self.img_BW.mpl.ax.plot(self.x_loc_list[-2:], - self.y_loc_list[-2:], - linewidth=2, - marker='+', - markersize=10, - color=[.9, .9, 0], - markerfacecolor=[.9, .9, 0], - markeredgecolor=[.9, .9, 0]) - self.img_BW.mpl.ax.set_xlim(getx) - self.img_BW.mpl.ax.set_ylim(gety) - - self.img_BW.mpl.draw() - else: - if len(self.x_loc_list) > 0: # Insure at least 1 vertex - self.x_loc_list.append(self.x_loc_list[0]) - self.y_loc_list.append(self.y_loc_list[0]) - - # Pass on roi data - if not args: - pass_fcn((self.x_loc_list, self.y_loc_list)) - else: - pass_fcn((self.x_loc_list, self.y_loc_list), args) - - del self.x_loc_list - del self.y_loc_list - - self.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) - self.img_BW.mpl.setCursor(_QCursor(_QtCore.Qt.ArrowCursor)) - self.img_BW.mpl.mpl_disconnect(self.cid) - self.cid = None - self.changeSlider()
- - -
[docs] def freqWindow(self): - """ - Limit the frequency window displayed and analyzed - """ - text, ok = _QInputDialog.getText(None, 'Frequency Window', - 'Range Tuple (cm-1): ', - text='(500, 3400)') - if ok: - text_str_list = text.strip('(').strip(')').strip().split(',') - freqwin = [float(q) for q in text_str_list] - freqwin.sort() - self.hsi.freq.op_list_freq = freqwin - self.ui.freqSlider.setMinimum(0) - self.ui.freqSlider.setMaximum(self.hsi.freq.op_size-1) - self.changeSlider()
- - -
[docs] def lineEditFreqChanged(self): - """ - Frequency manually entered in frequency-slider-display - """ - - try: - freq_in = float(self.ui.lineEditFreq.text()) - pos = self.hsi.freq.get_index_of_closest_freq(freq_in) - if self.hsi.freq.op_list_pix is not None: - pos -= self.hsi.freq.op_list_pix[0] - - self.ui.freqSlider.setSliderPosition(pos) - self.changeSlider() - except: - pass
- -
[docs] def lineEditPixChanged(self): - """ - Frequency in pixel units manually entered in frequency-slider-display - """ - pos = int(self.ui.lineEditPix.text()) - - self.ui.freqSlider.setSliderPosition(pos) - self.changeSlider()
- -
[docs] def zeroFirstColumn(self): - """ - Zero first non-all-zero column. (Rather than crop) - - """ - self.zc = _ZeroColumn(first_or_last=0) - self.zc.transform(self.hsi.data) - - # Adjust mask - self.hsi._mask[:, self.zc.zero_col] *= 0 - - self.changeSlider()
- -
[docs] def zeroFirstRow(self): - """ - Zero first non-all-zero row. (Rather than crop) - - """ - self.zr = _ZeroRow(first_or_last=0) - self.zr.transform(self.hsi.data) - - # Adjust mask - self.hsi._mask[self.zr.zero_row, :] *= 0 - - self.changeSlider()
- -
[docs] def zeroLastColumn(self): - """ - Zero first non-all-zero column. (Rather than crop) - - """ - self.zc = _ZeroColumn(first_or_last=-1) - self.zc.transform(self.hsi.data) - - # Adjust mask - self.hsi._mask[:, self.zc.zero_col] *= 0 - - self.changeSlider()
- -
[docs] def zeroLastRow(self): - """ - Zero first non-all-zero row. (Rather than crop) - - """ - self.zr = _ZeroRow(first_or_last=-1) - self.zr.transform(self.hsi.data) - - # Adjust mask - self.hsi._mask[self.zr.zero_row, :] *= 0 - - self.changeSlider()
- -
[docs] def opChange(self): - """ - Math operation performed on single-color images changed. - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentop = self.img_RGB_list[rgbnum].math.ui.comboBoxOperations.currentText() - self.img_RGB_list[rgbnum].data.operation = currentop - except: - pass
- -
[docs] def condOpChange(self): - """ - Conditional math operation performed on single-color images changed. - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentop = self.img_RGB_list[rgbnum].math.ui.comboBoxCondOps.currentText() - self.img_RGB_list[rgbnum].data.condoperation = currentop - except: - pass
- -
[docs] def condInEqualityChange(self): - """ - Conditional inequality changed. - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentop = self.img_RGB_list[rgbnum].math.ui.comboBoxCondInEquality.currentText() - self.img_RGB_list[rgbnum].data.inequality = currentop - except: - pass
- -
[docs] def spinBoxInEqualityChange(self): - """ - Conditional inequality value changed. - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - self.img_RGB_list[rgbnum].data.inequalityval = \ - self.img_RGB_list[rgbnum].math.ui.spinBoxInEquality.value() - except: - pass
- -
[docs] def doKK(self): - """ - Pop-up Kramers-Kronig parameter entry dialog and perform - the Kramers-Kronig phase retrieval algorithm. - """ - - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - nrb = self.nrb.mean() - - # Range of pixels to perform-over - rng = self.hsi.freq.op_range_pix - - out = DialogKKOptions.dialogKKOptions(data=[self.hsi.f, - nrb[..., rng], - rand_spectra], parent=self) - - if out is not None: - cars_amp_offset = out['cars_amp'] - nrb_amp_offset = out['nrb_amp'] - phase_offset = out['phase_offset'] - norm_to_nrb = out['norm_to_nrb'] - pad_factor = out['pad_factor'] - - kk = KramersKronig(cars_amp_offset=cars_amp_offset, - nrb_amp_offset=nrb_amp_offset, - phase_offset=phase_offset, norm_to_nrb=norm_to_nrb, - pad_factor=pad_factor, - rng=rng) - - self.hsi.data = kk.calculate(self.hsi.data, self.nrb.data) - self.changeSlider() - - self.ui.actionPhaseErrorCorrection.setEnabled(True) - self.ui.actionScaleErrorCorrection.setEnabled(True) - - # Backup for Undo - self.bcpre.add_step(['KK', 'CARSAmp', cars_amp_offset, 'NRBAmp', - nrb_amp_offset, 'Phase', phase_offset, - 'Norm', norm_to_nrb]) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up()
- -
[docs] def deNoiseNRB(self): - """ - Denoise NRB with Savitky-Golay - """ - # Range of pixels to perform-over - rng = self.hsi.freq.op_range_pix - - plugin = _widgetSG(window_length=11, polyorder=3) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(self.nrb.mean()[rng], - x=self.hsi.f, - plugin=plugin, - parent=self) - if winPlotEffect is not None: - win_size = winPlotEffect.parameters['window_length'] - order = winPlotEffect.parameters['polyorder'] - - nrb_denoise = _copy.deepcopy(_np.squeeze(self.nrb.data)) - nrb_denoise[..., rng] = _sg(nrb_denoise[..., rng], win_size, order) - - self.nrb.data = nrb_denoise - - # Backup for Undo - self.bcpre.add_step(['DenoiseNrbSG', - 'Win_size', win_size, - 'Order', order]) - - self.changeSlider()
- -
[docs] def deNoiseDark(self): - """ - Denoise Dark with Savitky-Golay - """ - # Range of pixels to perform-over - rng = self.hsi.freq.op_range_pix - - plugin = _widgetSG(window_length=201, polyorder=3) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(self.dark.mean()[rng], - x=self.hsi.f, - plugin=plugin, - parent=self) - if winPlotEffect is not None: - win_size = winPlotEffect.parameters['window_length'] - order = winPlotEffect.parameters['polyorder'] - - dark_denoise = _copy.deepcopy(_np.squeeze(self.dark.data)) - dark_denoise[..., rng] = _sg(dark_denoise[..., rng], win_size, order) - - self.dark.data = dark_denoise - - # Backup for Undo - self.bcpre.add_step(['DenoiseDarkSG', - 'Win_size', win_size, - 'Order', order]) - - - self.changeSlider()
- -
[docs] def deNoise(self): - """ - SVD - """ - # Range of pixels to perform-over - rng = self.hsi.freq.op_range_pix - # SVD Decompose - svd_decompose = SVDDecompose(rng=rng) - UsVh = svd_decompose.calculate(self.hsi.data) - - # Class method route - if rng is None: - # Note: .main in dialog_AbstractFactorization - svs = DialogSVD.dialogSVD(UsVh, self.hsi.data.shape, mask=self.hsi.mask, - img_all=self.hsi.data.mean(axis=-1), - spect_all=self.hsi.data.mean(axis=(0,1)), - parent=self) - else: - svs = DialogSVD.dialogSVD(UsVh, self.hsi.data[..., rng].shape, - mask=self.hsi.mask, - img_all=self.hsi.data[..., rng].mean(axis=-1), - spect_all=self.hsi.data[..., rng].mean(axis=(0,1)), - parent=self) - - print('SV\'s:{}'.format(svs)) - - if svs is not None: - svd_recompose = SVDRecompose(rng=rng) - svd_recompose.transform(self.hsi.data, UsVh[0], UsVh[1], UsVh[2], - svs=svs) - - # Backup for Undo - self.bcpre.add_step(['SVD', 'SVs', svs]) - - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - self.changeSlider()
- -
[docs] def errorCorrectPhase(self): - """ - Error Correction: Phase - """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - if _np.iscomplexobj(rand_spectra): - rand_spectra = _np.angle(rand_spectra) - - rng = self.hsi.freq.op_range_pix - - plugin = _widgetALS() - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, - x=self.hsi.f, - plugin=plugin, - parent=self) - if winPlotEffect is not None: - asym_param = winPlotEffect.parameters['asym_param'] - smoothness_param = winPlotEffect.parameters['smoothness_param'] - redux_factor = winPlotEffect.parameters['redux'] - fix_end_points = winPlotEffect.parameters['fix_end_points'] - max_iter = winPlotEffect.parameters['max_iter'] - min_diff = winPlotEffect.parameters['min_diff'] - - phase_err_correct_als = _PhaseErrCorrectALS(smoothness_param=smoothness_param, - asym_param=asym_param, - redux=redux_factor, - order=2, - rng=rng, - fix_end_points=fix_end_points, - max_iter=max_iter, - min_diff=min_diff, - verbose=False) - - phase_err_correct_als.transform(self.hsi.data) - - # Backup for Undo - - if _np.size(asym_param) == 1: - self.bcpre.add_step(['PhaseErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param', asym_param, - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - else: - self.bcpre.add_step(['PhaseErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param_start', - winPlotEffect.parameters['asym_param_start'], - 'asym_param_end', - winPlotEffect.parameters['asym_param_end'], - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - - self.changeSlider()
- -
[docs] def errorCorrectScale(self): - """ - Error Correction: Scale - """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - if _np.iscomplexobj(rand_spectra): - rand_spectra = rand_spectra.real - - rng = self.hsi.freq.op_range_pix - - plugin = _widgetSG(window_length=601, polyorder=2) - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, - x=self.hsi.f, - plugin=plugin, - parent=self) - if winPlotEffect is not None: - win_size = winPlotEffect.parameters['window_length'] - order = winPlotEffect.parameters['polyorder'] - - scale_err_correct_sg = _ScaleErrCorrectSG(win_size=win_size, - order=order, - rng=rng) - scale_err_correct_sg.transform(self.hsi.data) - - # Backup for Undo - self.bcpre.add_step(['ScaleErrorCorrectSG', - 'win_size', win_size, - 'order', order]) - - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - self.changeSlider()
- -
[docs] def errorCorrectAmp(self): - """ - Error Correction: Amp aka Baseline Detrending - - Notes - ----- - If data is complex, amplitude detrending occurs on and only on the \ - imaginary portion - """ - rand_spectra = self.hsi.get_rand_spectra(5, pt_sz=3, quads=True, - full=False) - if _np.iscomplexobj(rand_spectra): - rand_spectra = rand_spectra.imag - - rng = self.hsi.freq.op_range_pix - - plugin = _widgetALS() - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(rand_spectra, - x=self.hsi.f, - plugin=plugin, - parent=self) - if winPlotEffect is not None: - asym_param = winPlotEffect.parameters['asym_param'] - smoothness_param = winPlotEffect.parameters['smoothness_param'] - redux_factor = winPlotEffect.parameters['redux'] - fix_end_points = winPlotEffect.parameters['fix_end_points'] - max_iter = winPlotEffect.parameters['max_iter'] - min_diff = winPlotEffect.parameters['min_diff'] - - - baseline_detrend = _SubtractBaselineALS(smoothness_param=smoothness_param, - asym_param=asym_param, - redux=redux_factor, - order=2, - rng=rng, - fix_end_points=fix_end_points, - max_iter=max_iter, - min_diff=min_diff, - verbose=False) - baseline_detrend.transform(self.hsi.data) - - # Backup for Undo - if _np.size(asym_param) == 1: - self.bcpre.add_step(['AmpErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param', asym_param, - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - else: - self.bcpre.add_step(['AmpErrorCorrectALS', - 'smoothness_param', smoothness_param, - 'asym_param_start', - winPlotEffect.parameters['asym_param_start'], - 'asym_param_end', - winPlotEffect.parameters['asym_param_end'], - 'redux', redux_factor, - 'order', 2, - 'fix_end_points', fix_end_points, - 'max_iter', max_iter, - 'min_diff', min_diff]) - - - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - - self.changeSlider()
- -
[docs] def doUndo(self): - """ - Undo last operation back to last backup point - """ - self.bcpre.pop_to_last() - self.hsi = _BCPre.load_pickle(self.bcpre.id_list[-1]) - del_flag = 0 - - for count in self.bcpre.cut_list: - try: - _os.remove(count + '.pickle') - except: - print('Error in deleting old pickle files') - else: - del_flag += 1 - if del_flag == len(self.bcpre.cut_list): - del self.bcpre.cut_list - else: - print('Did not delete pickle file cut list... Something went wrong') - - self.ui.freqSlider.setMinimum(0) - - self.ui.freqSlider.setMaximum(self.hsi.freq.size-1) - - self.changeSlider()
- -
[docs] def subDark(self): - """ - Subtract loaded dark spectrum from HSI data. - """ - - nrbloaded = self.nrb.data is not None - nrbloaded_left = self.nrb_left.data is not None - nrbloaded_right = self.nrb_right.data is not None - darkloaded = self.dark.data is not None - - if self.hsi.data is not None: - if darkloaded: - # Instantiate SubtractDark - sub_dark = SubtractDark(self.dark.data) - - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Dark Spectrum from Image?') - msg.setWindowTitle('Confirm dark subtract from image') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_dark.transform(self.hsi.data) - - if nrbloaded: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Dark Spectrum from NRB Spectrum(a)?') - msg.setWindowTitle('Confirm dark subtract from NRB spectrum(a)') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_dark.transform(self.nrb.data) - - if nrbloaded_left: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Dark Spectrum from Left-Side NRB Spectrum(a)?') - msg.setWindowTitle('Confirm dark subtract from Left-Side NRB spectrum(a)') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_dark.transform(self.nrb_left.data) - - if nrbloaded_right: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Dark Spectrum from Right-Side NRB Spectrum(a)?') - msg.setWindowTitle('Confirm dark subtract from Right-Side NRB spectrum(a)') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_dark.transform(self.nrb_right.data) - - - # Backup for Undo - if darkloaded or nrbloaded: - self.bcpre.add_step(['SubDark']) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - - self.changeSlider() - else: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Information) - msg.setText('Dark spectrum not loaded.') - msg.setStandardButtons(_QMessageBox.Ok) - msg.setDefaultButton(_QMessageBox.Ok) - msg.exec() - else: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Information) - msg.setText('Image data not loaded. Cannot subtract dark spectrum.') - msg.setStandardButtons(_QMessageBox.Ok) - msg.setDefaultButton(_QMessageBox.Ok) - msg.exec()
- -
[docs] def subResidual(self): - """ - Subtract a linear residual over range - """ - nrbloaded = self.nrb.data is not None - nrbloaded_left = self.nrb_left.data is not None - nrbloaded_right = self.nrb_right.data is not None - imgloaded = self.hsi.data is not None - - if nrbloaded or imgloaded: - text, ok = _QInputDialog.getText(None, 'Frequency Window', - 'Range Tuple (cm-1): ', - text='(-1500, -500)') - if ok: - text_str_list = text.strip('(').strip(')').strip().split(',') - freqwin = [float(q) for q in text_str_list] - freqwin.sort() - - rng = self.hsi.freq.get_index_of_closest_freq(freqwin) - sub_residual = SubtractMeanOverRange(rng) - - if imgloaded: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Residual Dark Spectrum from Image?') - msg.setWindowTitle('Confirm residual subtraction from Image') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out_img = msg.exec() - - if out_img == _QMessageBox.Ok: - sub_residual.transform(self.hsi.data) - - if nrbloaded: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Residual Dark Spectrum from NRB?') - msg.setWindowTitle('Confirm residual subtraction from NRB') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_residual.transform(self.nrb.data) - - if nrbloaded_left: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Residual Dark Spectrum from Left-Side NRB?') - msg.setWindowTitle('Confirm residual subtraction from Left-Side NRB') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_residual.transform(self.nrb_left.data) - - if nrbloaded_right: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Question) - msg.setText('Subtract Residual Dark Spectrum from Right-Side NRB?') - msg.setWindowTitle('Confirm residual subtraction from Right-Side NRB') - msg.setStandardButtons(_QMessageBox.Ok | _QMessageBox.Cancel) - msg.setDefaultButton(_QMessageBox.Ok) - out = msg.exec() - - if out == _QMessageBox.Ok: - sub_residual.transform(self.nrb_right.data) - - # Backup for Undo - if out_img == _QMessageBox.Ok: - self.bcpre.add_step(['SubResidual','RangeStart', - freqwin[0], 'RangeEnd', - freqwin[1]]) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - self.changeSlider() - else: - msg = _QMessageBox(self) - msg.setIcon(_QMessageBox.Information) - msg.setText('Image or NRB data need be loaded.') - msg.setStandardButtons(_QMessageBox.Ok) - msg.setDefaultButton(_QMessageBox.Ok) - msg.exec()
- -
[docs] def anscombe(self): - """ - Performance Anscombe transformation - """ - out = DialogAnscombeOptions.dialogAnscombeOptions(parent=self) - - if out is not None: - self._anscombe_params = _copy.deepcopy(out) - - rng = self.hsi.freq.op_range_pix - - ansc = _Anscombe(gauss_std=out['stddev'], gauss_mean=0.0, - poisson_multi=out['gain'], rng=rng) - ansc.transform(self.hsi.data) - - # Backup for Undo - self.bcpre.add_step(['Anscombe','Gauss_mean', 0.0, - 'Gauss_std', out['stddev'], - 'Poisson_multi', out['gain']]) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - self.changeSlider()
- -
[docs] def inverseAnscombe(self): - """ - Performance an Inverse Anscombe transformation - """ - if self._anscombe_params is None: - out = DialogAnscombeOptions.dialogAnscombeOptions(parent=self) - else: - out = DialogAnscombeOptions.dialogAnscombeOptions(stddev=self._anscombe_params['stddev'], - gain=self._anscombe_params['gain'], - parent=self) - - if out is not None: - rng = self.hsi.freq.op_range_pix - - iansc = _AnscombeInverse(gauss_std=out['stddev'], gauss_mean=0.0, - poisson_multi=out['gain'], rng=rng) - iansc.transform(self.hsi.data) - - # Backup for Undo - self.bcpre.add_step(['InvAnscombe','Gauss_mean', 0.0, - 'Gauss_std', out['stddev'], - 'Poisson_multi', out['gain']]) - if self.ui.actionUndo_Backup_Enabled.isChecked(): - try: - _BCPre.backup_pickle(self.hsi, self.bcpre.id_list[-1]) - except: - print('Error in pickle backup (Undo functionality)') - else: - self.bcpre.backed_up() - self.changeSlider()
- -
[docs] def doMath(self): - """ - Perform selected math operation on single-color imagery. - """ - - # Which RGB image is it - rgbnum = self.ui.tabColors.currentIndex() - - # Which operation is selected - operation_index = self.img_RGB_list[rgbnum].math.ui.comboBoxCondOps.currentIndex() - operation_text = self.img_RGB_list[rgbnum].math.ui.comboBoxCondOps.currentText() - - - if operation_index == 0: - num_freq_needed = 0 - else: - # num_freq_needed = widgetColorMath.OPERATION_FREQ_COUNT[operation_index-1] - num_freq_needed = self.img_RGB_list[rgbnum].math.OPERATION_FREQ_COUNT[operation_index-1] - # Check conditional frequencies are set - cond_set = False - - if (num_freq_needed == 1 and - self.img_RGB_list[rgbnum].data.condfreq1 is not None): - - # Conditional frequency LOCATION 1 - condloc1 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.condfreq1) - - # All frequencies set - cond_set = True - elif (num_freq_needed == 2 and - self.img_RGB_list[rgbnum].data.condfreq1 is not None and - self.img_RGB_list[rgbnum].data.condfreq2 is not None): - - # Conditional frequency LOCATIONS - condloc1 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.condfreq1) - condloc2 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.condfreq2) - - # All frequencies set - cond_set = True - elif (num_freq_needed == 3 and - self.img_RGB_list[rgbnum].data.condfreq1 is not None and - self.img_RGB_list[rgbnum].data.condfreq2 is not None and - self.img_RGB_list[rgbnum].data.condfreq3 is not None): - - # Conditional frequency LOCATIONS - condloc1 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.condfreq1) - condloc2 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.condfreq2) - condloc3 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.condfreq3) - - # All frequencies set - cond_set = True - else: - cond_set = False - - if cond_set is False: - self.img_RGB_list[rgbnum].math.ui.comboBoxCondOps.setCurrentIndex(0) - Mask = 1 - else: - if (operation_text == '') or (operation_text == ' '): # Return just a plane - Mask = _peakamps.MeasurePeak.measure(self.hsi.data_imag_over_real, - condloc1) - - - elif operation_text == '+': # Addition - Mask = _peakamps.MeasurePeakAdd.measure(self.hsi.data_imag_over_real, - condloc1, condloc2) - - elif operation_text == '-': # Subtraction - Mask = _peakamps.MeasurePeakMinus.measure(self.hsi.data_imag_over_real, - condloc1, condloc2) - - elif operation_text == '*': # Multiplication - Mask = _peakamps.MeasurePeakMultiply.measure(self.hsi.data_imag_over_real, - condloc1, condloc2) - - elif operation_text == '/': # Division - Mask = _peakamps.MeasurePeakDivide.measure(self.hsi.data_imag_over_real, - condloc1, condloc2) - - elif operation_text == 'SUM': # Summation over range - Mask = _peakamps.MeasurePeakSummation.measure(self.hsi.data_imag_over_real, - condloc1, condloc2) - - elif operation_text == 'Peak b/w troughs': # Peak between troughs - Mask = _peakamps.MeasurePeakBWTroughs.measure(self.hsi.data_imag_over_real, - condloc1, condloc2, condloc3) - else: - pass - - if cond_set is True: - inequality_text = self.img_RGB_list[rgbnum].math.ui.comboBoxCondInEquality.currentText() - inequality_val = self.img_RGB_list[rgbnum].math.ui.spinBoxInEquality.value() - if inequality_text == '<': - Mask = Mask < inequality_val - elif inequality_text == '>': - Mask = Mask > inequality_val - elif inequality_text == '=': - Mask = Mask == inequality_val - elif inequality_text == '>=': - Mask = Mask >= inequality_val - elif inequality_text == '<=': - Mask = Mask <= inequality_val - else: - print('Inequality type error... setting to 1') - Mask = 1 - # Check frequencies are set - operation_index = self.img_RGB_list[rgbnum].math.ui.comboBoxOperations.currentIndex() - operation_text = self.img_RGB_list[rgbnum].math.ui.comboBoxOperations.currentText() - - # num_freq_needed = widgetColorMath.OPERATION_FREQ_COUNT[operation_index] - num_freq_needed = self.img_RGB_list[rgbnum].math.OPERATION_FREQ_COUNT[operation_index] - - freq_set = False - - if (num_freq_needed == 1 and - self.img_RGB_list[rgbnum].data.opfreq1 is not None): - - # Operating frequency LOCATION 1 - oploc1 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.opfreq1) - - # All frequencies set - freq_set = True - elif (num_freq_needed == 2 and - self.img_RGB_list[rgbnum].data.opfreq1 is not None and - self.img_RGB_list[rgbnum].data.opfreq2 is not None): - - # Operating frequency LOCATIONS - oploc1 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.opfreq1) - oploc2 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.opfreq2) - - # All frequencies set - freq_set = True - - elif (num_freq_needed == 3 and - self.img_RGB_list[rgbnum].data.opfreq1 is not None and - self.img_RGB_list[rgbnum].data.opfreq2 is not None and - self.img_RGB_list[rgbnum].data.opfreq3 is not None): - - # Operating frequency LOCATIONS - oploc1 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.opfreq1) - oploc2 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.opfreq2) - oploc3 = self.hsi.freq.get_index_of_closest_freq(self.img_RGB_list[rgbnum].data.opfreq3) - - # All frequencies set - freq_set = True - - else: - freq_set = False - - if freq_set == True: - if (operation_text == '') or (operation_text == ' '): # Return just a plane - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeak.measure(self.hsi.data_imag_over_real, - oploc1) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - elif operation_text == '+': # Addition - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakAdd.measure(self.hsi.data_imag_over_real, - oploc1, oploc2) - - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - elif operation_text == '-': # Subtraction - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakMinus.measure(self.hsi.data_imag_over_real, - oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - elif operation_text == '*': # Multiplication - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakMultiply.measure(self.hsi.data_imag_over_real, - oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - elif operation_text == '/': # Division - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakDivide.measure(self.hsi.data_imag_over_real, - oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - elif operation_text == 'SUM': # Division - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakSummation.measure(self.hsi.data_imag_over_real, - oploc1, oploc2) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - elif operation_text == 'Peak b/w troughs': # Division - self.img_RGB_list[rgbnum].data.grayscaleimage = Mask * \ - _peakamps.MeasurePeakBWTroughs.measure(self.hsi.data_imag_over_real, - oploc1, oploc2, - oploc3) - self.img_RGB_list[rgbnum].changeColor() - #self.updateImgColorMinMax() - else: - pass - else: - pass - self.doComposite()
- -
[docs] def setOpFreq1(self): - """ - Set color math frequency #1 (the primary frequency) - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentfreq = float(self.ui.lineEditFreq.text()) - - self.img_RGB_list[rgbnum].data.opfreq1 = currentfreq - self.img_RGB_list[rgbnum].math.ui.pushButtonOpFreq1.setText(str(round(currentfreq, 1))) - self.img_RGB_list[rgbnum].data.grayscaleimage = self.img_BW.data.grayscaleimage - self.img_RGB_list[rgbnum].changeColor() - - self.img_RGB_list[rgbnum].mpl.draw() - - except: - print('Error') - self.doComposite()
- -
[docs] def setOpFreq2(self): - """ - Set color math frequency #2 (e.g., freq #1 + freq #2) - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentfreq = float(self.ui.lineEditFreq.text()) - - self.img_RGB_list[rgbnum].data.opfreq2 = currentfreq - self.img_RGB_list[rgbnum].math.ui.pushButtonOpFreq2.setText(str(round(currentfreq, 1))) - except: - pass
- -
[docs] def setOpFreq3(self): - """ - Set color math frequency #3 (e.g., Amplitude at freq #1 - interpolation [freq #2, freq #3]) - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentfreq = float(self.ui.lineEditFreq.text()) - - self.img_RGB_list[rgbnum].data.opfreq3 = currentfreq - self.img_RGB_list[rgbnum].math.ui.pushButtonOpFreq3.setText(str(round(currentfreq, 1))) - - except: - pass
- -
[docs] def setCondFreq1(self): - """ - Set color math conditional frequency #1 - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentfreq = float(self.ui.lineEditFreq.text()) - - self.img_RGB_list[rgbnum].data.condfreq1 = currentfreq - self.img_RGB_list[rgbnum].math.ui.pushButtonCondFreq1.setText(str(round(currentfreq, 1))) - - except: - print('Error')
- -
[docs] def setCondFreq2(self): - """ - Set color math conditional frequency #2 - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentfreq = float(self.ui.lineEditFreq.text()) - - self.img_RGB_list[rgbnum].data.condfreq2 = currentfreq - self.img_RGB_list[rgbnum].math.ui.pushButtonCondFreq2.setText(str(round(currentfreq, 1))) - - except: - print('Error')
- -
[docs] def setCondFreq3(self): - """ - Set color math conditional frequency #1 - """ - rgbnum = self.ui.tabColors.currentIndex() - - try: - currentfreq = float(self.ui.lineEditFreq.text()) - - self.img_RGB_list[rgbnum].data.condfreq3 = currentfreq - self.img_RGB_list[rgbnum].math.ui.pushButtonCondFreq3.setText(str(round(currentfreq, 1))) - - except: - print('Error')
- -
[docs] def spectrumColorImg(self): - """ - Generate plot of mean - """ - # Which RGB image is it - rgbnum = self.ui.tabColors.currentIndex() - - Mask = _copy.deepcopy(self.img_RGB_list[rgbnum].data.grayscaleimage) - - if self.img_RGB_list[rgbnum].data.setmin is not None: - Mask *= Mask >= self.img_RGB_list[rgbnum].data.setmin - - if self.img_RGB_list[rgbnum].data.setmax is not None: - Mask *= Mask <= self.img_RGB_list[rgbnum].data.setmax - - if Mask.max() <= 0: - pass - else: - - Mask = Mask > 0 - Mask = Mask.astype(_np.integer) - - mask_hits = Mask.sum() - - - mloc, nloc = _np.where(Mask) - - - if mask_hits > 1: - mean_spect = self.hsi.data_imag_over_real[mloc, nloc, :][:, self.hsi.freq.op_range_pix].mean(axis=0) - std_spect = self.hsi.data_imag_over_real[mloc, nloc, :][:, self.hsi.freq.op_range_pix].std(axis=0) - self.plotter.plot(self.hsi.f, mean_spect, label='Mean spectrum ({})'.format(mask_hits)) - elif mask_hits == 1: - mean_spect = _np.squeeze(self.hsi.data_imag_over_real[mloc,nloc,:])[self.hsi.freq.op_range_pix] - - std_spect = 0 - # Plot spectrum - - self.plotter.plot(self.hsi.f, mean_spect, label='Spectrum ({})'.format(mask_hits)) - - - # Check color of line b/c uses color cycler-- for fill_b/w - color = self.plotter.list_all[-1].style_dict['color'] - - # Alternative - #color = self.plotter.modelLine._model_data[-1]['color'] - - # Plot +-1 std. dev. - if mask_hits > 1: - self.plotter.fill_between(self.hsi.f, mean_spect - std_spect, - mean_spect + std_spect, - color=color, - alpha=0.25, - label=r'$\pm$1 Std. Dev. ({})'.format(mask_hits)) - - - self.plotter.show() - self.plotter.raise_()
- -
[docs] def createImgBW(self, img): - """ - Generate the single-frequency grayscale image - """ - xunits = self.img_BW.data.xunits - yunits = self.img_BW.data.yunits - extent = self.img_BW.data.winextent - - self.img_BW.createImg(img=img, xunits=xunits, - yunits=yunits, - extent=extent, - cmap=self.img_BW.colormode.ui.comboBoxColormap.currentText()) - - if self.img_BW.ui.checkBoxFixed.checkState()==0: - self.img_BW.ui.spinBoxMax.setValue(self.img_BW.data.maxer) - self.img_BW.ui.spinBoxMin.setValue(self.img_BW.data.minner)
- -
[docs] def changeSlider(self): - """ - Respond to change in frequency slider - """ - - # Get current axis limits to reset to these - # after refresh is performed - orig_axis_lims = self.img_BW.mpl.ax.axis() - - pos = self.ui.freqSlider.sliderPosition() - assert isinstance(pos, int), 'Slider position need be an integer' - - if self.hsi.freq.op_list_pix is not None: - offset = self.hsi.freq.op_list_pix[0] - else: - offset = 0 - - self.ui.lineEditPix.setText(str(pos)) - - try: - self.ui.lineEditFreq.setText(str(round(self.hsi.f[pos],2))) - # Set BW Class Data - - self.img_BW.data.grayscaleimage = self.hsi.data_imag_over_real[:, :, pos+offset] - - xlabel = '' - if isinstance(self.hsi.x_rep.label, str): - xlabel += self.hsi.x_rep.label.strip() - if isinstance(self.hsi.x_rep.units, str): - xlabel += ' (' - xlabel += self.hsi.x_rep.units.strip() - xlabel += ')' - - # print('Xlabel: {}'.format(xlabel)) - ylabel = '' - if isinstance(self.hsi.y_rep.label, str): - ylabel += self.hsi.y_rep.label.strip() - if isinstance(self.hsi.y_rep.units, str): - ylabel += ' (' - ylabel += self.hsi.y_rep.units.strip() - ylabel += ')' - - self.img_BW.data.set_x(self.hsi.x, xlabel) - self.img_BW.data.set_y(self.hsi.y, ylabel) - - self.img_BW.checkBoxRemOutliers() - # if self.img_BW.ui.checkBoxFixed.checkState() == 0: - # self.img_BW.data.setmax = None - # self.img_BW.data.setmin = None - - # Set axis to original limits - self.img_BW.mpl.ax.axis(orig_axis_lims) - - if not self._mpl_v2: - self.img_BW.mpl.ax.hold(True) - - except: - print('Error in changeSlider: display img_BW') - - try: - if self.show_overlays: - for ol in self.overlays: - x = ol['meta']['x'] - y = ol['meta']['y'] - - color = ol['color'] - mfc = color # Marker face color - mec = color # Marker edge color - lw = ol['linewidth'] # Linewidth - label = ol['label'] - ls = ol['linestyle'] # Linestyle - ms = ol['markersize'] # Markersize - a = ol['alpha'] - marker = ol['marker'] - - # Need some sort of marker if just a point - if _np.size(x) == 1: - if isinstance(marker, str): - if marker.lower() == 'none': - marker = 'x' - - self.img_BW.mpl.ax.plot(x, y, marker=marker, - mfc=mfc, mec=mec, - color=color, lw=lw, - ls=ls, ms=ms, alpha=a, - label=label) - - if self.ui.actionShowOverlayLegend.isChecked(): - try: - self.img_BW.mpl.ax.legend(loc='best') - except: - pass - except: - print('Error in changeSlider: display overlays') - - self.img_BW.mpl.draw() - - if self.bcpre.backed_flag.count(True) > 1: - self.ui.actionUndo.setEnabled(True) - else: - self.ui.actionUndo.setEnabled(False)
- -
[docs] def sliderPressed(self): - """ - Respond to press of frequency slider (set tracking of location) - """ - self.ui.freqSlider.setTracking(False)
- -
[docs] def sliderReleased(self): - """ - Respond to release of frequency slider (end tracking of location) - """ - self.ui.freqSlider.setTracking(True)
- -
[docs] def checkCompositeUpdate(self,num): - """ - Update color composite only if appropriate tab is selected. - """ - if num == self.ui.tabColors.count()-1: - self.doComposite()
- -
[docs] def doComposite(self): - """ - Update color composite image. - """ - try: - self.img_Composite.initData(self.img_RGB_list) - self.img_Composite.changeMode() # This checks what mode is set - - xlabel = '' - if isinstance(self.hsi.x_rep.label, str): - xlabel += self.hsi.x_rep.label.strip() - if isinstance(self.hsi.x_rep.units, str): - xlabel += ' (' - xlabel += self.hsi.x_rep.units.strip() - xlabel += ')' - - # print('Xlabel: {}'.format(xlabel)) - ylabel = '' - if isinstance(self.hsi.y_rep.label, str): - ylabel += self.hsi.y_rep.label.strip() - if isinstance(self.hsi.y_rep.units, str): - ylabel += ' (' - ylabel += self.hsi.y_rep.units.strip() - ylabel += ')' - - self.img_Composite.data.set_x(self.hsi.x, xlabel) - self.img_Composite.data.set_y(self.hsi.y, ylabel) - - self.img_Composite.createImg(img=self.img_Composite.data.image, - xunits=self.img_Composite.data.xunits, - yunits=self.img_Composite.data.yunits, - extent=self.img_BW.data.winextent) - self.img_Composite.mpl.draw() - - self.img_Composite2.initData(self.img_RGB_list) - self.img_Composite2.changeMode() - - self.img_Composite2.data.set_x(self.hsi.x, xlabel) - self.img_Composite2.data.set_y(self.hsi.y, ylabel) - self.img_Composite2.createImg(img=self.img_Composite2.data.image, - xunits=self.img_Composite2.data.xunits, - yunits=self.img_Composite2.data.yunits, - extent=self.img_BW.data.winextent) - self.img_Composite2.mpl.draw() - except: - print('Error in doComposite')
- -
[docs] def updateOverlays(self): - self.overlays=[] - for ln in self.plotter.list_line_objs: - ms = ln.model_style - - # Make sure there is the appropriate meta data - if ms.get('meta').get('overlay') is not None: - if ms['meta']['overlay'] == True: - self.overlays.append(ms) - self.changeSlider()
- -
[docs] def deleteOverlays(self): - self.updateOverlays()
- -
[docs] def checkShowOverlays(self): - self.show_overlays = self.ui.actionShowOverlays.isChecked() - self.changeSlider()
- -
[docs] def makeRamanPhantom(self): - """ - Generate a numerical phantom for Raman - """ - cplx = False # Is model complex-valued -- False for Raman - - dialog = DialogModel.dialogModel(cplx=cplx, parent=self) - if dialog is not None: - model = _Model(subsample=dialog['subsample']) - - wn_start = dialog['wn_start'] - wn_end = dialog['wn_end'] - - lam_start = 0.01 / (wn_start + 0.01/(dialog['probe']*1e-9)) # meters - lam_start *= 1e9 # nm - - lam_end = 0.01 / (wn_end + 0.01/(dialog['probe']*1e-9)) # meters - lam_end *= 1e9 # nm - - lam_ctr = (lam_start + lam_end) / 2 # nm - - n_pix = _np.ceil((lam_end-lam_start) / dialog['wl_slope']) - - # Make a properly linear frequency-vector and polyfit - f = dialog['wl_slope'] * _np.arange(n_pix) # Temporary frequency vec - f -= f.mean() - f += lam_ctr - - a_vec = _np.polyfit(_np.arange(n_pix), f, 1) - - calib = {'a_vec': a_vec, - 'ctr_wl': lam_ctr, - 'ctr_wl0': lam_ctr, - 'n_pix': n_pix, - 'probe': dialog['probe'], - 'units': 'nm'} - - f = _calib_pix_wn(calib)[0] - model.make_hsi(f=f) - - if cplx: - model.hsi = model.hsi.astype(_np.complex64) - self.hsi = Hsi(data=model.hsi, x=model.x, y=model.y) - else: - model.hsi = 1*model.hsi.imag - model.hsi = model.hsi.astype(_np.float32) - self.hsi = Hsi(data=model.hsi, x=model.x, y=model.y) - - # For Raman -- make the Hsi more intense - # This is ARBITRARY - self.hsi._data *= 50e3 - - self.hsi.freq.calib_fcn = _calib_pix_wn - self.hsi.freq.calib = calib - self.hsi.freq.update() - - add_gnoise = dialog['gnoise_bool'] # AWGN (Gaussian) - add_pnoise = dialog['pnoise_bool'] # Poisson noise - add_dark = dialog['dark_bool'] # Dark background -- just a constant - - # These values correspond to the defaults of the - # Anscombe UI - g_noise = dialog['gnoise_stddev'] # Std Dev of Gaussian noise - p_amp = dialog['pnoise_gain'] # Multiplier of Poisson noise - dark_amp = dialog['dark_level'] - - if add_pnoise: # Add Poisson noise - # NOTE: CORRECT is p_amp*poisson(signal) - # DEFINITELY NOT p_amp*(poisson(signal)-signal) + signal - self.hsi._data += p_amp*(_np.random.poisson(self.hsi._data)) - self.hsi._data - if add_gnoise: # Add AGWN - self.hsi._data += _np.random.randn(*self.hsi._data.shape) - if add_dark: # Add a constant dark background - self.hsi._data += dark_amp - self.dark._data = dark_amp + 0*f - self.dark.freq = self.hsi.freq - - self.filename = 'Phantom.h5' - self.path = _os.path.abspath('./') - self.dataset_name = '/BCARSImage/Phantom_v0/Phantom_v0' - - meta = {'Calib.a_vec': a_vec, - 'Calib.ctr_wl': lam_ctr, - 'Calib.ctr_wl0': lam_ctr, - 'Calib.n_pix': n_pix, - 'Calib.probe': calib['probe'], - 'Calib.units': 'nm', - 'Memo': 'Numerical phantom from murine pancreas artery. See Camp et al, JRS (2016).', - 'RasterScanParams.FastAxis': 'X', - 'RasterScanParams.FastAxisStart': model.x[0], - 'RasterScanParams.FastAxisStepSize': _np.diff(model.x).mean(), - 'RasterScanParams.FastAxisSteps': model.x.size, - 'RasterScanParams.FastAxisStop': model.x[-1], - 'RasterScanParams.FixedAxis': 'Z', - 'RasterScanParams.FixedAxisPosition': 0, - 'RasterScanParams.SlowAxis': 'Y', - 'RasterScanParams.SlowAxisStart': model.y[0], - 'RasterScanParams.SlowAxisStepSize': _np.diff(model.y).mean(), - 'RasterScanParams.SlowAxisSteps': model.y.size, - 'RasterScanParams.SlowAxisStop': model.y[-1], - 'Spectro.CenterWavelength': lam_ctr, - } - self.hsi._meta = meta - self.fileOpenSuccess(True) - self.changeSlider() - else: - pass
- - -
[docs] def makeBCARSPhantom(self): - """ - Generate a numerical phantom for BCARS - """ - cplx = True # Is model complex-valued -- True for BCARS - - dialog = DialogModel.dialogModel(cplx=cplx, parent=self) - if dialog is not None: - model = _Model(subsample=dialog['subsample']) - - wn_start = dialog['wn_start'] - wn_end = dialog['wn_end'] - - lam_start = 0.01 / (wn_start + 0.01/(dialog['probe']*1e-9)) # meters - lam_start *= 1e9 # nm - - lam_end = 0.01 / (wn_end + 0.01/(dialog['probe']*1e-9)) # meters - lam_end *= 1e9 # nm - - lam_ctr = (lam_start + lam_end) / 2 # nm - - n_pix = _np.ceil((lam_end-lam_start) / dialog['wl_slope']) - - # Make a properly linear frequency-vector and polyfit - f = dialog['wl_slope'] * _np.arange(n_pix) # Temporary frequency vec - f -= f.mean() - f += lam_ctr - - a_vec = _np.polyfit(_np.arange(n_pix), f, 1) - - calib = {'a_vec': a_vec, - 'ctr_wl': lam_ctr, - 'ctr_wl0': lam_ctr, - 'n_pix': n_pix, - 'probe': dialog['probe'], - 'units': 'nm'} - - f = _calib_pix_wn(calib)[0] - model.make_hsi(f=f) - - if cplx: - model.hsi = model.hsi.astype(_np.complex64) - self.hsi = Hsi(data=model.hsi, x=model.x, y=model.y) - else: - model.hsi = 1*model.hsi.imag - model.hsi = model.hsi.astype(_np.float32) - self.hsi = Hsi(data=model.hsi, x=model.x, y=model.y) - - # Simple Gaussian 0-centered source profile - source = 1e2*_np.exp(-f**2/(2*1500**2)) - nrb = 10*_np.exp(-(f-20e3)**2/(2*10e3**2)) - - self.hsi.data = _np.abs((self.hsi.data+nrb)*source)**2 - self.hsi.freq.calib_fcn = _calib_pix_wn - self.hsi.freq.calib = calib - self.hsi.freq.update() - - self.nrb.data = _np.abs(source*nrb)**2 - self.nrb.freq = self.hsi.freq - - add_gnoise = dialog['gnoise_bool'] # AWGN (Gaussian) - add_pnoise = dialog['pnoise_bool'] # Poisson noise - add_dark = dialog['dark_bool'] # Dark background -- just a constant - - # These values correspond to the defaults of the - # Anscombe UI - g_noise = dialog['gnoise_stddev'] # Std Dev of Gaussian noise - p_amp = dialog['pnoise_gain'] # Multiplier of Poisson noise - dark_amp = dialog['dark_level'] - - # Only dark added to NRB - # Others only to Hsi data - if add_pnoise: # Add Poisson noise - # NOTE: CORRECT is p_amp*poisson(signal) - # DEFINITELY NOT p_amp*(poisson(signal)-signal) + signal - self.hsi._data += p_amp*(_np.random.poisson(self.hsi._data)) - self.hsi._data - if add_gnoise: # Add AGWN - self.hsi._data += _np.random.randn(*self.hsi._data.shape) - if add_dark: # Add a constant dark background - self.hsi._data += dark_amp - self.nrb._data += dark_amp - self.dark._data = dark_amp + 0*f - self.dark.freq = self.hsi.freq - - self.filename = 'Phantom.h5' - self.path = _os.path.abspath('./') - self.dataset_name = '/BCARSImage/Phantom_v0/Phantom_v0' - - meta = {'Calib.a_vec': a_vec, - 'Calib.ctr_wl': lam_ctr, - 'Calib.ctr_wl0': lam_ctr, - 'Calib.n_pix': n_pix, - 'Calib.probe': calib['probe'], - 'Calib.units': 'nm', - 'Memo': 'Numerical phantom from murine pancreas artery. See Camp et al, JRS (2016).', - 'RasterScanParams.FastAxis': 'X', - 'RasterScanParams.FastAxisStart': model.x[0], - 'RasterScanParams.FastAxisStepSize': _np.diff(model.x).mean(), - 'RasterScanParams.FastAxisSteps': model.x.size, - 'RasterScanParams.FastAxisStop': model.x[-1], - 'RasterScanParams.FixedAxis': 'Z', - 'RasterScanParams.FixedAxisPosition': 0, - 'RasterScanParams.SlowAxis': 'Y', - 'RasterScanParams.SlowAxisStart': model.y[0], - 'RasterScanParams.SlowAxisStepSize': _np.diff(model.y).mean(), - 'RasterScanParams.SlowAxisSteps': model.y.size, - 'RasterScanParams.SlowAxisStop': model.y[-1], - 'Spectro.CenterWavelength': lam_ctr, - } - self.hsi._meta = meta - - self.ui.actionDarkSpectrum.setEnabled(True) - self.ui.actionNRBSpectrum.setEnabled(True) - self.ui.actionDarkSubtract.setEnabled(True) - self.ui.actionKramersKronig.setEnabled(True) - self.ui.actionPhaseErrorCorrection.setEnabled(True) - self.ui.actionScaleErrorCorrection.setEnabled(True) - self.ui.menuCoherent_Raman_Imaging.setEnabled(True) - - self.fileOpenSuccess(True) - self.changeSlider() - else: - pass
- -
[docs]def crikit_launch(**kwargs): - """ - Command line launching of CRIkitUI. - - Input kwargs (Optional) - ------------ - hsi : crikit.data.Hsi - Hsi instance - - data : ndarray (3D) - Numpy array (Y,X,Freq) hsi - - x : ndarray (1D) - x-array - - x_units : str - Units of x (e.g. r'$\mu$m') - - x_label : str - Label of x (e.g. 'X') - - y : ndarray (1D) - y-array - - y_units : str - Units of y (e.g. r'$\mu$m') - - y_label : str - Label of y (e.g. 'Y') - - f : ndarray (1D) - frequency-array - - f_units : str - Units of frequency (e.g. r'cm$^{-1}$') - - f_label : str - Label of frequency (e.g. 'Wavenumber') - - filename : str - Filename of HDF data to auto-load (requires path and dataset_name as well) - - path : str - Path of HDF data to auto-load (requires filename and dataset_name as well) - - dataset_name : str - Dataset name(s) of HDF data to auto-load (requires path and filename as well) - - """ - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - app.setQuitOnLastWindowClosed(False) - - parent = kwargs.get('parent') - - if parent is None: - obj = _QWidget() - else: - obj = parent - - kwargs['parent'] = obj - # print('Kwargs: {}'.format(kwargs)) - win = CRIkitUI_process(**kwargs) ### EDIT ### - - # Insert other stuff to do - - # Final stuff - win.showMaximized() - #win.plotter.lower() - #win.raise_() - app.exec_() - return None
- -if __name__ == '__main__': - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - app.setQuitOnLastWindowClosed(False) - - obj = _QWidget() - win = CRIkitUI_process(parent=obj) ### EDIT ### - - # Insert other stuff to do - - - # Final stuff - win.showMaximized() - #win.plotter.lower() - #win.raise_() - app.exec_() -# _sys.exit(app.exec_()) - #app.closeAllWindows() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/algorithms/kk.html b/docs/build/html/_modules/crikit/cri/algorithms/kk.html deleted file mode 100644 index fe39bc2..0000000 --- a/docs/build/html/_modules/crikit/cri/algorithms/kk.html +++ /dev/null @@ -1,467 +0,0 @@ - - - - - - - - - - - crikit.cri.algorithms.kk — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.cri.algorithms.kk
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.cri.algorithms.kk

-"""
-Kramers-Kronig Relation Phase Retrieval (crikit.process.maths.kk)
-=================================================================
-
-    kkrelation : Retrieve real and imaginary components from a
-    spectrum that is the modulus of a function
-
-    hilbertfft : Fourier-domain Hilbert transform
-
-References
-----------
-[1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent 
-    Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase 
-    Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543.
-
-"""
-
-import numpy as _np
-from scipy import fftpack as _fftpack
-
-__all__ = ['kkrelation', 'hilbertfft']
-
-_DEFAULT_THREADS = 1
-
-# Conditional modules
-# Check for and load pyFFTW if available (kkrelation, hilbertfft)
-try:  # pragma: no cover
-    import pyfftw as _pyfftw
-    _pyfftw_available = True
-except ImportError:  # pragma: no cover
-    print("No pyFFTW found. Using Scipy instead. \n\
-    You may want to install pyFFTW and FFTW for [potentially]\n\
-    significant performance enhancement")
-    _pyfftw_available = False
-
-
-
-# Check for and load multiprocessing to determine number of CPUs
-try:
-    import multiprocessing as _multiprocessing
-    _thread_num = _multiprocessing.cpu_count()
-except ImportError:  # pragma: no cover
-    print("No multiprocessing module found. \n\
-    Default thread number set to 1. This can be\n\
-    changed within the .py file")
-    _thread_num = _DEFAULT_THREADS
-
-
-
[docs]def kkrelation(bg, cri, phase_offset=0.0, norm_by_bg=True, pad_factor=1): - """ - Retrieve the real and imaginary components of a CRI spectra(um) via - the Kramers-Kronig (KK) relation. - - Parameters - ---------- - bg : ndarray - Coherent background (bg) spectra(um) array that can be one-, two-, \ - or three-dimensional - cri : ndarray - CRI spectra(um) array that can be one-,two-,or three-dimensional \ - (phase_offset) : int, float, or ndarray, optional - Global phase offset applied to the KK, which effecively controls \ - the real-to-imaginary components relationship - (norm_by_bg) : bool - Should the output be normalized by the square-root of the \ - background (bg) spectrum(a) - (pad_factor) : int - The multiple number of spectra-length pads that will be - applied before and after the original spectra - - - Returns - ------- - out : complex ndarray - The real and imaginary components of KK. - - Notes - ----- - (1) The imaginary components provides the sponatenous Raman-like \ - spectra(um). - - (2) This module assumes the spectra are oriented as such that the \ - frequency (wavenumber) increases with increasing index. If this is \ - not the case for your spectra(um), apply a phase_offset of _np.pi - - References - ---------- - Y Liu, Y J Lee, and M T Cicerone, "Broadband CARS spectral phase \ - retrieval using a time-domain Kramers-Kronig transform," Opt. Lett. 34, \ - 1363-1365 (2009). - - C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable \ - Coherent Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting \ - Errors in Phase Retrieval," Journal of Raman Spectroscopy (2016). \ - arXiv:1507.06543. - """ - - ratio = cri / bg - ratio[_np.isnan(ratio)] = 1e-8 - ratio[_np.isinf(ratio)] = 1e-8 - - ratio[ratio <= 0] = 1e-8 - - if ratio.ndim == 3: - h = _np.zeros(ratio.shape, dtype=float) - for row_num, blk in enumerate(ratio): - h[row_num, :, :] = hilbertfft(0.5 * _np.log(blk), - pad_factor=pad_factor) - else: - h = hilbertfft(0.5 * _np.log(ratio), pad_factor=pad_factor) - - # Note: disabled numexpr eval due to stability issues - if norm_by_bg is True: - out = _np.sqrt(ratio) * _np.exp(1j * phase_offset + 1j * h) - # out = _ne.evaluate('sqrt(ratio)*exp(1j*phase_offset + 1j*h)') - return out - else: - out = _np.sqrt(cri) * _np.exp(1j * phase_offset + 1j * h) - return out
- # return _ne.evaluate('sqrt(cri)*exp(1j*phase_offset + 1j*h)') - - -
[docs]def hilbertfft(spectra, pad_factor=1, use_pyfftw=True): - """ - Compute the one-dimensional Hilbert Transform. - - This function computes the one-dimentional Hilbert transform - using the Fourier-domain implementation. - - Parameters - ---------- - spectra : ndarray - Input array that can be one-,two-,or three-dimensional - pad_factor : int, optional - The multiple number of spectra-length pads that will be - applied before and after the original spectra - use_pyfftw : bool, optional - If available, use pyfftw. Else use scipy scipack implementation - - Returns - ------- - ndarray - Hilbert transformed data - - References - ---------- - C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable \ - Coherent Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting \ - Errors in Phase Retrieval," Journal of Raman Spectroscopy (2016). \ - arXiv:1507.06543. - - A D Poularikas, "The Hilbert Transform," in The Handbook of \ - Formulas and Tables for Signal Processing (ed., A. D. Poularikas), \ - Boca Raton, CRC Press LLC (1999). - """ - - assert spectra.ndim <= 2, 'Input data need be 1D or 2D for memory' - - freq_len = spectra.shape[-1] - freq_pad_len = freq_len*(2*pad_factor+1) - pad_len = freq_len*(pad_factor) - time_vec = _np.fft.fftfreq(freq_pad_len) - - if pad_factor > 0: - pad_left = _np.dot(spectra[..., 0][..., None], _np.ones((1, pad_len))) - pad_right = _np.dot(spectra[..., -1][..., None], _np.ones((1, pad_len))) - padded = _np.concatenate((pad_left, spectra, pad_right), axis=-1) - else: - padded = spectra - - padded = padded.astype(_np.complex) - - # Use pyFFTW (supposed optimal) library or Scipy - # Note (although not obvious with pyFFTW) these functions overwrite - # the input variable-- saves memory and increases speed - if _pyfftw_available and use_pyfftw: - _pyfftw.interfaces.cache.enable() - padded = _pyfftw.interfaces.scipy_fftpack.ifft(padded, axis=-1, - overwrite_x=True, - threads=_thread_num, - auto_align_input=True, - planner_effort='FFTW_MEASURE') - - padded *= 1j*_np.sign(time_vec) - - padded = _pyfftw.interfaces.scipy_fftpack.fft(padded, axis=-1, - overwrite_x=True, - threads=_thread_num, - auto_align_input=True, - planner_effort='FFTW_MEASURE') - else: # Perform Hilbert Transform with Scipy FFTPACK - _fftpack.ifft(padded, axis=-1, overwrite_x=True) - padded *= 1j*_np.sign(time_vec) - _fftpack.fft(padded, axis=-1, overwrite_x=True) - - # Set inf's and NaN's to arbitrarily small value - padded[_np.isnan(padded)] = 1e-8 - padded[_np.isinf(padded)] = 1e-8 - - return _np.real(padded[..., pad_len:pad_len + freq_len])
- -if __name__ == '__main__': # pragma: no cover - import timeit as _timeit - - x = _np.random.rand(300,900) - print(x.dtype) - y = _np.random.rand(300,900) - - - if _pyfftw_available: - start = _timeit.default_timer() - #out = kkrelation(x,y) - out = hilbertfft(x) - start -= _timeit.default_timer() - print('PyFFTW Time (Trial 1): {:.3g} sec'.format(-start)) - - start = _timeit.default_timer() - #out = kkrelation(x,y) - out = hilbertfft(x) - start -= _timeit.default_timer() - print('PyFFTW Time (Trial 2): {:.3g} sec'.format(-start)) - - start = _timeit.default_timer() - #out = kkrelation(x,y) - out = hilbertfft(x, use_pyfftw=False) - start -= _timeit.default_timer() - print('Scipy Time (Trial 1): {:.3g} sec'.format(-start)) - - start = _timeit.default_timer() - #out = kkrelation(x,y) - out = hilbertfft(x, use_pyfftw=False) - start -= _timeit.default_timer() - print('Scipy Time (Trial 2): {:.3g} sec'.format(-start)) - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/error_correction.html b/docs/build/html/_modules/crikit/cri/error_correction.html deleted file mode 100644 index bacb94c..0000000 --- a/docs/build/html/_modules/crikit/cri/error_correction.html +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - - - - - - crikit.cri.error_correction — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.cri.error_correction
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.cri.error_correction

-"""
-Created on Mon Jun  6 11:20:35 2016
-
-@author: chc
-"""
-
-import numpy as _np
-import copy as _copy
-
-from scipy.signal import savgol_filter as _sg
-
-from crikit.cri.algorithms.kk import hilbertfft as _hilbert
-
-from crikit.preprocess.algorithms.als import AlsCvxopt as _AlsCvxopt
-
-from crikit.utils.datacheck import _rng_is_pix_vec
-
-
-
[docs]class PhaseErrCorrectALS: - """ - Phase error correction using alternating least squares (ALS) - - References - ----------- - * C H Camp Jr, Y J Lee, and M T Cicerone, JRS (2016). - """ - def __init__(self, smoothness_param=1, asym_param=1e-2, - redux=10, order=2, rng=None, fix_end_points=False, - fix_rng=None, max_iter=100, min_diff=1e-5, **kwargs): - - - self.rng = _rng_is_pix_vec(rng) - self._k = kwargs - - self._k.update({'smoothness_param' : smoothness_param, - 'asym_param' : asym_param, - 'redux' : redux, - 'order' : order, - 'fix_end_points' : fix_end_points, - 'fix_rng' : fix_rng, - 'max_iter' : max_iter, - 'min_diff' : min_diff}) - - -
[docs] def _calc(self, data, ret_obj, **kwargs): - - self._inst_als = _AlsCvxopt(**kwargs) - - try: - shp = data.shape[0:-2] - total_num = _np.array(shp).prod() - - counter = 1 - for idx in _np.ndindex(shp): - print('Detrended iteration {} / {}'.format(counter, total_num)) - ph = _np.unwrap(_np.angle(data[idx])) - if self.rng is None: - err_phase = self._inst_als.calculate(ph) - else: - err_phase = self._inst_als.calculate(ph[..., self.rng]) - - h = _np.zeros(err_phase.shape) - h += _hilbert(err_phase) - - correction_factor = 1/_np.exp(h) * _np.exp(-1j*err_phase) - - if self.rng is None: - ret_obj[idx] *= correction_factor - else: - ret_obj[idx][..., self.rng] *= correction_factor - counter += 1 - except: - return False - else: -# print(self._inst_als.__dict__) - return True
- -
[docs] def calculate(self, data, **kwargs): - - data_copy = _copy.deepcopy(data) - self._k.update(kwargs) - - success = self._calc(data, ret_obj=data_copy, **self._k) - if success: - return data_copy - else: - return None
- -
[docs] def transform(self, data, **kwargs): - self._k.update(kwargs) - - success = self._calc(data, ret_obj=data, **self._k) - return success
- -
[docs]class ScaleErrCorrectSG: - """ - Scale error correction using Savitky-Golay - - References - ----------- - * C H Camp Jr, Y J Lee, and M T Cicerone, JRS (2016). - """ - def __init__(self, win_size=601, order=2, rng=None): - self.win_size = win_size - self.order = order - self.rng = _rng_is_pix_vec(rng) - -
[docs] def _calc(self, data, ret_obj): - try: - if self.rng is None: - correction_factor = _sg(data.real, window_length=self.win_size, - polyorder=self.order, axis=-1) - else: - correction_factor = _sg(data[..., self.rng].real, - window_length=self.win_size, - polyorder=self.order, axis=-1) - - correction_factor[correction_factor == 0] = 1 - correction_factor **= -1 - - if self.rng is None: - ret_obj *= correction_factor - else: - ret_obj[..., self.rng] *= correction_factor - except: - return False - else: - return True
- -
[docs] def calculate(self, data): - - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- -
[docs] def transform(self, data): - success = self._calc(data, ret_obj=data) - return success
- - -if __name__ == '__main__': # pragma: no cover - import matplotlib.pyplot as plt - from crikit.cri.kk import KramersKronig - import timeit - - SPECT_LEN = 878 - WN = _np.linspace(4000, 500, SPECT_LEN) - chi = (1 / ((WN - 1000 - 1j * 10)) + - 1 / ((WN - 1020 - 1j * 10)) + - 1 / ((WN - 2800 - 1j * 10))) - chiNR = 0*chi + 0.055 - exc = WN - sig = _np.abs(chi + chiNR)**2 - - sigNR = _np.abs(chiNR)**2 - sigRef = chiNR*(WN/1e3)**.5 - - NUM_REPS = 10 - - kk = KramersKronig() - kkd = kk.calculate(sig, sigRef) - kkd = _np.dot(_np.random.rand(NUM_REPS,NUM_REPS,1)*_np.ones((NUM_REPS, NUM_REPS, 1)), kkd[None, :]) - -# plt.plot(chi.imag/chiNR.real, label='Ideal') - plt.plot(kkd[5, 5, :].imag, label='Before Correction') - - start = timeit.default_timer() - phase_err_correct_als = PhaseErrCorrectALS(fix_end_points=True, - smoothness_param=1e8, - asym_param=1e-3, - redux=1) - success = phase_err_correct_als.transform(kkd, verbose=False) - print('Success? : {}'.format(success)) - stop = timeit.default_timer() - print('Sec/spectrum: {:.3g}'.format((stop-start)/NUM_REPS**2)) - - -# - plt.plot(kkd[5,5,:].imag, label='After PhErr Corr.') - plt.legend() - plt.show() -# scale_err_correct_sg = ScaleErrCorrectSG() -# success = scale_err_correct_sg.transform(kkd) -# print('Success? : {}'.format(success)) -# plt.plot(kkd[5, 5, :].imag, label='After Correction') -# plt.legend(loc='best') -# plt.show() - -# scale_err_correct_sg = ScaleErrCorrectSG() -# out = scale_err_correct_sg.calculate(kkd[0,0,:]) -# plt.plot(out.imag) -# -# scale_err_correct_sg = ScaleErrCorrectSG(win_size=11, order=2) -# out = scale_err_correct_sg.calculate(kkd[0,0,:]) -# plt.plot(out.imag) -# -# plt.show() - -# -# phase_err_correct_als = PhaseErrCorrectALS(print_iteration=False) -# out = phase_err_correct_als.calculate(kkd) -# -# plt.plot(out[0,0,:].imag) -# -# phase_err_correct_als = PhaseErrCorrectALS(smoothness_param=1e1, -# asym_param=1e-2, -# redux_factor=1) - - -# print(phase_err_correct_als._k) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/kk.html b/docs/build/html/_modules/crikit/cri/kk.html deleted file mode 100644 index a6c2991..0000000 --- a/docs/build/html/_modules/crikit/cri/kk.html +++ /dev/null @@ -1,481 +0,0 @@ - - - - - - - - - - - crikit.cri.kk — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.cri.kk

-"""
-Kramers-Kronig relation phase retrieval.
-
-References
-----------
-[1] Y. Liu, Y. J. Lee, and M. T. Cicerone, "Broadband CARS spectral
-phase retrieval using a time-domain Kramers-Kronig transform,"
-Opt. Lett. 34, 1363-1365 (2009).
-
-[2] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, \
-Comparable Coherent Anti-Stokes Raman Scattering (CARS) \
-Spectroscopy: Correcting Errors in Phase Retrieval," Journal of Raman \
-Spectroscopy 47, 408-415 (2016). arXiv:1507.06543.
-
-
-"""
-
-import timeit as _timeit
-
-import numpy as _np
-
-from crikit.cri.algorithms.kk import kkrelation as _kkrelation
-from crikit.utils.datacheck import _rng_is_pix_vec
-from crikit.utils.general import find_nearest as _find_nearest
-from crikit.utils.general import mean_nd_to_1d as _mean_nd_to_1d
-
-
[docs]class KramersKronig: - """ - Retrieve the real and imaginary components of coherent Raman data via the \ - Kramers-Kronig (KK) relation. See References. - - Parameters - ---------- - cars_amp_offset : float, optional (default=0.0) - DC offset applied to CARS spectrum(a) prior to KK relation. See Notes \ - and Ref. [2]. - - nrb_amp_offset : float, optional (default=0.0) - DC offset applied to NRB spectrum(a) prior to KK relation. See Notes \ - and Ref. [2]. - - phase_offset : float or ndarray, optional (default=0.0) - Phase constant or ndarray applied to retrieved phase prior to \ - separating the real and imaginary components. See Notes \ - and Ref. [2]. - - norm_to_nrb : bool, optional (default=True) - Normalize the amplitude by sqrt(NRB). This effectively removes several \ - system reponse functions. Highly recommended. See Ref. [2] - - pad_factor : int, optional (default=1) - Multiple size of spectral-length to pad the ends of each spectra with. \ - Padded with a constant value corresponding to the value at that end of \ - the spectrum. See Ref. [1]. - - rng : ndarray (1D), optional (default=None) - Range of pixels/frequencies (if freq provided) to perform over - - rng_list : list/tuple, optional (default=None) - First and Last pixels/frequencies (if freq provided) to perform over - - freq : ndarray (1D), optional (default=None) - Frequency vector - - Returns - ------- - ndarray - KK of cars - - Notes - ----- - * This function does NOT overwrite input data - * The imaginary components provides the sponatenous Raman-like spectra(um). - * This module assumes the spectra are oriented as such that the frequency \ - (wavenumber) increases with increasing index. If this is not the case for \ - your spectra(um), apply a phase_offset of pi. - - References - ---------- - [1] Y. Liu, Y. J. Lee, and M. T. Cicerone, "Broadband CARS spectral - phase retrieval using a time-domain Kramers-Kronig transform," - Opt. Lett. 34, 1363-1365 (2009). - - [2] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, \ - Comparable Coherent Anti-Stokes Raman Scattering (CARS) \ - Spectroscopy: Correcting Errors in Phase Retrieval," Journal of Raman \ - Spectroscopy 47, 408-415 (2016). arXiv:1507.06543. - - """ - def __init__(self, cars_amp_offset=0.0, nrb_amp_offset=0.0, - phase_offset=0.0, norm_to_nrb=True, pad_factor=1, rng=None): - - self.cars_amp_offset = cars_amp_offset - self.nrb_amp_offset = nrb_amp_offset - self.phase_offset = phase_offset - self.norm_to_nrb = norm_to_nrb - self.pad_factor = pad_factor - - # Check range of operation - self.rng = _rng_is_pix_vec(rng) - - -
[docs] def _calc(self, cars, nrb, ret_obj): - - # Assume that an nD nrb should be averaged to be 1D - nrb = _mean_nd_to_1d(nrb) - - shp = cars.shape[0:-2] - - # Step row-by-row through image - for idx in _np.ndindex(shp): - if self.rng is None: - kkd = _kkrelation(bg=nrb + self.nrb_amp_offset, - cri=cars[idx] + self.cars_amp_offset, - phase_offset=self.phase_offset, - norm_by_bg=self.norm_to_nrb, - pad_factor=self.pad_factor) - else: - kkd = _kkrelation(bg=nrb[self.rng] + self.nrb_amp_offset, - cri=cars[idx][..., self.rng] + self.cars_amp_offset, - phase_offset=self.phase_offset, - norm_by_bg=self.norm_to_nrb, - pad_factor=self.pad_factor) - - try: - ret_obj[idx] *= 0 - if self.rng is None: - ret_obj[idx] += kkd - elif ret_obj[idx].size == kkd.size: - ret_obj[idx] += kkd - else: - ret_obj[idx][..., self.rng] += kkd - except: - return False - else: - pass - return True
- -
[docs] def calculate(self, cars, nrb): - """ - cars : ndarray - Coherent Raman signal. - - nrb : ndarray - Nonresonant background (NRB) - """ - - kkd = _np.zeros(cars.shape, dtype=_np.complex) - success = self._calc(cars, nrb, ret_obj=kkd) - if success: - return kkd - else: - return None
- -
[docs] def _transform(self, cars, nrb): - if issubclass(cars.dtype.type, _np.complex): - success = self._calc(cars, nrb, ret_obj=cars) - return success - else: - return False
- - -if __name__ == '__main__': # pragma: no cover - - from crikit.data.spectrum import Spectrum as _Spectrum - from crikit.data.spectra import Spectra as _Spectra - from crikit.data.hsi import Hsi as _Hsi - - hsi = _Hsi() - nrb = _Spectra() - - WN = _np.linspace(-1386,3826,400) - X = .055 + 1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) - XNR = 0*X + 0.055 - E = 1*_np.exp(-(WN-2000)**2/(2*3000**2)) - - # Simulated spectrum - CARS = _np.abs(E+X)**2 - NRB = _np.abs(E+XNR)**2 - nrb.data = NRB - - # Copies of spectrum - temp = _np.dot(_np.ones((30,30,1)),CARS[None,:]) - - # Create an HSData class instance - hsi.data = temp - num_spectra = int(hsi.size/WN.size) - - hsi.freq.data = WN - - start = _timeit.default_timer() - kkd = _kkrelation(NRB,CARS) - stop = _timeit.default_timer() - print('Single spectrum -- Total time: {:.6f} sec'.format(stop-start)) - _timeit.time.sleep(2) - - start = _timeit.default_timer() - kkd = _kkrelation(NRB,temp) - stop = _timeit.default_timer() - print('Data-based -- Total time: {:.6f} sec ({:.6f} sec/spectrum)'.format(stop-start, - (stop-start)/num_spectra)) - _timeit.time.sleep(2) - - - kk = KramersKronig(cars_amp_offset=0, nrb_amp_offset=0, norm_to_nrb=False, pad_factor=1) - start = _timeit.default_timer() - kk.calculate(hsi.data, nrb.data) - stop = _timeit.default_timer() - print('Class-based -- Total time: {:.6f} sec ({:.6f} sec/spectrum)'.format(stop-start, - (stop-start)/num_spectra)) - - hsi.data = temp - _timeit.time.sleep(2) - - - import matplotlib as mpl - mpl.rcParams['font.size'] = 14 - import matplotlib.pyplot as plt - - hsi.freq.op_list_freq = [500, 4000] - - #plt.plot(hsi.freq.freq_vec[hsi.freq.op_range_pix], hsi.data[0,0,hsi.freq.op_range_pix]) - - kk = KramersKronig(cars_amp_offset=0, nrb_amp_offset=0, - norm_to_nrb=False, rng=hsi.freq.op_range_pix, - pad_factor=1) - start = _timeit.default_timer() - del kkd - kkd = kk.calculate(hsi.data, nrb.data) - stop = _timeit.default_timer() - print('Pixrange Class-based -- Total time: {:.6f} sec ({:.6f} sec/spectrum)'.format(stop-start, - (stop-start)/num_spectra)) - - hsi.data = kkd - del kkd - _timeit.time.sleep(2) - - plt.plot(WN, X.imag, label='Imag.{$\chi_{R}$}') - plt.plot(hsi.freq.data[hsi.freq.op_range_pix], - hsi.data[10,10,hsi.freq.op_range_pix].imag, 'r*', - label='KK-Retrieved') - plt.legend(loc='best') - plt.xlabel('Wavenumber (cm$^{-1}$)') - plt.ylabel('Raman Int. (au)') - plt.title('Raman vs KK-Retrieved CARS') - plt.show() - - print(_np.allclose(X.imag[hsi.freq.op_range_pix], hsi.data[10,10,hsi.freq.op_range_pix].imag,rtol=1)) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/merge_nrbs.html b/docs/build/html/_modules/crikit/cri/merge_nrbs.html deleted file mode 100644 index 969345f..0000000 --- a/docs/build/html/_modules/crikit/cri/merge_nrbs.html +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - crikit.cri.merge_nrbs — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.cri.merge_nrbs
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.cri.merge_nrbs

-"""
-Created on Wed Nov  2 11:04:43 2016
-
-@author: chc
-"""
-
-import copy as _copy
-
-if __name__ == '__main__':
-    import matplotlib.pyplot as _plt
-    import numpy as _np
-
-    
-
[docs]class MergeNRBs: - """ - Merge two NRBs: a left-side and a right-side - - """ - def __init__(self, nrb_left, nrb_right, pix, left_side_scale=True): - """ - Attributes - ---------- - pix : int - Pixel number to make the merge - - left_side_scale : bool - Scale the left-side to match the right-side. If FALSE, scales the - right-side. If None, scales neither. - - """ - self.nrb_left = nrb_left - self.nrb_right = nrb_right - self.nrb_merge = None - - self.pix = pix - self.scale_left = left_side_scale - -
[docs] def calculate(self): - """ - - """ - if self.nrb_left.size != self.nrb_right.size: - print('NRB size mismatch') - return None - else: - pass - - self.nrb_merge = _copy.deepcopy(0*self.nrb_left) - - success = self._calc(self.nrb_merge, ret_obj=self.nrb_merge) - if success: - return self.nrb_merge - else: - return None
- -
[docs] def _calc(self, data, ret_obj): - try: - ret_obj *= 0 - scaler = self.nrb_left[self.pix]/self.nrb_right[self.pix] - if self.scale_left == True: - ret_obj += self.nrb_left/scaler - ret_obj[self.pix::] = self.nrb_right[self.pix::] - elif self.scale_left == False: - ret_obj += self.nrb_left - ret_obj[self.pix::] = self.nrb_right[self.pix::]*scaler - elif self.scale_left is None: - ret_obj[0:self.pix+1] = self.nrb_left[0:self.pix+1] - ret_obj[self.pix+1::] = self.nrb_right[self.pix+1::] - - else: - raise ValueError('self.scale_left must be 0 or 1') - except: - return False - else: - return True
- -if __name__ == '__main__': - x = _np.arange(0,1000) - - nrb_left = _np.exp(-(x-500)**2/(100**2)) - nrb_right = _np.exp(-(x-700)**2/(120**2)) - - pix = 625 - - _plt.plot(x, nrb_left, label='left') - _plt.plot(x, nrb_right, label='right') - _plt.title('Raw NRBs') - - - merge = MergeNRBs(nrb_left, nrb_right, pix, left_side_scale=True) - out_scaled_left = merge.calculate() - _plt.plot(x, out_scaled_left, ls='--', label='Left Scaled') - - merge = MergeNRBs(nrb_left, nrb_right, pix, left_side_scale=False) - out_scaled_right = merge.calculate() - _plt.plot(x, out_scaled_right, ls='--', label='Right Scaled') - - merge = MergeNRBs(nrb_left, nrb_right, pix, left_side_scale=None) - out_scaled_none = merge.calculate() - _plt.plot(x, out_scaled_none, ls='--', lw=3, label='NOT Scaled') - - _plt.legend(loc='best') - _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/tests/test_hilbert.html b/docs/build/html/_modules/crikit/cri/tests/test_hilbert.html deleted file mode 100644 index 731bbb0..0000000 --- a/docs/build/html/_modules/crikit/cri/tests/test_hilbert.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - - - - - - crikit.cri.tests.test_hilbert — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.cri.tests.test_hilbert
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.cri.tests.test_hilbert

-"""
-Testing for Hilbert transform method
-
-Using the math relation a^2 / (a^2 + x^2) (Lorentz/Cauchy) has an 
-analytical Hilbert transform: x^2 / (a^2 + x^2)
-"""
-
-import numpy as np
-from numpy.testing import assert_array_almost_equal
-
-from crikit.cri.algorithms.kk import hilbertfft
-
-
-
[docs]def test_pyfftw_hilbert_no_pad(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - hilb_y = hilbertfft(y, pad_factor=0, use_pyfftw=True) - hilb_y_analytical = x/(2**2 + x**2) - assert_array_almost_equal(hilb_y_analytical, hilb_y, decimal=2)
- -
[docs]def test_pyfftw_hilbert_pad(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - hilb_y = hilbertfft(y, pad_factor=10, use_pyfftw=True) - hilb_y_analytical = x/(2**2 + x**2) - assert_array_almost_equal(hilb_y_analytical, hilb_y, decimal=4)
- -
[docs]def test_hilbert_no_pad(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - hilb_y = hilbertfft(y, pad_factor=0, use_pyfftw=False) - hilb_y_analytical = x/(2**2 + x**2) - assert_array_almost_equal(hilb_y_analytical, hilb_y, decimal=2)
- -
[docs]def test_hilbert_pad(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - hilb_y = hilbertfft(y, pad_factor=10, use_pyfftw=False) - hilb_y_analytical = x/(2**2 + x**2) - assert_array_almost_equal(hilb_y_analytical, hilb_y, decimal=4)
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/tests/test_kk.html b/docs/build/html/_modules/crikit/cri/tests/test_kk.html deleted file mode 100644 index 2e2556e..0000000 --- a/docs/build/html/_modules/crikit/cri/tests/test_kk.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - crikit.cri.tests.test_kk — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.cri.tests.test_kk
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.cri.tests.test_kk

-"""
-Testing for Kramers-Kronig Phase Retrieval Method
-
-Using the math relation a^2 / (a^2 + x^2) (Lorentz/Cauchy) has an 
-analytical Hilbert transform: x^2 / (a^2 + x^2)-- and how that plays into
-the KK
-
-"""
-
-import numpy as np
-from numpy.testing import assert_array_almost_equal
-
-from crikit.cri.kk import KramersKronig
-
-
-
[docs]def test_kk(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - hilb_y_analytical = x/(2**2 + x**2) - - kk = KramersKronig(pad_factor=10) - kkd = kk.calculate(np.exp(2*y), 0*y + 1) - - kkd_angle = np.angle(kkd) - assert_array_almost_equal(hilb_y_analytical, kkd_angle, decimal=4)
- -
[docs]def test_kk_no_bg_norm(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - - kk = KramersKronig(norm_to_nrb=False) - kkd = kk.calculate(y, 0*y + 1) - - assert_array_almost_equal(np.abs(kkd), np.sqrt(y))
- -
[docs]def test_kk_rng(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - - rng = np.arange(5, x.size) - - kk = KramersKronig(norm_to_nrb=False, rng=rng) - kkd = kk.calculate(y, 0*y + 1) - - assert_array_almost_equal(np.abs(kkd[rng]), np.sqrt(y[rng]))
- -
[docs]def test_kk_transform(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - y_complex = y.astype(np.complex) - - kk = KramersKronig(norm_to_nrb=False) - success = kk._transform(y_complex, 0*y_complex + 1) - - assert success - assert_array_almost_equal(np.abs(y_complex), np.sqrt(y))
- -
[docs]def test_kk_transform_fail(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - y_complex = y.astype(np.complex) - - kk = KramersKronig(norm_to_nrb=False) - - success = kk._transform(y, 0*y + 1) - assert not success
- -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/cri/tests/test_kk_alg.html b/docs/build/html/_modules/crikit/cri/tests/test_kk_alg.html deleted file mode 100644 index b23ee2c..0000000 --- a/docs/build/html/_modules/crikit/cri/tests/test_kk_alg.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - - - - - crikit.cri.tests.test_kk_alg — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.cri.tests.test_kk_alg
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.cri.tests.test_kk_alg

-"""
-Testing for Kramers-Kronig Phase Retrieval Method
-
-Using the math relation a^2 / (a^2 + x^2) (Lorentz/Cauchy) has an 
-analytical Hilbert transform: x^2 / (a^2 + x^2)-- and how that plays into
-the KK
-
-"""
-
-import numpy as np
-from numpy.testing import assert_array_almost_equal
-
-from crikit.cri.algorithms.kk import kkrelation
-
-
-
[docs]def test_kk(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - hilb_y_analytical = x/(2**2 + x**2) - kkd = kkrelation(0*y + 1, np.exp(2*y), pad_factor=10) - kkd_angle = np.angle(kkd) - assert_array_almost_equal(hilb_y_analytical, kkd_angle, decimal=4)
- -
[docs]def test_kk_no_bg_norm(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - - kkd = kkrelation(0*y + 1, y, norm_by_bg=False) - assert_array_almost_equal(np.abs(kkd), np.sqrt(y))
- -
[docs]def test_kk_3d(): - x = np.linspace(-100, 100, 1000) - y = 2/(2**2 + x**2) - y = y[:, None, None] - - kkd = kkrelation(0*y + 1, y, norm_by_bg=False) - assert_array_almost_equal(np.abs(kkd), np.sqrt(y))
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/data/factorized.html b/docs/build/html/_modules/crikit/data/factorized.html deleted file mode 100644 index 2104dfc..0000000 --- a/docs/build/html/_modules/crikit/data/factorized.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - crikit.data.factorized — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.data.factorized
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.data.factorized

-"""
-Factored data class
-
-Created on Fri Apr 22 23:42:40 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-from crikit.data.frequency import Frequency as _Frequency
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.spectra import Spectra as _Spectra
-from crikit.data.replicate import Replicate as _Replicate
-from crikit.data.hsi import Hsi as _Hsi
-
-
[docs]class _Factorized: - """ - Factorized class. Contains items unique to factorized spectral data. - """ - - def __init__(self): - raise NotImplementedError
- -
[docs]class FactorizedHsi(_Hsi, _Factorized): - """ - Factorized Hsi Class - - Attributes - ---------- - - Methods - ------- - - Notes - ----- - * TODO: deside on - - """ - def __init__(self): - raise NotImplementedError
- -
[docs]class FactorizedSpectra(_Spectra, _Factorized): - """ - Factorized Spectra Class - - Attributes - ---------- - - Methods - ------- - - Notes - ----- - * TODO: deside on - - """ - def __init__(self): - raise NotImplementedError
- -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/data/frequency.html b/docs/build/html/_modules/crikit/data/frequency.html deleted file mode 100644 index 3992cb6..0000000 --- a/docs/build/html/_modules/crikit/data/frequency.html +++ /dev/null @@ -1,695 +0,0 @@ - - - - - - - - - - - crikit.data.frequency — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.data.frequency
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.data.frequency

-"""
-"Frequency" [,wavelength, and wavenumber] class and function.
-
-"""
-
-import numpy as _np
-import copy as _copy
-from crikit.utils.general import find_nearest as _find_nearest
-
-__all__ = ['Frequency', 'calib_pix_wn', 'calib_pix_wl']
-
-
[docs]class Frequency: - """ - Frequency [,wavelength, and waevnumber] class - - Attributes - ---------- - data : 1D ndarray, optional (see note) - Frequency vector - - calib : object, optional (see note) - Calibration object that is passed to calib_fcn - - calib_orig : object, optional (see note) - Calibration object ('original'). Set during initial setting of calib. \ - Useful for backing-up calibration) - - calib_fcn : fcn, optional (see note) - Function that accepts a calibration object and returns data and \ - units - - units : str, optional - Units of data (the default is 'Frequency'). Over-written by return \ - from calib_fcn - - op_list_pix : list or tuple or 1D ndarray - Range of pixels to perform operations over. Must be even lengthed. - - op_list_freq : list or tuple or 1D ndarray - Range of frequencies (or wavelength, or wavenumber) to perform \ - operations over. Must be even lengthed. - - plot_list_pix : list or tuple or 1D ndarray - Range of pixels to plot. Must be even lengthed. - - plot_list_freq : list or tuple or 1D ndarray - Range of frequencies (or wavelength, or wavenumber) to plot. \ - Must be even lengthed. - - size : int, read-only - Length of data - - pix_vec : 1D ndarray, read-only - Pixel vector (0-indexed) - - op_range_freq : 1D ndarray, read-only - Range of operarational frequencies - - plot_range_freq : 1D ndarray, read-only - Range of printing frequencies (not implemented) - - Methods - ------- - update - Updates data based on contents of calib (or calib_orig) and calib_fcn - - get_index_of_closest_freq - Find the closest frequency in freq to a given freq value and RETURN - the pixel value. - - get_closest_freq - Find the closest frequency in freq to a given freq value. - - Notes - ----- - Currently, this implementation does not check whether the - attributes/parameters are contradictory: - - calib - - calib_orig - - data - - - The purpose of _list_ is to limit the range over which operation \ - or plotting is performed. In some instances, for example, one may collect \ - a larger set of frequencies that of interest or there may be blank (i.e., \ - no signal) regions. Limiting these regions enables faster computation, may \ - minimize "edge effects", and may allow for zoomed-in plotting when there \ - are items of interest or a large dynamic range across a spectrum. - - - For functions, methods, etc. that take into account _list_ \ - parameters, they should default to op_list_ if plot_list_ are set to \ - None. - - """ - - def __init__(self, data=None, calib=None, calib_orig=None, - calib_fcn=None, units=None): - - - self._data = None - self._calib = None - self._calib_orig = None - self._calib_fcn = None - self._label = None - self._units = None - self._op_list_pix = None - self._op_list_freq = None - self._plot_list_pix = None - self._plot_list_freq = None - - if data is not None: - self.data = data - if calib is not None: - self.calib = calib - if calib_orig is not None: - self.calib_orig = calib_orig - if calib_fcn is not None: - self.calib_fcn = calib_fcn - if units is not None: - self.units = units - - if (self._data is None) and (self._calib is not None) and \ - (self._calib_fcn is not None): - self.update() - - @property - def data(self): - return self._data - - @data.setter - def data(self, value): - if isinstance(value, _np.ndarray): - if value.ndim == 1: - self._data = value - else: - raise TypeError('data must be a 1D ndarray') - elif value is None: - self._data = None - else: - raise TypeError('data must be a 1D ndarray') - - @property - def calib(self): - return self._calib - - @calib.setter - def calib(self, value): - if isinstance(value, dict): - self._calib = value - if self._calib_orig is None: - self._calib_orig = value - elif value is None: - self._calib = None - self.update() - else: - raise TypeError('calib must be of type dict') - - @calib.deleter - def calib(self): - self._calib = None - self.update() - - - @property - def calib_orig(self): - return self._calib_orig - - @calib_orig.setter - def calib_orig(self, value): - if isinstance(value, dict): - self._calib_orig = value - else: - raise TypeError('calib_orig must be of type dict') - - - @property - def calib_fcn(self): - return self._calib_fcn - - @calib_fcn.setter - def calib_fcn(self, value): - if callable(value): - self._calib_fcn = value - else: - raise TypeError('calib_fcn must be a callable function') - - @property - def units(self): - return self._units - - @units.setter - def units(self, value): - if isinstance(value, str): - self._units = value - else: - raise TypeError('units must be of type str') - - @property - def size(self): - return self.data.size - - @property - def pix_vec(self): - return _np.arange(self.data.size) - -
[docs] def update(self): - """ - Update data with calib and calib_fcn. - """ - if self._calib_fcn is None: - raise TypeError('Calibration function not set') - if self._calib is None: - if self._calib_orig is None: - raise TypeError('Calibration object not set') - else: - self.calib = self._calib_orig - - self.data, self.units = self.calib_fcn(self.calib)
- - @property - def op_list_pix(self): - return self._op_list_pix - - @op_list_pix.setter - def op_list_pix(self,value): - if isinstance(value, list) or isinstance(value, tuple) or isinstance(value, _np.ndarray): - if len(value) == 2: - value = list(value) - value.sort() - self._op_list_pix = value - self._op_list_freq = self.get_closest_freq(value) - self._op_list_freq.sort() - elif len(value) != 2 and _np.mod(len(value),2) == 0 and len(value) != 0: - raise NotImplementedError('op_list_pix can only currently handle 2 entries') - else: - raise TypeError('op_list_pix should be a list, tuple, or ndarray with an even number of entries') - else: - raise TypeError('op_list_pix should be a list, tuple, or ndarray') - - @op_list_pix.deleter - def op_list_pix(self): - self._op_list_pix = None - self._op_list_freq = None - - @property - def op_list_freq(self): - return self._op_list_freq - - @op_list_freq.setter - def op_list_freq(self,value): - if isinstance(value, list) or isinstance(value, tuple) or isinstance(value, _np.ndarray): - if len(value) == 2: - value = list(value) - value.sort() - self._op_list_pix = self.get_index_of_closest_freq(value) - self._op_list_pix.sort() - self._op_list_freq = self.get_closest_freq(value) - self._op_list_freq.sort() - elif len(value) != 2 and _np.mod(len(value),2) == 0 and len(value) != 0: - raise NotImplementedError('op_list_freq can only currently handle 2 entries') - elif len(value) == 0: - self._op_list_freq = None - self._op_list_pix = None - else: - raise TypeError('op_list_freq should be a list, tuple, or ndarray with an even number of entries') - else: - raise TypeError('op_list_freq should be a list, tuple, or ndarray') - - @op_list_freq.deleter - def op_list_freq(self): - self._op_list_pix = None - self._op_list_freq = None - - @property - def op_range_pix(self): - if self._op_list_pix is not None: - return _np.arange(self._op_list_pix[0],self._op_list_pix[1]+1) - else: - return self.pix_vec - - @property - def op_range_freq(self): - if self._op_list_pix is not None: - return self.data[self.op_range_pix] - else: - return self.data - - @property - def op_size(self): - if self._op_list_pix is None: - return self.data.size - else: - return self._op_list_pix[-1] - self._op_list_pix[0] + 1 - - @property - def plot_list_pix(self): - raise NotImplementedError('plot_list_pix is not yet implemented') - - @property - def plot_list_freq(self): - raise NotImplementedError('plot_list_freq is not yet implemented') - - -
[docs] def get_index_of_closest_freq(self, in_freqs): - """ - Return index(-es) of frequency(-ies) in freq closest to in_freqs - """ - return _find_nearest(self.data, in_freqs)[1]
- -
[docs] def get_closest_freq(self, in_freqs): - """ - Return frequency(-ies) in freq closest to in_freqs - """ - return _find_nearest(self.data, in_freqs)[0]
- -
[docs]def calib_pix_wl(calib_obj): - """ - Return a wavelength (wl) vector based on calibration (calib) object - - Parameters - ---------- - calib_obj : dict or list or 1D ndarray - Calibration object (see below). - - calib_obj : dict {'n_pix', 'ctr_wl', 'ctr_wl0', 'units', 'a_vec'} - Calibration dict with 5 key-value pairs (see Notes) - - calib_obj : list or 1D ndarray - Calibration array ['n_pix', 'ctr_wl', 'ctr_wl0', 'units', - 'a_0', 'a_1', ..., 'a_n'] - Returns - ------- - wl_vec : 1D ndarray - Wavelength vector - units : str - Units string 'Wavelength (' + calib_obj['units'] + ')' - - Notes - ----- - calib_obj dict key-value pairs: - * n_pix : int, number of pixels (0-index) - * ctr_wl : float, center wavelength - * ctr_wl0 : float, center calibration wavelength - * units : str, wavelength units, optional (default is 'nm') - * a_vec : list or 1D ndarray, polynomial coefficients, [a_n, a_n-1,..., \ - a_1, a_0]. a_2...a_n, optional. - - calibration model: - .. math:: - wl\_{vec} = a_n*(n\_{pix})^n + a_{n-1}*(n\_{pix})^{n-1} + ~...~ + \ - n\_{pix}*a_1 + a_0 + ctr\_{wl} - ctr\_{wl0} - - """ - - - calib = {} - - if len(calib_obj) < 4: - raise TypeError('Calibration object does not contain enough entries') - - if isinstance(calib_obj, dict): - key_list = ['n_pix','ctr_wl', 'ctr_wl0', 'a_vec'] - for k in key_list: - if k not in calib_obj: - raise KeyError('Calibration dict missing: {}'.format(k)) - else: - calib[k] = calib_obj[k] - if 'units' in calib_obj: - calib['units'] = calib_obj['units'] - else: - calib['units'] = 'nm' - - pix = _np.arange(calib['n_pix']) - wl_vec = _np.polyval(calib['a_vec'], pix) - wl_vec += calib['ctr_wl'] - calib['ctr_wl0'] - - return (wl_vec, calib['units'])
- -
[docs]def calib_pix_wn(calib_obj): - """ - Return a wavenumber (wn) vector based on calibration (calib) object - - Parameters - ---------- - calib_obj : dict or list or 1D ndarray - Calibration object (see below). - - calib_obj : dict {'n_pix', 'ctr_wl', 'ctr_wl0', 'probe', 'units', 'a_vec'} - Calibration dict with 6 key-value pairs (see Notes) - - calib_obj : list or 1D ndarray - Calibration array ['n_pix', 'ctr_wl', 'ctr_wl0', 'probe', 'units', - 'a_0', 'a_1', ..., 'a_n'] - - Returns - ------- - wn_vec : 1D ndarray - Wavenumber vector - units : str - Wavenumber units. Always 'cm$^-1$' - - Notes - ----- - calib_obj dict key-value pairs: - * n_pix : int, number of pixels (0-index) - * ctr_wl : float, center wavelength - * ctr_wl0 : float, center calibration wavelength - * probe : float, center wavelength of probe source (in units) - * units : {'nm', 'um'}, wavelength units, optional (default is 'nm') - * a_vec : list or 1D ndarray, polynomial coefficients, [a_n, a_n-1,..., \ - a_1, a_0]. a_2...a_n, optional. - - calibration model : - Wavelength vector: - .. math:: - wl\_{vec} = a_n*(n\_{pix})^n + a_{n-1}*(n\_{pix})^{n-1} + ~...~ + \ - n\_{pix}*a_1 + a_0 + ctr\_{wl} - ctr\_{wl0} - Wavenumber vector: - .. math:: - wl\_{vec} = a_n*(n\_{pix})^n + a_{n-1}*(n\_{pix})^{n-1} + ~...~ + \ - n\_{pix}*a_1 + a_0 + ctr\_{wl} - ctr\_{wl0} - - """ - calib = _copy.deepcopy(calib_obj) - - if 'probe' not in calib: - raise KeyError('\'probe\' key not in calib_obj') - - if 'units' not in calib: - calib['units'] = 'nm' - factor = 1e7 - elif calib['units'] == 'nm': - factor = 1e7 - elif calib['units'] == 'um': - factor = 1e4 - else: - raise ValueError('Only nanometer (\'nm\') and micrometer (\'um\') units accepted') - wl_vec, _ = calib_pix_wl(calib_obj) - wn_vec = factor/wl_vec - factor/calib['probe'] - return (wn_vec, 'cm$^{-1}$')
- -if __name__ == '__main__': # pragma: no cover - import matplotlib as _mpl - _mpl.use('Qt5Agg') - _mpl.rcParams['font.family'] = 'sans-serif' - _mpl.rcParams['font.size'] = 12 - import matplotlib.pyplot as _plt - - _calib_dict = {} - _calib_dict['n_pix'] = 1600 - _calib_dict['ctr_wl'] = 730.0 - _calib_dict['ctr_wl0'] = 730.0 - _calib_dict['probe'] = 771.461 - _calib_dict['units'] = 'nm' - _calib_dict['a_vec'] = (-0.167740721307557, 863.8736708961577) # slope, intercept - - _wl_vec, _units_wl = calib_pix_wl(_calib_dict) - _wn_vec, _units_wn = calib_pix_wn(_calib_dict) - _plt.plot(_wl_vec, _wn_vec) - _plt.xlabel('Wavelength ({})'.format(_units_wl)) - _plt.ylabel('Wavenumber ({})'.format(_units_wn)) - _plt.title('Wavenumber vs Wavelength') - _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/data/hsi.html b/docs/build/html/_modules/crikit/data/hsi.html deleted file mode 100644 index 29f9291..0000000 --- a/docs/build/html/_modules/crikit/data/hsi.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - - - - - - crikit.data.hsi — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.data.hsi

-"""
-Hyperspectral imagery (hsi) class
-
-Created on Tue Apr 12 13:06:30 2016
-
-@author: chc
-"""
-
-import numpy as _np
-import copy as _copy
-
-from crikit.data.frequency import Frequency as _Frequency
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.replicate import Replicate as _Replicate
-
-__all__ = ['Hsi']
-
-
[docs]class Hsi(_Spectrum): - """ - Hyperspectral imagery class - - Parameters - ---------- - data : 3D ndarray [y_pix, x_pix, f_pix] - HSI image - - mask : 3D ndarray (int) [y_pix, x_pix, f_pix] - 0,1 mask with 1 is a usable pixel and 0 is not - - freq : crikit.data.frequency.Frequency instance - Frequency [wavelength, wavenumber] object (i.e., the independent \ - variable) - - label : str - Image label (i.e., a string describing what the image is) - - units : str - Units of image (e.g., intensity) - - x_rep : crikit.data.replicate.Replicate instance, Not implemented yet - x-axis spatial object - - y_rep : crikit.data.replicate.Replicate instance, Not implemented yet - x-axis spatial object - - x : 1D ndarray - x-axis spatial vector - - y : 1D ndarray - y-axis spatial vector - - meta : dict - Meta-data dictionary - - Attributes - ---------- - data_imag_over_real : ndarray (3D) - If data is complex, return the imaginary portion - - data_real_over_imag : ndarray (3D) - If data is complex, return the real portion - - shape : tuple, read-only - Shape of data - - size : int, read-only - Size of data (i.e., total number of entries) - - Methods - ------- - mean : 1D ndarray - Mean spectrum. If extent [a,b] is provided, calculate mean over that\ - inclusive region. - - std : 1D ndarray - Standard deviation of spectrum. If extent [a,b] is provided, calculate standard\ - deviation over that inclusive region. - - subtract : 3D ndarray or None - Subtract spectrum or object - - Notes - ----- - * freq object contains some useful parameters such as op_range_\* and \ - plot_range_\*, which define spectral regions-of-interest. (It's debatable \ - as to whether those parameters should be in Frequency or Spectrum classes) - - """ - - def __init__(self, data=None, freq=None, x=None, y=None, x_rep=None, - y_rep=None, label=None, units=None, meta=None): - - super().__init__(data, freq, label, units, meta) - self._x_rep = _Replicate() - self._y_rep = _Replicate() - self._mask = None - - self._x_rep = _Replicate(data=x) - self._y_rep = _Replicate(data=y) - - if x is None and x_rep is not None: - self.x_rep = _copy.deepcopy(x_rep) - if y is None and y_rep is not None: - self.y_rep = _copy.deepcopy(y_rep) - - @property - def mask(self): - return self._mask - - @property - def x_rep(self): - return self._x_rep - - @x_rep.setter - def x_rep(self, value): - if isinstance(value, _Replicate): - self._x_rep = value - elif isinstance(value, _np.ndarray): - self._x_rep.data = value - - @property - def y_rep(self): - return self._y_rep - - @property - def x(self): - return self._x_rep.data - - @x.setter - def x(self, value): - self._x_rep.data = value - - @property - def y(self): - return self._y_rep.data - - @y.setter - def y(self, value): - self._y_rep.data = value - - - @y_rep.setter - def y_rep(self, value): - if isinstance(value, _Replicate): - self._y_rep = value - elif isinstance(value, _np.ndarray): - self._y_rep.data = value - - @property - def data(self): - return self._data - - @data.setter - def data(self, value): - if isinstance(value, _np.ndarray): - if value.ndim == 3: - if self.freq is None or self.freq.op_list_pix is None: - self._data = value - self._mask = _np.ones((self._data.shape[0], - self._data.shape[1]), - dtype=_np.int) - else: - if value.shape[-1] == self.freq.op_range_pix.size: - temp = _np.zeros((self._data.shape),dtype=value.dtype) - temp[:,:,self.freq.op_range_pix] = value - self._data = temp - self._mask = _np.ones((self._data.shape[0], - self._data.shape[1]), - dtype=_np.int) - elif value.shape[-1] == self._data.shape[-1]: - self._data = value - self._mask = _np.ones((self._data.shape[0], - self._data.shape[1]), - dtype=_np.int) - else: - #raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) - raise TypeError('pre-data: {}, value: {}'.format(self._data.shape,value.shape)) - else: - raise TypeError('data must be 3D') - else: - print('Assigning non-ndarray to data. Not shape checking') - self._data = value - -
[docs] def check(self): - """ - Check x, y, and freq to make sure the dimensions agree with data - """ - if self._data is None: - print('Hsi check: data is None, not checking') - else: - if self._x_rep._data is None: - self._x_rep._data = _np.arange(self.shape[1]) - self._x_rep._label = 'X' - self._x_rep._units = 'pix' - print('Hsi check: setting x to pixels') - elif self._x_rep._data.size != self._data.shape[1]: - self._x_rep = _Replicate() - self._x_rep._data = _np.arange(self.shape[1]) - self._x_rep._label = 'X' - self._x_rep._units = 'pix' - print('Hsi check: setting x to pixels') - - if self._y_rep._data is None: - self._y_rep._data = _np.arange(self.shape[0]) - self._y_rep._label = 'Y' - self._y_rep._units = 'pix' - print('Hsi check: setting y to pixels') - elif self._y_rep._data.size != self._data.shape[0]: - self._y_rep = _Replicate() - self._y_rep._data = _np.arange(self.shape[0]) - self._y_rep._label = 'Y' - self._y_rep._units = 'pix' - print('Hsi check: setting y to pixels') - - if self.freq._data is None: - self.freq._data = _np.arange(self.shape[-1]) - self.freq._label = 'Frequency' - self.freq._units = 'pix' - print('Hsi check: setting freq to pixels') - elif self.freq._data.size != self._data.shape[-1]: - self.freq = _Frequency() - self.freq._data = _np.arange(self.shape[-1]) - print('Hsi check: setting freq to pixels') - return None
- -
[docs] def subtract(self, spectra, overwrite=True): - """ - Subtract spectrum from data - """ - # Order IS important - if isinstance(spectra, Hsi): - if overwrite: - self.data -= spectra.data - return None - else: - return self.data - spectra.data - elif isinstance(spectra, _Spectrum): - if overwrite: - self.data -= spectra.data[None,None,:] - return None - else: - return self.data - spectra.data - elif isinstance(spectra, _np.ndarray): - if spectra.shape == self.data.shape: - if overwrite: - self.data -= spectra - return None - else: - return self.data - spectra - else: - if overwrite: - self.data -= spectra[None,None,:] - return None - else: - return self.data - spectra[None,None,:]
- -
[docs] def get_rand_spectra(self, num, pt_sz=1, quads=False, full=False): - - mlen, nlen, freqlen = self.data.shape - - if quads: - num_spectra = num + 5 - else: - num_spectra = num - - if _np.iscomplexobj(self.data): - dtype = _np.complex - else: - dtype = _np.float - - temp = _np.zeros((num_spectra, self.data.shape[-1]), dtype=dtype) - - quad_mid_row = int(_np.round(mlen/2)) - quad_mid_col = int(_np.round(nlen/2)) - center_row = (int(_np.round(mlen/3)), int(_np.round(2*mlen/3))) - center_col = (int(_np.round(nlen/3)), int(_np.round(2*nlen/3))) - - start_count = 0 - if quads: - # QUADS - # Bottom-left - temp[0, :] = _np.mean(self.data[0:quad_mid_row, 0:quad_mid_col, :], axis=(0, 1)) - - # Upper-left - temp[1, :] = _np.mean(self.data[0:quad_mid_row, quad_mid_col+1::, :], axis=(0, 1)) - - # Upper-right - temp[2, :] = _np.mean(self.data[quad_mid_row+1::, quad_mid_col+1::, :], axis=(0, 1)) - - # Bottom-right - temp[3, :] = _np.mean(self.data[quad_mid_row+1::, 0:quad_mid_col, :], axis=(0, 1)) - - # Center - temp[4, :] = _np.mean(self.data[center_row[0]:center_row[1], center_col[0]:center_col[1], :], axis=(0, 1)) - - start_count += 5 - else: - pass - - rand_rows = ((mlen-pt_sz-1)*_np.random.rand(num_spectra)).astype(int) - rand_cols = ((nlen-pt_sz-1)*_np.random.rand(num_spectra)).astype(int) - - for count in _np.arange(start_count,num_spectra): - if pt_sz == 1: - temp[count, :] = _np.squeeze(self.data[rand_rows[count-start_count], - rand_cols[count-start_count]]) - else: - - rows = [rand_rows[count-start_count]-(pt_sz-1), - rand_rows[count-start_count]+pt_sz] - cols = [rand_cols[count-start_count]-(pt_sz-1), - rand_cols[count-start_count]+pt_sz] - - if rows[0] < 0: - rows[0] = 0 - if rows[1] >= mlen: - rows[1] = mlen-1 - if cols[0] < 0: - cols[0] = 0 - if cols[1] >= nlen: - cols[1] = nlen-1 - - if cols[0] == cols[1] or rows[0] == rows[1]: - pass - else: - temp[count,:] = _np.squeeze(_np.mean(self.data[rows[0]:rows[1], cols[0]:cols[1], :], axis=(0, 1))) - - if (not full) and (self.freq.data is not None): - temp = temp[..., self.freq.op_range_pix] - - return temp
- - def __sub__(self, spectrum): - return self.subtract(spectrum, overwrite=False)
- -if __name__ == '__main__': # pragma: no cover - - x = _np.linspace(0,100,10) - y = _np.linspace(0,100,10) - freq = _np.arange(20) - data = _np.random.rand(10,10,20) - - - hs = Hsi(data=data, freq=freq, x=x, y=y) - print(hs.shape) - print(isinstance(hs, _Spectrum)) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/data/replicate.html b/docs/build/html/_modules/crikit/data/replicate.html deleted file mode 100644 index 32f60d4..0000000 --- a/docs/build/html/_modules/crikit/data/replicate.html +++ /dev/null @@ -1,416 +0,0 @@ - - - - - - - - - - - crikit.data.replicate — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.data.replicate
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.data.replicate

-"""
-Replicate class used for things such as repetitive measurements or even spatial \
-vectors (e.g., x and y)
-
-Created on Tue Apr 12 11:42:56 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-__all__ = ['Replicate']
-
-
[docs]class Replicate: - """ - Replicate class - - Attributes - ---------- - data : 1D ndarray [size] - Replicate data - - calib : list [(start), stop, (step size)] - Calibration descriptor. See Note. - - units : str - Units of replicate data - - size : int, read-only - - Methods - ------- - update_calib_from_data - Calculate and set calib parameter from data - - update_data_from_calib - Calculate and set data from calib parameter - - calib_data_agree - Return bool as to whether data and that derived from calib agree - - Notes - ----- - * input to calib can be a list or tuple or 1D ndarray or int or float - - Setting calib can take up to 3 entries : - * 1 entry: stop = entry; start = 0, step size = 1 - * 2 entries: start = entry[0], stop = entry[1], step size = 1 - * 3 entries: [start, stop, step size] - - """ - - - def __init__(self, data=None, calib=None, units=None, label=None): - self._data = None - self._calib = None - self._units = None - self._label = None - - if data is not None: - self.data = data - if calib is not None: - self.calib = calib - if units is not None: - self.units = units - if label is not None: - self.label = label - - @property - def data(self): - return self._data - - @data.setter - def data(self, value): - if isinstance(value, _np.ndarray): - if value.ndim == 1: - self._data = value - else: - raise TypeError('data must be 1D ndarray') - elif value is None: - self._data = None - else: - raise TypeError('data must be 1D ndarray') - - @property - def size(self): - return self._data.size - - @property - def calib(self): - return self._calib - - @calib.setter - def calib(self, value): - if isinstance(value, _np.ndarray) or isinstance(value, list) or isinstance(value, tuple): - if len(value) == 3: - self._calib = list(value) - elif len(value) == 2: - temp = list(value) - temp.append(1) - self._calib = temp - elif len(value) == 1: - temp = [0] - temp.append(value[0]) - temp.append(1) - self._calib = temp - else: - raise TypeError('calib should have 1-3 components: [(start), stop, (step size)]') - elif isinstance(value, int) or isinstance(value, float): - temp = [0] - temp.append(value) - temp.append(1) - self._calib = temp - else: - raise TypeError('calib should be an int or float [stop]; or a \ - 1D ndarray, tuple, or list with 1-3 entires: [start, stop, step size]') - - @property - def units(self): - return self._units - - @units.setter - def units(self, value): - if isinstance(value, str) | (value is None): - self._units = value - else: - raise TypeError('units should be of type str') - - @property - def label(self): - return self._label - - @label.setter - def label(self, value): - if isinstance(value, str) | (value is None): - self._label = value - else: - raise TypeError('label should be of type str') - -
[docs] def update_data_from_calib(self): - """ - Calculate and set data from calib parameter - """ - if self._calib is not None: - self.data = _np.arange(self._calib[0],self._calib[1], self._calib[2]) - else: - raise TypeError('calib is not set')
- -
[docs] def update_calib_from_data(self): - """ - Calculate and set calib parameter from data. Note: assumes uniform \ - spacing of data. - """ - if self._data is not None: - delta = self._data[1] - self._data[0] - self.calib = [self._data[0], self._data[-1]+delta, delta] - else: - raise TypeError('data is not set')
- -
[docs] def calib_data_agree(self): - if self._data is None: - raise TypeError('data not set') - if self._calib is None: - raise TypeError('calib not set') - - temp = _np.arange(self._calib[0],self._calib[1],self._calib[2]) - - if temp.size != self._data.size: - return False - else: - return _np.allclose(temp, self._data)
- -if __name__ == '__main__': # pragma: no cover - - start = 0 - stop = 10 - step_size = .1 - - x = _np.arange(start, stop, step_size) - - rep = Replicate(data=x,calib=[start, stop, step_size]) - - print('Calib and data agree: {}'.format(rep.calib_data_agree())) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/data/spectra.html b/docs/build/html/_modules/crikit/data/spectra.html deleted file mode 100644 index 70899a6..0000000 --- a/docs/build/html/_modules/crikit/data/spectra.html +++ /dev/null @@ -1,392 +0,0 @@ - - - - - - - - - - - crikit.data.spectra — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.data.spectra

-"""
-Spectra class and function (very similar to Spetcrum except this deals with
-multiple entries)
-
-"""
-
-import numpy as _np
-import copy as _copy
-
-from crikit.data.frequency import Frequency as _Frequency
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.replicate import Replicate as _Replicate
-
-__all__ = ['Spectra']
-
-
[docs]class Spectra(_Spectrum): - """ - Spectra class - - Attributes - ---------- - data : 2D ndarray [n_pix, f_pix] - Spectra. Note: input can be a ndarray of any dimension: it will be \ - CONVERTED to [n_pix, f_pix] shape, assuming that shape[-1] is the f_pix \ - long. - - freq : crikit.data.frequency.Frequency instance - Frequency [wavelength, wavenumber] object (i.e., the independent \ - variable) - - label : str - Spectrum label (i.e., a string describing what the spectrum is) - - units : str - Units of spectrum - - reps : crikit.data.replicate.Replicate instance, Not implemented yet - Object describing the meaning of multiple spectra (i.e., the physical \ - meaning of n_pix). - - meta : dict - Meta-data dictionary - - shape : tuple, read-only - Shape of data - - n_pix : int, read-only - Size of data's replicate/spectral number axis. - - Methods - ------- - mean : 1D ndarray - Mean spectrum. If extent [a,b] is provided, calculate mean over that\ - inclusive region. - - std : 1D ndarray - Standard deviation of spectrum. If extent [a,b] is provided, calculate standard\ - deviation over that inclusive region. - - subtract : 2D ndarray or None - Subtract spectrum or object - - Notes - ----- - * freq object contains some useful parameters such as op_range_\* and \ - plot_range_\*, which define spectral regions-of-interest. (It's debatable \ - as to whether those parameters should be in Frequency or Spectrum classes) - - """ - - def __init__(self, data=None, freq=None, label=None, units=None, meta=None): - super().__init__(data, freq, label, units, meta) - self._reps = _Replicate() - - @property - def data(self): - return self._data - - @data.setter - def data(self, value): - if isinstance(value, _np.ndarray): - if self.freq.data is None or self.freq.op_list_pix is None: - if value.ndim == 1: - print('Spectra: converting data input from 1D to 2D ndarray') - self._data = value[None,:] - elif value.ndim == 2: - self._data = value - else: - print('Spectra: converting data input from {}D to 2D ndarray'.format(value.ndim)) - f_sh = value.shape[-1] - self._data = value.reshape((-1, f_sh)) - else: - if value.shape[-1] == self.freq.op_range_pix.size: - temp = _np.zeros((self._data.shape),dtype=value.dtype) - temp[:,self.freq.op_range_pix] = value - self._data = temp - else: - raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) - else: - print('Assigning non-ndarray to data. Not shape checking') - self._data = value - - @property - def n_pix(self): - return self._data.shape[0] - - @property - def reps(self): - return self._reps - - @reps.setter - def reps(self, value): - if isinstance(value, _Replicate): - self._reps = value - elif isinstance(value, _np.ndarray): - self._reps.data = value - -
[docs] def subtract(self, spectra, overwrite=True): - """ - Subtract spectrum from data - """ - # Order IS important - if isinstance(spectra, Spectra): - if overwrite: - self.data -= spectra.data - return None - else: - return self.data - spectra.data - elif isinstance(spectra, _Spectrum): - if overwrite: - self.data -= spectra.data[None,:] - return None - else: - return self.data - spectra.data[None,:] - elif isinstance(spectra, _np.ndarray): - if spectra.shape == self.data.shape: - if overwrite: - self.data -= spectra - return None - else: - return self.data - spectra - else: - if overwrite: - self.data -= spectra[None,:] - return None - else: - return self.data - spectra[None,:]
- - def __sub__(self, spectrum): - return self.subtract(spectrum, overwrite=False)
- -if __name__ == '__main__': # pragma: no cover - sp = Spectra() - print(sp.__dict__) - print('Subclass? : {}'.format(issubclass(Spectra,_Spectrum))) - print('Instance of Spectra? : {}'.format(isinstance(sp,Spectra))) - print('Instance of Spectrum? : {}'.format(isinstance(sp,_Spectrum))) - print('Type(sp) == Spectrum? : {}'.format(type(sp)==_Spectrum)) - print('Type(sp) == Spectra? : {}'.format(type(sp)==Spectra)) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/data/spectrum.html b/docs/build/html/_modules/crikit/data/spectrum.html deleted file mode 100644 index 3508f17..0000000 --- a/docs/build/html/_modules/crikit/data/spectrum.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - - - - - - crikit.data.spectrum — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.data.spectrum
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.data.spectrum

-"""
-Spectrum class and function
-
-"""
-
-import numpy as _np
-import copy as _copy
-
-from crikit.data.frequency import Frequency as _Frequency
-
-__all__ = ['Spectrum']
-
-
[docs]class Spectrum: - """ - Spectrum class - - Attributes - ---------- - data : 1D ndarray [f_pix] - Spectrum - - freq : crikit.data.Frequency instance - Frequency [wavelength, wavenumber] object (i.e., the independent \ - variable) - - label : str - Spectrum label (i.e., a string describing what the spectrum is) - - units : str - Units of spectrum - - meta : dict - Meta-data dictionary - - f_pix : int, read-only - Size of data. Note: this matches the size of data and does NOT check \ - the size of freq.freq_vec. - - ndim : int, read-only - Number of data dimensions - - shape : tuple, read-only - Shape of data - - size : int, read-only - Size of data (i.e., total number of entries) - - Methods - ------- - mean : int - Mean value. If extent [a,b] is provided, calculate mean over that\ - inclusive region. - - std : int - Standard deviation. If extent [a,b] is provided, calculate standard\ - deviation over that inclusive region. - - subtract : 1D ndarray or None - Subtract spectrum or object - - Notes - ----- - * freq object contains some useful parameters such as op_range_\* and \ - plot_range_\*, which define spectral regions-of-interest. (It's debatable \ - as to whether those parameters should be in Frequency or Spectrum classes) - - """ - - def __init__(self, data=None, freq=None, label=None, units=None, meta=None): - - self._data = None - self._freq = _Frequency() - self._label = None - self._units = None - self._meta = {} - - if data is not None: - self.data = _copy.deepcopy(data) - if freq is not None: - self.freq = _copy.deepcopy(freq) - else: - self.freq = _Frequency() - if label is not None: - self.label = _copy.deepcopy(label) - if units is not None: - self.units = _copy.deepcopy(units) - if meta is not None: - self._meta = _copy.deepcopy(meta) - - @property - def data(self): - return self._data - - @data.setter - def data(self, value): - if isinstance(value, _np.ndarray): - if value.ndim == 1: - if self.freq is not None and self.freq.op_list_pix is not None: - if value.shape[-1] == self.freq.op_range_pix.size: - temp = _np.zeros((self.freq.size),dtype=value.dtype) - temp[self.freq.op_range_pix] = value - self._data = temp - else: - raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) - else: - self._data = value - else: - raise TypeError('data must be a 1D ndarray') - else: - raise TypeError('data must be a 1D ndarray') - - @property - def data_imag_over_real(self): - if _np.iscomplexobj(self._data): - if isinstance(self._data, _np.ndarray): - return self._data.imag - else: - return _np.imag(self._data) - else: - return self._data - - @property - def data_real_over_imag(self): - if _np.iscomplexobj(self._data): - if isinstance(self._data, _np.ndarray): - return self._data.real - else: - return _np.real(self._data) - else: - return self._data - - @property - def freq(self): - return self._freq - - @freq.setter - def freq(self, value): - if isinstance(value, _Frequency): - self._freq = value - elif isinstance(value, _np.ndarray): - self.freq = _Frequency(data=value) - else: - raise TypeError('freq must be of type crikit.data.Frequency') - - @property - def f(self): - """ - Convenience attribute: return frequency vector within operating (op) \ - range - """ - return self.freq.op_range_freq - - @property - def f_full(self): - """ - Convenience attribute: return full frequency vector - """ - return self.freq.data - - @property - def units(self): - return self._units - - @units.setter - def units(self, value): - if isinstance(value, str): - self._units = value - else: - raise TypeError('units must be of type str') - - @property - def label(self): - return self._label - - @label.setter - def label(self, value): - if isinstance(value, str): - self._label = value - else: - raise TypeError('label must be of type str') - - @property - def meta(self): - temp_dict = self._meta.copy() - - if self.freq.calib is not None: - try: - calib_dict = {} - calib_prefix = 'Calib.' - - calib_dict[calib_prefix + 'a_vec'] = self.freq.calib['a_vec'] - calib_dict[calib_prefix + 'ctr_wl'] = self.freq.calib['ctr_wl'] - calib_dict[calib_prefix + 'ctr_wl0'] = self.freq.calib['ctr_wl0'] - calib_dict[calib_prefix + 'n_pix'] = self.freq.calib['n_pix'] - calib_dict[calib_prefix + 'probe'] = self.freq.calib['probe'] - - try: # Doesn't really matter if we have the units - calib_dict[calib_prefix + 'units'] = self.freq.calib['units'] - except: - pass - - except: - print('Could not get calibration information') - else: - temp_dict.update(calib_dict) - - if self.freq.calib_orig is not None: - try: - calib_dict = {} - calib_prefix = 'CalibOrig.' - - calib_dict[calib_prefix + 'a_vec'] = self.freq.calib_orig['a_vec'] - calib_dict[calib_prefix + 'ctr_wl'] = self.freq.calib_orig['ctr_wl'] - calib_dict[calib_prefix + 'ctr_wl0'] = self.freq.calib_orig['ctr_wl0'] - calib_dict[calib_prefix + 'n_pix'] = self.freq.calib_orig['n_pix'] - calib_dict[calib_prefix + 'probe'] = self.freq.calib_orig['probe'] - - try: # Doesn't really matter if we have the units - calib_dict[calib_prefix + 'units'] = self.freq.calib_orig['units'] - except: - pass - - except: - print('Could not get calibration information') - else: - temp_dict.update(calib_dict) - - # return self._meta - return temp_dict - - @meta.setter - def meta(self, value): - if isinstance(value, dict): - self._meta = value - else: - raise TypeError('meta must be of type dict') - - @property - def f_pix(self): - if self._data is not None: - return self._data.shape[-1] - - @property - def ndim(self): - if self._data is None: - return None - elif isinstance(self._data, _np.ndarray): - return self._data.ndim - else: - return len(self._data.shape) - - @property - def shape(self): - if self._data is None: - return None - else: - return self._data.shape - - @property - def size(self): - if self._data is None: - return None - else: - return self._data.size - -
[docs] def mean(self, extent=None, over_space=True): - """ - Return mean spectrum (or mean over extent [list with 2 elements]). If\ - over_space is False, returns reps-number of mean spectra - """ - if self._data is None: - return None - - ndim = len(self._data.shape) - - if ndim == 1: - if isinstance(self._data, _np.ndarray): - return self._data.mean() - else: - return _np.mean(self._data) - - if ndim > 1: - if over_space == True: - axes = tuple(_np.arange(ndim-1)) - else: - axes = -1 - - if isinstance(self._data, _np.ndarray): - if extent is None: - return self._data.mean(axis=axes) - else: - return self._data[:,extent[0]:extent[1]+1].mean(axis=axes) - else: - if extent is None: - return _np.mean(self._data, axis=axes) - else: - return _np.mean(self._data[:,extent[0]:extent[1]+1], - axis=axes)
- -
[docs] def std(self, extent=None, over_space=True): - """ - Return standard deviation (std) spectrum (or std over extent - [list with 2 elements]). If over_space is False, reps (or reps x reps) - number of std's. - """ - if self._data is None: - return None - - ndim = len(self._data.shape) - - if ndim == 1: - if isinstance(self._data, _np.ndarray): - return self._data.std() - else: - return _np.std(self._data) - - if ndim > 1: - if over_space == True: - axes = tuple(_np.arange(ndim-1)) - else: - axes = -1 - - if isinstance(self._data, _np.ndarray): - if extent is None: - return self._data.std(axis=axes) - else: - return self._data[:,extent[0]:extent[1]+1].std(axis=axes) - else: - if extent is None: - return _np.std(self._data, axis=axes) - else: - return _np.std(self._data[:,extent[0]:extent[1]+1], - axis=axes)
- -
[docs] def subtract(self, spectrum, overwrite=True): - """ - Subtract spectrum from data - """ - if isinstance(spectrum, Spectrum): - if overwrite: - self.data -= spectrum.data - return None - else: - return self.data - spectrum.data - elif isinstance(spectrum, _np.ndarray): - if overwrite: - self.data -= spectrum - return None - else: - return self.data - spectrum
- - def __sub__(self, spectrum): - return self.subtract(spectrum, overwrite=False)
- - -if __name__ == '__main__': # pragma: no cover - import timeit as _timeit - - N = 10001 - wn = _np.linspace(500,3000,N) - sp = Spectrum(data=_np.random.rand(N) + 1j*_np.random.rand(N), freq=wn) - - tmr = _timeit.default_timer() - sp.data[200:500] - tmr -= _timeit.default_timer() - print(-tmr) - - tmr = _timeit.default_timer() - locs = _np.arange(sp.freq.get_index_of_closest_freq(500), - sp.freq.get_index_of_closest_freq(600)) - sp.data_imag_over_real[locs] - tmr -= _timeit.default_timer() - print(-tmr) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/datasets/model.html b/docs/build/html/_modules/crikit/datasets/model.html deleted file mode 100644 index 0393de4..0000000 --- a/docs/build/html/_modules/crikit/datasets/model.html +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - - - - - - crikit.datasets.model — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.datasets.model
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.datasets.model

-import numpy as _np
-from pkgutil import get_data as _get_data
-from io import BytesIO as _BytesIO
-import copy as _copy
-
-
[docs]class Model: - """ - Model class - - Parameters - ---------- - subsample : int - Subsample the spatial dimenension (ie x[::subsample], y[::subsample]) - - dtype : numpy dtype - Dtype to set final image - - """ - _M = 300 - _N = 300 - - def __init__(self, subsample=1, dtype=_np.complex): - self.n_layers = 7 # Number of components - self.img_shape = [300, 300] # Spaital imaging shape - - self.x = _np.linspace(1,199,self._N) - self.y = _np.linspace(1,199,self._M) - - if subsample > 1: - self.x = self.x[::subsample] - self.y = self.y[::subsample] - self.img_shape = [self.y.size, self.x.size] - - self.dtype = dtype - - # Order of spectral array - # A: amplitude - # Omega: center frequency - # Gamma: peak frequency width - self.spec_order = ['Omega','A','Gamma'] - - # Filename prefix for concentration images - self.__conc_img_prefix = 'Chem_Conc_' - - # Filename prefix for spectral array - self.__spec_prefix = 'Chem_Spec_' - - self.layers = _np.zeros(self.img_shape + [self.n_layers]) - self.spec_list = [] - self.n_peak_list = [] - - # Final hyperspectral image - self.hsi = None - - # Spectra array - self.spectra = None - - # Frequency vector - # For convenicence self.f or self.wn will work - self._f = None - - try: - for num in range(self.n_layers): - gd_layer = _get_data('crikit.datasets', '{}{}{}'.format(self.__conc_img_prefix, - num, '.csv')) - self.layers[:,:,num] = _np.genfromtxt(_BytesIO(gd_layer), delimiter=',')[::subsample,::subsample] - - gd_spec = _get_data('crikit.datasets', '{}{}{}'.format(self.__spec_prefix, - num, '.csv')) - self.spec_list.append(_np.genfromtxt(_BytesIO(gd_spec), delimiter=',')) - except: - print('Failed to import model layer and/or spectral information') - else: - print('Model spatial size: {}'.format(self.img_shape)) - print('Model components/layers: {}'.format(self.n_layers)) - - @property - def f(self): - return self._f - - @property - def wn(self): - return self._f - - @property - def hsi_i(self): - """Return imag{hsi}""" - return self.hsi.imag - - @property - def hsi_r(self): - """Return real{hsi}""" - return self.hsi.real - -
[docs] def make_spectra(self, f): - """ - Parameters - ---------- - f : ndarray (1D) - Frequency vector - """ - self._f = f - - a_loc = self.spec_order.index('A') - o_loc = self.spec_order.index('Omega') - g_loc = self.spec_order.index('Gamma') - - self.spectra = _np.zeros((self.n_layers, f.size), dtype=self.dtype) - - try: - for num, arr in enumerate(self.spec_list): - omega_vec = arr[:,o_loc] - a_vec = arr[:,a_loc] - gamma_vec = arr[:,g_loc] - self.n_peak_list.append(a_vec.size) - - self.spectra[num, :] = _np.sum(a_vec[:,None] / (omega_vec [:,None] - f[None,:] - 1j*gamma_vec[:,None]), axis=0) - except: - print('Failed to make model spectra') - else: - print('Model spectral size: {}'.format(self.f.size))
- -
[docs] def make_hsi(self, f=None): - """ - Make the HSI image - - Parameters - ---------- - f : ndarray (1D) - Frequency vector - """ - try: - if f is not None: - self.make_spectra(f=f) - - # self.hsi = _np.zeros(self.img_shape + [self._f.size], dtype=self.dtype) - self.hsi = _np.dot(self.layers, self.spectra) - print('Model HSI shape: {}'.format(self.hsi.shape)) - except: - print('Faled to make model HSI')
- -#%% -if __name__ == '__main__': - model = Model(subsample=4) - print('Layer shape: {}'.format(model.layers.shape)) - - wn = _np.linspace(500, 3400, 100) - model.make_hsi(f=wn) - - print('Model shape: {}'.format(model.hsi.shape)) - print('Model is complex: {}'.format(_np.iscomplexobj(model.hsi))) - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/io/csv_nist.html b/docs/build/html/_modules/crikit/io/csv_nist.html deleted file mode 100644 index 476ff2c..0000000 --- a/docs/build/html/_modules/crikit/io/csv_nist.html +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - crikit.io.csv_nist — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.io.csv_nist

-"""
-Created on Wed Sep  7 12:36:36 2016
-
-@author: chc
-"""
-
-import os as _os
-import csv as _csv
-import numpy as _np
-import copy as _copy
-
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.spectra import Spectra as _Spectra
-from crikit.data.hsi import Hsi as _Hsi
-
-from configparser import ConfigParser as _ConfigParser
-#
-#__all__ = ['hdf_dset_list_rep','hdf_is_valid_dsets',
-#           'hdf_attr_to_dict','hdf_import_data']
-#
-
-
[docs]def csv_nist_import_data(pth, filename_header, filename_data, - output_cls_instance=None): - """ - Import dataset(s) from HDF file - - Parameters - ---------- - pth : str - Path - - filename_header : str - File name of header - - filename_data : str - File name of data - - output_cls_instance : crikit.data.spectrum.Spectrum (or subclass) - Spectrum class (or sub) object - - Returns - ------- - Success : bool - Success of import - Data, Meta : list (ndarray, dict) - If output_cls_instance is None and import is successful, will \ - return the data from dset_list and associated meta data. - - """ - # Join path and filename in an os-independant way - pfname_header = _os.path.normpath(_os.path.join(pth, filename_header)) - pfname_data = _os.path.normpath(_os.path.join(pth, filename_data)) - - valid_import_locs = 0 - - try: - with open(pfname_header,'r') as _: - pass - except: - print('Invalid header filename') - else: - valid_import_locs += 1 - - try: - with open(pfname_data,'r') as _: - pass - except: - print('Invalid data filename') - else: - valid_import_locs += 1 - - if valid_import_locs != 2: - return False - else: - try: - config = _ConfigParser() - config.read(pfname_header) - - # Frequency calibration - probe = config.getfloat('Frequency Calibration','probe(nm)') - wl1 = config.getfloat('Frequency Calibration','wavelength1(nm)') - wl2 = config.getfloat('Frequency Calibration','wavelength2(nm)') - pixel1 = config.getint('Frequency Calibration','pixel1') - pixel2 = config.getint('Frequency Calibration','pixel2') - f_begin = config.getfloat('Frequency Calibration','freq index begin') - f_size = config.getint('Frequency Calibration','freq index length') - f_min = config.getfloat('Frequency Calibration','freq Min') - f_max = config.getfloat('Frequency Calibration','freq Max') - - pix = _np.linspace(pixel1,pixel2,f_size) - wl = _np.linspace(wl1,wl2,f_size) - wn = 1e7*(1/wl - 1/probe) - - # Config is apparently backwards so flip order - pix = _np.flipud(pix) - wl = _np.flipud(wl) - wn = _np.flipud(wn) - - # Frequency calibration stuff - wl_center = wl.mean() - wl_slope, wl_intercept = _np.polyfit(pix, wl,1) - - - # Get data - with open(pfname_data,'r') as csvfile: - reader = _csv.reader(csvfile, delimiter='\t') - data = [] - for count in reader: - data.append(count) - data = _np.array(data).astype(float) - - if (data.shape[-1] == 3) | (data.shape[-1] == 2): # Spectra - print('Spectra') - wn = data[:,0] - temp = data[:,-1] - if data.shape[-1] == 3: - wl = data[:,1] - data = temp - - # Meta data - attr = {} - for each_section in config.sections(): - #print('Section: {}'.format(each_section)) - for (each_key, each_val) in config.items(each_section): - k = each_section + '.' + each_key - try: # int - v = int(each_val) - #print('Integer') - except: - try: # float - v = float(each_val) - except: # string - v = str.strip(each_val,'"') - #print('{}.{}: {}'.format(each_section,each_key, v)) - attr.update({k:v}) - - # Add in frequency calibration info - attr['Frequency Calibration.Slope'] = wl_slope - attr['Frequency Calibration.Intercept'] = wl_intercept - attr['Frequency Calibration.CenterWavelength'] = wl_center - - # Convert meta keys to match those of HDF5 version - # Note: will not overwrite, just add-to - # Note: Subject to change - - output_cls_instance.data = data - output_cls_instance.meta = attr - return True - - else: - data = data.reshape((data.shape[0],-1,f_size)) - # Spatial Info - x_start = config.getfloat('X scan Parameters','X start (um)') - x_steps = config.getint('X scan Parameters','X steps') - x_step_size = config.getfloat('X scan Parameters','X step size (um)') - x = _np.linspace(x_start, x_start + x_step_size * (x_steps-1), x_steps) - - try: # Exists a typo in header info in LabView program - y_start = config.getfloat('Y scan Paramters','Y start (um)') - y_steps = config.getint('Y scan Paramters','Y steps') - y_step_size = config.getfloat('Y scan Paramters','Y step size (um)') - y = _np.linspace(y_start, y_start + y_step_size * (y_steps-1), y_steps) - except: # In case typo is corrected in the future - y_start = config.getfloat('Y scan Parameters','Y start (um)') - y_steps = config.getint('Y scan Parameters','Y steps') - y_step_size = config.getfloat('Y scan Parameters','Y step size (um)') - y = _np.linspace(y_start, y_start + y_step_size * (y_steps-1), y_steps) - - # Meta data - attr = {} - for each_section in config.sections(): - #print('Section: {}'.format(each_section)) - for (each_key, each_val) in config.items(each_section): - k = each_section + '.' + each_key - try: # int - v = int(each_val) - #print('Integer') - except: - try: # float - v = float(each_val) - except: # string - v = str.strip(each_val,'"') - #print('{}.{}: {}'.format(each_section,each_key, v)) - attr.update({k:v}) - - # Add in frequency calibration info - attr['Frequency Calibration.Slope'] = wl_slope - attr['Frequency Calibration.Intercept'] = wl_intercept - attr['Frequency Calibration.CenterWavelength'] = wl_center - - # Convert meta keys to match those of HDF5 version - # Note: will not overwrite, just add-to - # Note: Subject to change - try: - ax1 = attr['Image data.1st axis'] - - if ax1 == 0: - attr['RasterScanParams.FastAxis'] = 'X' - elif ax1 == 1: - attr['RasterScanParams.FastAxis'] = 'Y' - elif ax1 == 2: - attr['RasterScanParams.FastAxis'] = 'Z' - - attr['RasterScanParams.FastAxisStart'] = x_start - attr['RasterScanParams.FastAxisStepSize'] = x_step_size - attr['RasterScanParams.FastAxisSteps'] = x_steps - attr['RasterScanParams.FastAxisStop'] = x[-1] - - ax2 = attr['Image data.2nd axis'] - - if ax2 == 0: - attr['RasterScanParams.SlowAxis'] = 'X' - elif ax2 == 1: - attr['RasterScanParams.SlowAxis'] = 'Y' - elif ax2 == 2: - attr['RasterScanParams.SlowAxis'] = 'Z' - - attr['RasterScanParams.SlowAxisStart'] = y_start - attr['RasterScanParams.SlowAxisStepSize'] = y_step_size - attr['RasterScanParams.SlowAxisSteps'] = y_steps - attr['RasterScanParams.SlowAxisStop'] = y[-1] - - ax3 = attr['Image data.3rd axis'] - - if ax3 == 0: - attr['RasterScanParams.FixedAxis'] = 'X' - elif ax3 == 1: - attr['RasterScanParams.FixedAxis'] = 'Y' - elif ax3 == 2: - attr['RasterScanParams.FixedAxis'] = 'Z' - - # Figure out fixed positions later - - except: - pass - else: - output_cls_instance.data = data - output_cls_instance.meta = attr - return True - - except: - print('Something failed in import')
- -if __name__ == '__main__': - #from crikit.data.spectra import Spectra as _Spectra - - sp = _Spectra() - pth = '../../../Young_150617/' - filename_header = 'SH-03.h' - filename_data = 'base061715_152213_60ms.txt' - - csv_nist_import_data(pth, filename_header, filename_data, - output_cls_instance=sp) - - print(sp.__dict__) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/io/hdf5.html b/docs/build/html/_modules/crikit/io/hdf5.html deleted file mode 100644 index a238c08..0000000 --- a/docs/build/html/_modules/crikit/io/hdf5.html +++ /dev/null @@ -1,586 +0,0 @@ - - - - - - - - - - - crikit.io.hdf5 — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.io.hdf5

-"""
-
-
-
-Created on Mon May 23 10:17:16 2016
-
-@author: chc
-"""
-
-import os as _os
-
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.spectra import Spectra as _Spectra
-from crikit.data.hsi import Hsi as _Hsi
-
-
-import h5py as _h5py
-_h5py.get_config().complex_names = ('Re','Im')
-
-import numpy as _np
-
-__all__ = ['hdf_dset_list_rep','hdf_is_valid_dsets',
-           'hdf_attr_to_dict','hdf_import_data']
-
-
[docs]def hdf_dset_list_rep(prefix,suffixes): - """ - Create a list of dataset names - """ - dset_list = [] - - assert isinstance(prefix,str) - - for sfx in suffixes: - dset_list.append(prefix + str(sfx)) - - return dset_list
- -
[docs]def hdf_is_valid_dsets(pth, filename, dset_list): - """ - Validate file and datasets exist. Return boolean as to whether valid - - """ - - isvalid = False - fileexists = False - - try: - # Join path and filename in an os-independant way - pfname = _os.path.normpath(_os.path.join(pth, filename)) - f = _h5py.File(pfname, 'r') - print('File exists: \'{}\''.format(pfname)) - fileexists = True - except OSError: - print('File does not exist: \'{}\''.format(pfname)) - fileexists = False - else: - if isinstance(dset_list, list): # List of dataset(s) - try: - for count in dset_list: - f[count] - except: - print('dataset: {} is invalid'.format(count)) - else: - print('All datasets are valid') - isvalid = True - elif isinstance(dset_list, str): # Single dataset string name - try: - f[dset_list] - except: - print('dataset {} is invalid'.format(count)) - else: - print('Dataset is valid') - isvalid = True - else: - print('dset_list is unrecognized type') - finally: - if fileexists: - f.close() - - return isvalid
- -def _convert_to_np_dtype(dset): - """ - Given an HDF5 dataset, return the values in a numpy-builtin datatype - - Parameters - ---------- - dset : h5py.Dataset - HDF5 (h5py) dataset - - Returns - ------- - out : numpy.ndarray (dtype = numpy built-in) - - Notes - ----- - The software accounts for big-/little-endianness, and the inability of \ - hdf5 to natively store complex numbers. - - """ - assert isinstance(dset, _h5py.Dataset), 'Input is not of type h5py.Dataset' - # Single datatype - if len(dset.dtype) == 0: - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - if issubclass(converted.dtype.type, _np.integer): # Integer to float - converted = converted.astype(_np.float) - return converted - #Compound datatype of length 2-- assumed ('Re','Im') - elif len(dset.dtype) == 2: - print('Warning: h5py.complex_names set incorrectly using \'{}\' and \'{}\' \ -for Re and Im, respectively'.format(dset.dtype.names[0], dset.dtype.names[1])) - _h5py.get_config().complex_names = (dset.dtype.names[0],dset.dtype.names[1]) - dset = dset.file[dset.name] - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - # Unknown datatype - else: - print('Warning: Unknown datatype. Returning dataset values as is.') - return dset.value - return converted - -
[docs]def hdf_attr_to_dict(attr): - """ - Convert from HDF attributes to valid dict - """ - - try: - output_dict = dict(attr) - except: - output_dict = {} - for count in attr: - try: - output_dict[count] = attr[count] - except: - print('Fail: {}'.format(count)) - - # String in HDF are treated as numpy bytes_ literals - # We want out instance in memeory to have Python Strings - # This does a simple conversion - # Also will check to see if a string is burried in an array - for k in output_dict: - if isinstance(output_dict[k], _np.bytes_): - output_dict[k] = output_dict[k].decode('UTF-8') - elif isinstance(output_dict[k], _np.ndarray): - if output_dict[k].dtype.kind == 'S': # String array - # This is a cute way of taking an array of charcters and merging - # them into a string. If just a single-element array, - # will also return a string - output_dict[k] = ''.join(output_dict[k].astype(_np.str)) - return output_dict
- -
[docs]def hdf_import_data(pth, filename, dset_list, output_cls_instance=None): - """ - Import dataset(s) from HDF file - - Parameters - ---------- - pth : str - Path - - filename : str - File name - - dset_list : list - List of 1 or more datasets - - output_cls_instance : crikit.data.spectrum.Spectrum (or subclass) - Spectrum class (or sub) object - - Returns - ------- - Success : bool - Success of import - Data, Meta : list (ndarray, dict) - If output_cls_instance is None and import is successful, will \ - return the data from dset_list and associated meta data. - - """ - # Join path and filename in an os-independant way - pfname = _os.path.normpath(_os.path.join(pth, filename)) - - if hdf_is_valid_dsets(pth, filename,dset_list) == False: - print('Invalid filename or dataset list') - return False - else: - try: - f = _h5py.File(pfname,'r') - - if type(output_cls_instance) == _Hsi: - print('Type Hsi') - if isinstance(dset_list, str): - output_cls_instance.data = _convert_to_np_dtype(f[dset_list]) - output_cls_instance.meta = hdf_attr_to_dict(f[dset_list].attrs) - elif isinstance(dset_list, list): - if len(dset_list) > 1: - print('Cannot accept more than 1 HSI image at this time') - else: - for num, dname in enumerate(dset_list): - if num == 0: - output_cls_instance.data = _convert_to_np_dtype(f[dname]) - output_cls_instance.meta = hdf_attr_to_dict(f[dname].attrs) - else: - output_cls_instance.data = _np.vstack((output_cls_instance.data, _convert_to_np_dtype(f[dname]))) - ret = True - elif type(output_cls_instance) == _Spectra: - print('Type Spectra') - if isinstance(dset_list,str): - output_cls_instance.data = _convert_to_np_dtype(f[dset_list]) - output_cls_instance.meta = hdf_attr_to_dict(f[dset_list].attrs) - - elif isinstance(dset_list, list): - for num, dname in enumerate(dset_list): - if num == 0: - output_cls_instance.data = _convert_to_np_dtype(f[dname]) - output_cls_instance.meta = hdf_attr_to_dict(f[dname].attrs) - else: - output_cls_instance.data = _np.vstack((output_cls_instance.data, _convert_to_np_dtype(f[dname]))) - ret = True - elif type(output_cls_instance) == _Spectrum: - print('Type Spectrum') - if isinstance(dset_list, str): - output_cls_instance.data = _convert_to_np_dtype(f[dset_list]) - output_cls_instance.meta = hdf_attr_to_dict(f[dset_list].attrs) - elif isinstance(dset_list, list): - if len > 1: - print('Will average spectra into a single spectrum') - else: - for num, dname in enumerate(dset_list): - if num == 0: - output_cls_instance.data = _convert_to_np_dtype(f[dname]) - output_cls_instance.meta = hdf_attr_to_dict(f[dname].attrs) - else: - output_cls_instance.data += _convert_to_np_dtype(f[dname]) - output_cls_instance.data /= num+1 - ret = True - elif output_cls_instance is None: - if isinstance(dset_list, str): - data = _convert_to_np_dtype(f[dset_list]) - meta = hdf_attr_to_dict(f[dset_list].attrs) - elif isinstance(dset_list, list): - for num, dname in enumerate(dset_list): - if num == 0: - data = _convert_to_np_dtype(f[dname]) - meta = hdf_attr_to_dict(f[dname].attrs) - else: - data = _np.vstack((data, _convert_to_np_dtype(f[dname]))) - ret = [data, meta] - else: - raise TypeError('output_cls must be Spectrum, Spectra, or Hsi') - except: - raise TypeError('Something failed in import_hdf_nist_special') - ret = False - - finally: - f.close() - return ret
- -def hdf_export_data(self, output_cls_instance, pth, filename, dsetname): - """ - - """ - - save_grp = dsetname.rpartition('/')[0] - save_dataset_name_no_grp = dsetname.rpartition('/')[-1] - - try: - # Join path and filename in an os-independant way - pfname_out = _os.path.normpath(_os.path.join(pth, filename)) - - f_out = _h5py.File(pfname_out, 'a') - loc = f_out.require_group(save_grp) - dset = loc.create_dataset(save_dataset_name_no_grp, data=output_cls_instance.data) - - for attr_key in output_cls_instance.meta: - try: - attribute = output_cls_instance.meta[attr_key] - if isinstance(attribute, str): - attribute = _np.array(attribute, dtype='S') - dset.attrs.create(attr_key,attribute) - except: - print('Error in attributes') - - # Breadcrumb attributes - bc_attr_dict = self.bcpre.attr_dict - for attr_key in bc_attr_dict: - try: - attribute = bc_attr_dict[attr_key] - if isinstance(attribute, str): - attribute = _np.array(attribute, dtype='S') - dset.attrs.create(attr_key,attribute) - except: - print('Error in attributes') - -# #print('Key: {}, Val: {}'.format(attr_key, bc_attr_dict[attr_key])) -# val = bc_attr_dict[attr_key] -# if isinstance(val, str): -# dset.attrs[attr_key] = val -# else: -# try: -# dset.attrs.create(attr_key,bc_attr_dict[attr_key]) -# except: -# print('Could not create attribute') - - except: - print('Something went wrong while saving') - else: - print('Saved without issues') - finally: - f_out.close() - -if __name__ == '__main__': # pragma: no cover - - from crikit.io.meta_configs import (special_nist_bcars2 - as _snb) - rosetta = _snb() - - pth = '../../../' - filename = 'mP2_w_small.h5' - - dset = '/Spectra/Dark_3_5ms_2' - tester = hdf_is_valid_dsets(pth, 'fake.h5','fake') - assert tester == False - - tester = hdf_is_valid_dsets(pth, filename,'fake_dset') - assert tester == False - - tester = hdf_is_valid_dsets(pth, filename,['fake_dset1','fake_dset2']) - assert tester == False - - tester = hdf_is_valid_dsets(pth, filename,dset) - assert tester == True - - dset_list = hdf_dset_list_rep('/Spectra/Dark_3_5ms_',_np.arange(2)) - tester = hdf_is_valid_dsets(pth, filename,dset_list) - assert tester == True - - print('--------------\n\n') - - spect_dark = _Spectra() - tester = hdf_is_valid_dsets(pth, filename,['/Spectra/Dark_3_5ms_2']) - hdf_import_data(pth, filename,'/Spectra/Dark_3_5ms_2',spect_dark) - #hdf_process_attr(rosetta, spect_dark) - - print('Shape of dark spectra: {}'.format(spect_dark.shape)) - print('Shape of dark spectra.mean(): {}'.format(spect_dark.mean().shape)) - - print('') - img = _Hsi() - hdf_import_data(pth, filename,'/BCARSImage/mP2_3_5ms_Pos_2_0/mP2_3_5ms_Pos_2_0_small',img) - print('Shape of img: {}'.format(img.shape)) - print('Shape of img.mean(): {}'.format(img.mean().shape)) - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/io/meta_configs.html b/docs/build/html/_modules/crikit/io/meta_configs.html deleted file mode 100644 index cc90dc5..0000000 --- a/docs/build/html/_modules/crikit/io/meta_configs.html +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - crikit.io.meta_configs — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.io.meta_configs
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.io.meta_configs

-"""
-Configuration settings for HDF imports
-
-Use '!' as the first entry in a list to denote to use the value rather \
-than querying for it
-
-Created on Mon May 23 10:35:19 2016
-
-@author: chc
-"""
-
-
[docs]def special_nist_bcars2(): - """ - Return import attributes particular to the "BCARS 2" system at NIST - """ - rosetta = {} - - rosetta['XPixelSize'] = ['RasterScanParams.FastAxisStepSize', - 'Raster.Fast.StepSize'] - rosetta['XStart'] = ['RasterScanParams.FastAxisStart', 'Raster.Fast.Start'] - rosetta['XStop'] = ['RasterScanParams.FastAxisStop', 'Raster.Fast.Stop'] - rosetta['XLength'] = ['RasterScanParams.FastAxisSteps', 'Raster.Fast.Steps'] - rosetta['XLabel'] = ['RasterScanParams.FastAxis','Raster.Fast.Axis','!','X'] - rosetta['XUnits'] = ['RasterScanParams.FastAxisUnits','!','$\\mu$m'] - - rosetta['YPixelSize'] = ['RasterScanParams.SlowAxisStepSize', - 'Raster.Slow.StepSize'] - rosetta['YStart'] = ['RasterScanParams.SlowAxisStart', 'Raster.Slow.Start'] - rosetta['YStop'] = ['RasterScanParams.SlowAxisStop', 'Raster.Slow.Stop'] - rosetta['YLength'] = ['RasterScanParams.SlowAxisSteps', 'Raster.Slow.Steps'] - rosetta['YLabel'] = ['RasterScanParams.SlowAxis','Raster.Slow.Axis','!','Y'] - rosetta['YUnits'] = ['RasterScanParams.SlowAxisUnits','!','$\\mu$m'] - - rosetta['ZPosition'] = ['RasterScanParams.FixedAxisPosition', - 'Raster.Stack.Position','!',0] - rosetta['ZLabel'] = ['RasterScanParams.FixedAxis', 'Raster.Stack.Axis','!','Z'] - - # Color Calibration - rosetta['ColorCenterWL'] = ['Spectro.CenterWavelength', - 'Spectro.CurrentWavelength', 'Calib.ctr_wl', - '!', 729.994] - rosetta['ColorUnits'] = ['Calib.units', '!', 'nm'] - rosetta['ColorChannels'] = ['Calib.n_pix', '!', 1600] - rosetta['ColorCalibWL'] = ['Calib.ctr_wl', 'Spectro.CalibWavelength', '!', 729.994] - rosetta['ColorPolyVals'] = ['Spectro.Avec', 'Calib.a_vec', '!', [-0.167740721307557, - 863.8736708961577]] - - rosetta['ColorProbe'] = ['Spectro.ProbeWavelength', 'Calib.probe', '!', 771.461] - rosetta['ColorWnMode'] = ['!', True] - - # Color Calibration Original - rosetta['OrigColorCenterWL'] = ['Spectro.CenterWavelength', - 'Spectro.CurrentWavelength', - 'CalibOrig.ctr_wl'] - rosetta['OrigColorUnits'] = ['CalibOrig.units'] - rosetta['OrigColorChannels'] = ['CalibOrig.n_pix'] - rosetta['OrigColorCalibWL'] = ['CalibOrig.ctr_wl'] - - rosetta['OrigColorPolyVals'] = ['CalibOrig.a_vec'] - - rosetta['OrigColorProbe'] = ['CalibOrig.probe'] - rosetta['OrigColorWnMode'] = ['!', True] - - return rosetta
- -
[docs]def special_nist_bcars1_sample_scan(): - """ - Return import attributes particular to the "BCARS 1" system at NIST - """ - rosetta = {} - - rosetta['XPixelSize'] = 'X scan Parameters.x step size (um)' - rosetta['XStart'] = 'X scan Parameters.x start (um)' - rosetta['XStop'] = 'RasterScanParams.FastAxisStop' - rosetta['XLength'] = 'X scan Parameters.x steps' - rosetta['XLabel'] = 'RasterScanParams.FastAxis' - rosetta['XUnits'] = ['RasterScanParams.FastAxisUnits', '!', '$\mu m$'] - - rosetta['YPixelSize'] = 'Y scan Paramters.y step size (um)' - rosetta['YStart'] = 'Y scan Paramters.y start (um)' - rosetta['YStop'] = 'RasterScanParams.SlowAxisStop' - rosetta['YLength'] = 'Y scan Paramters.y steps' - rosetta['YLabel'] = 'RasterScanParams.SlowAxis' - rosetta['YUnits'] = ['RasterScanParams.SlowAxisUnits', '!', '$\mu m$'] - - rosetta['ZPosition'] = 'Z scan parameters.z start (um)' - rosetta['ZLabel'] = 'RasterScanParams.FixedAxis' - - rosetta['ColorCenterWL'] = ['Frequency Calibration.CenterWavelength', '!', 696.831] - rosetta['ColorUnits'] = ['!','nm'] - rosetta['ColorChannels'] = ['Frequency Calibration.freq index length', '!', 512] - rosetta['ColorCalibWL'] = ['Frequency Calibration.CenterWavelength', '!', 696.831] - - # Will become deprecated in favor of ColorPolyVals - rosetta['ColorSlope'] = ['Frequency Calibration.Slope', '!', -0.50418919] - rosetta['ColorIntercept'] = ['Frequency Calibration.Intercept', '!', 825.651318] - - rosetta['ColorPolyVals'] = ['Frequency Calibration.Polyvals', '!', - [-0.50418919, 825.651318]] - - rosetta['ColorProbe'] = ['Frequency Calibration.probe(nm)','!', 830.0] - rosetta['ColorWnMode'] = ['!', True] - # rosetta['ColorCalibWN'] = ['Processing.WNCalib','Processing.WNCalibOrig'] - - return rosetta
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/io/meta_process.html b/docs/build/html/_modules/crikit/io/meta_process.html deleted file mode 100644 index 69f214d..0000000 --- a/docs/build/html/_modules/crikit/io/meta_process.html +++ /dev/null @@ -1,429 +0,0 @@ - - - - - - - - - - - crikit.io.meta_process — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.io.meta_process
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.io.meta_process

-"""
-Created on Mon May 23 16:55:09 2016
-
-@author: chc
-"""
-
-from crikit.data.frequency import (calib_pix_wn as _calib_pix_wn,
-                                   calib_pix_wl as _calib_pix_wl)
-
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.spectra import Spectra as _Spectra
-from crikit.data.hsi import Hsi as _Hsi
-
-import numpy as _np
-
-
[docs]def rosetta_query(key, rosetta, output_cls_instance): - """ - Return the highest-priority value - """ - - if isinstance(rosetta[key],list): # There is a priority list - for num, count in enumerate(rosetta[key]): - temp_val = None - temp_key = None - - try: - if isinstance(count,str): - if count == '!': - temp_key = key - temp_val = rosetta[key][num+1] - print('Using default meta_configs value for: {}'.format(key)) - break - else: - temp_key = count - temp_val = output_cls_instance._meta[temp_key] - break -# print('{}:{}'.format(count, temp_val)) - else: - pass - except: - temp_val = None - temp_key = None - - if temp_val is not None: - return(temp_val, temp_key) - else: - return None - - elif isinstance(rosetta[key],str): - try: - temp = output_cls_instance._meta[rosetta[key]] - except: - return None - else: - return (temp, rosetta[key]) - else: # the value is likely a predefined answer-- no need to query meta - return None
- -
[docs]def meta_process(rosetta, output_cls_instance): - """ - Uses a conversion dict (rosetta) to process the meta data in \ - output_cls_instance - """ - - # Frequency-calibration - try: - calib_dict = {} - - calib_dict['a_vec'] = rosetta_query('ColorPolyVals',rosetta, output_cls_instance)[0] - calib_dict['n_pix'] = rosetta_query('ColorChannels',rosetta, output_cls_instance)[0] - calib_dict['ctr_wl'] = rosetta_query('ColorCenterWL',rosetta, output_cls_instance)[0] - calib_dict['ctr_wl0'] = rosetta_query('ColorCalibWL',rosetta, output_cls_instance)[0] - calib_dict['probe'] = rosetta_query('ColorProbe',rosetta, output_cls_instance)[0] - calib_dict['units'] = rosetta_query('ColorUnits',rosetta, output_cls_instance)[0] - - output_cls_instance.freq.calib = calib_dict - - use_wn = rosetta_query('ColorWnMode',rosetta, output_cls_instance)[0] - print('Use wavenumber: {}'.format(use_wn)) - if use_wn: # Use wavenumber? - output_cls_instance.freq.calib_fcn = _calib_pix_wn - else: # Use wavelength - output_cls_instance.freq.calib_fcn = _calib_pix_wl - - output_cls_instance.freq.update() - except: - print('Something failed in meta_process: freq-calib') - - # See if an original calibration is found - try: - calib_orig_dict = {} - - calib_orig_dict['a_vec'] = rosetta_query('OrigColorPolyVals',rosetta, output_cls_instance)[0] - if calib_orig_dict['a_vec'] is None: - raise ValueError - calib_orig_dict['n_pix'] = rosetta_query('OrigColorChannels',rosetta, output_cls_instance)[0] - if calib_orig_dict['n_pix'] is None: - raise ValueError - calib_orig_dict['ctr_wl'] = rosetta_query('OrigColorCenterWL',rosetta, output_cls_instance)[0] - if calib_orig_dict['ctr_wl'] is None: - raise ValueError - calib_orig_dict['ctr_wl0'] = rosetta_query('OrigColorCalibWL',rosetta, output_cls_instance)[0] - if calib_orig_dict['ctr_wl0'] is None: - raise ValueError - - # Probe and Units are not necessary for calibration - # Probe is only needed for wavelength-to-wavenumber conversion - calib_orig_dict['probe'] = rosetta_query('OrigColorProbe',rosetta, output_cls_instance)[0] - calib_orig_dict['units'] = rosetta_query('OrigColorUnits',rosetta, output_cls_instance)[0] - - except: - print('Original calibration not found.') - else: - print('Original calibration found.') - output_cls_instance.freq.calib_orig = calib_orig_dict - - # Spatial for HSI - if type(output_cls_instance) == _Hsi: - print('Type Hsi') - try: - start = rosetta_query('XStart',rosetta, output_cls_instance)[0] - stop = rosetta_query('XStop',rosetta, output_cls_instance)[0] - steps = rosetta_query('XLength',rosetta, output_cls_instance)[0] - units = rosetta_query('XUnits',rosetta, output_cls_instance)[0] - label = rosetta_query('XLabel',rosetta, output_cls_instance)[0] - - # HDF files store strings in np.bytes format - if isinstance(units, bytes): - units = units.decode() - if isinstance(label, bytes): - label = label.decode() - - output_cls_instance.x_rep.data = _np.linspace(start, stop, steps) - output_cls_instance.x_rep.units = units - output_cls_instance.x_rep.label = label - output_cls_instance.x_rep.update_calib_from_data() - - del start, stop, steps, units, label - - start = rosetta_query('YStart',rosetta, output_cls_instance)[0] - stop = rosetta_query('YStop',rosetta, output_cls_instance)[0] - steps = rosetta_query('YLength',rosetta, output_cls_instance)[0] - units = rosetta_query('YUnits',rosetta, output_cls_instance)[0] - label = rosetta_query('YLabel',rosetta, output_cls_instance)[0] - - # HDF files store strings in np.bytes format - if isinstance(units, bytes): - units = units.decode() - if isinstance(label, bytes): - label = label.decode() - - output_cls_instance.y_rep.data = _np.linspace(start, stop, steps) - output_cls_instance.y_rep.units = units - output_cls_instance.y_rep.label = label - output_cls_instance.y_rep.update_calib_from_data() - - del start, stop, steps, units - except: - print('Something failed in meta_process: HSI-spatial calib') - - elif type(output_cls_instance) == _Spectra: - try: - print('Type Spectra') - output_cls_instance.reps.units = None - output_cls_instance.reps.label = 'Acq Number' - output_cls_instance.reps.data = _np.arange(output_cls_instance.data.shape[0]) - # print(output_cls_instance.reps.data.shape) - output_cls_instance.reps.update_calib_from_data() - except: - print('Something failed in meta_process: Spectra rep-calib') - - elif type(output_cls_instance) == _Spectrum: - print('Type Spectrum')
- -if __name__ == '__main__': - - from crikit.io.meta_configs import (special_nist_bcars2 - as _snb) - - from crikit.io.hdf5 import hdf_import_data as _hdf_import_data - rosetta = _snb() - - filename = _os.path.abspath('../../../mP2_w_small.h5') - - spect_dark = _Spectra() - _hdf_import_data(filename,'/Spectra/Dark_3_5ms_2',spect_dark) - meta_process(rosetta, spect_dark) - print(spect_dark.reps) - - print('') - img = _Hsi() - _hdf_import_data(filename,'/BCARSImage/mP2_3_5ms_Pos_2_0/mP2_3_5ms_Pos_2_0_small',img) - meta_process(rosetta, img) - print(img.freq.__dict__) - - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/measurement/fftspatialnoise.html b/docs/build/html/_modules/crikit/measurement/fftspatialnoise.html deleted file mode 100644 index 188f20b..0000000 --- a/docs/build/html/_modules/crikit/measurement/fftspatialnoise.html +++ /dev/null @@ -1,340 +0,0 @@ - - - - - - - - - - - crikit.measurement.fftspatialnoise — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.measurement.fftspatialnoise
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.measurement.fftspatialnoise

-"""
-Created on Fri Jun 10 16:16:17 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-
[docs]class FFTSignalMetric: - """ - FFT Spatial Noise Metric (Ratio - 1) - """ - def __init__(self, img_shp, cutoff=0.5, img=None): - - self.value = None - self.cutoff = cutoff - self.img_shape = img_shp - self.img_size = self.img_shape[0]*self.img_shape[1] - - self._calc_mtxs() - - if img is None: - pass - else: - self.calc(img) - -
[docs] def _calc_mtxs(self): - """ - Calculate binary spatial weight maxtrix, wij. - - Note: Currently only supports 1st-order "rook's" case continuity - """ - - self.cutoff_row = [int(self.img_shape[0]/2*self.cutoff), - int(self.img_shape[0]/2*(1+self.cutoff))] - self.cutoff_col = [int(self.img_shape[1]/2*self.cutoff), - int(self.img_shape[1]/2*(1+self.cutoff))] - - self.n_inner_pix = (self.cutoff_row[1]-self.cutoff_row[0]+1) * \ - (self.cutoff_col[1]-self.cutoff_col[0]+1) - - self.n_outter_pix = self.img_size - self.n_inner_pix - - self.scaler = self.n_outter_pix/self.n_inner_pix
- -
[docs] def calc(self, img): - """ - - """ - self.value = None - - f_img = _np.abs(_np.fft.fftshift(_np.fft.fft2(img-img.mean()))) - sum_inner = f_img[self.cutoff_row[0]:self.cutoff_row[1]+1, - self.cutoff_col[0]:self.cutoff_col[1]+1].sum() - sum_outter = f_img.sum() - sum_inner - - if sum_outter == 0: - self.value = 1e6 - else: - self.value = self.scaler*sum_inner/sum_outter - - self.value -= 1
- -if __name__ == '__main__': - - import timeit as _timeit - - side_len = 301 - img = _np.zeros(side_len**2) - img[::1] = 1.0 - img = img.reshape((side_len, side_len)) - - tmr = _timeit.default_timer() - fmet = FFTSignalMetric(img_shp=(side_len, side_len)) - fmet.calc(img) - tmr -= _timeit.default_timer() - - print('---------') - print('Calculated in {:.3g} sec'.format(-tmr)) - print('FFT Signal Metric of checkerboard: {:.3g}'.format(fmet.value)) - print('Is close to ideal -1 value (?) (+/- .1): {}'.format(_np.isclose(fmet.value, -1, atol=1e-1))) - - img = _np.random.rand(side_len, side_len) - - tmr = _timeit.default_timer() - fmet = FFTSignalMetric(img_shp=(side_len, side_len)) - fmet.calc(img) - tmr -= _timeit.default_timer() - - print('\n---------') - print('Calculated in {:.3g} sec'.format(-tmr)) - print('FFT Signal Metric of random: {:.3g}'.format(fmet.value)) - print('Is close to ideal 0 value (+/- .1): {}'.format(_np.isclose(fmet.value, 0, - atol=1e-1))) - - img = _np.random.rand(1, side_len) - - tmr = _timeit.default_timer() - fmet = FFTSignalMetric(img_shp=(1, side_len)) - fmet.calc(img) - tmr -= _timeit.default_timer() - - print('\n---------') - print('Calculated in {:.3g} sec'.format(-tmr)) - print('FFT Signal Metric of random: {:.3g}'.format(fmet.value)) - print('Is close to ideal 0 value (+/- .1): {}'.format(_np.isclose(fmet.value, 0, - atol=1e-1))) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/measurement/peakamps.html b/docs/build/html/_modules/crikit/measurement/peakamps.html deleted file mode 100644 index f7a034f..0000000 --- a/docs/build/html/_modules/crikit/measurement/peakamps.html +++ /dev/null @@ -1,683 +0,0 @@ - - - - - - - - - - - crikit.measurement.peakamps — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.measurement.peakamps
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.measurement.peakamps

-"""
-Created on Wed Jun 29 01:28:44 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-
[docs]class MeasurePeak: - """ - Meausure peak amplitude. - - Parameters - ---------- - pk : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk): - self.amp = None - - self.pk = pk - -
[docs] def calculate(self, signal): - self.amp = self._calc(signal) - - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk): - inst = MeasurePeak(pk) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - amp = signal[..., self.pk] - - return amp
- -
[docs]class MeasurePeakBWTroughs: - """ - Meausure the amplitude of a peak between troughs. - - Parameters - ---------- - pk : int - Peak location in pixel coordinates - tr1 : int - Trough 1 location in pixel coordinates - tr2 : int - Trough 2 location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk, tr1, tr2): - self.amp = None - - self.pk = pk - - if tr1 < tr2: - self.tr_left = tr1 - self.tr_right = tr2 - else: - self.tr_left = tr2 - self.tr_right = tr1 - -
[docs] def calculate(self, signal): -# try: - self.amp = self._calc(signal) -# except: -# return None -# else: - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk, tr1, tr2): - inst = MeasurePeakBWTroughs(pk, tr1, tr2) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - slope = (signal[..., self.tr_right]-signal[..., self.tr_left])/ \ - (self.tr_right - self.tr_left) - amp = signal[..., self.pk] - (slope*(self.pk - self.tr_left) + \ - signal[..., self.tr_left]) - - return amp
- -
[docs]class MeasurePeakMinus: - """ - Meausure the difference (subtraction) of two peaks (pk1 - pk2). - - Parameters - ---------- - pk1 : int - Peak location in pixel coordinates - pk2 : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk1, pk2): - self.amp = None - - self.pk1 = pk1 - self.pk2 = pk2 - -
[docs] def calculate(self, signal): - self.amp = self._calc(signal) - - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk1, pk2): - inst = MeasurePeakMinus(pk1, pk2) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - amp = signal[..., self.pk1] - signal[..., self.pk2] - - return amp
- -
[docs]class MeasurePeakAdd: - """ - Meausure the addition of two peaks (pk1 + pk2). - - Parameters - ---------- - pk1 : int - Peak location in pixel coordinates - pk2 : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk1, pk2): - self.amp = None - - self.pk1 = pk1 - self.pk2 = pk2 - -
[docs] def calculate(self, signal): - self.amp = self._calc(signal) - - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk1, pk2): - inst = MeasurePeakAdd(pk1, pk2) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - amp = signal[..., self.pk1] + signal[..., self.pk2] - - return amp
- -
[docs]class MeasurePeakMultiply: - """ - Meausure the multiplication of two peak. - - Parameters - ---------- - pk1 : int - Peak location in pixel coordinates - pk2 : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk1, pk2): - self.amp = None - - self.pk1 = pk1 - self.pk2 = pk2 - -
[docs] def calculate(self, signal): - self.amp = self._calc(signal) - - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk1, pk2): - inst = MeasurePeakMultiply(pk1, pk2) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - amp = signal[..., self.pk1] * signal[..., self.pk2] - - return amp
- -
[docs]class MeasurePeakDivide: - """ - Meausure the ratio (division) of two peaks. pk1/pk2 - - Parameters - ---------- - pk1 : int - Peak location in pixel coordinates - pk2 : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk1, pk2): - self.amp = None - - self.pk1 = pk1 - self.pk2 = pk2 - -
[docs] def calculate(self, signal): - self.amp = self._calc(signal) - - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk1, pk2): - inst = MeasurePeakDivide(pk1, pk2) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - amp = signal[..., self.pk1] / signal[..., self.pk2] - - return amp
- -
[docs]class MeasurePeakSummation: - """ - Meausure the summation of all amplitudes between (inclusive) two peak - locations. - - Parameters - ---------- - pk1 : int - Peak location in pixel coordinates - pk2 : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, pk1, pk2): - self.amp = None - - self.pk1 = pk1 - self.pk2 = pk2 - -
[docs] def calculate(self, signal): - self.amp = self._calc(signal) - - return self.amp
- -
[docs] @staticmethod - def measure(signal, pk1, pk2): - inst = MeasurePeakSummation(pk1, pk2) - return inst.calculate(signal)
- -
[docs] def _calc(self, signal): - amp = _np.sum(signal[..., self.pk1:self.pk2+1], axis=-1) - - return amp
- -if __name__ == '__main__': - import matplotlib.pyplot as _plt - - print('\n\n--------- 1-Signal Test--------') - amp = 100 - pk = 50 - tr1 = 20 - tr2 = 80 - - x = _np.arange(100) - signal = amp*_np.exp(-(x-pk)**2/(10**2)) - baseline = x - y = signal + baseline - - _plt.plot(x, y.T, label='Signal') - _plt.plot(x,baseline, label='baseline') - _plt.plot(x, signal.T,label='Signal - Baseline') - - # non-static method - #pbwt = MeasurePeakBWTroughs(pk=pk, tr1=tr1, tr2=tr2) - #out = pbwt.calculate(y) - - # static method - out = MeasurePeakBWTroughs.measure(signal, pk, tr1, tr2) - - _plt.plot((pk, pk), (0, out), 'k', lw=3, label='Calculated Amp') - _plt.xlabel('X') - _plt.ylabel('Amplitude (au)') - _plt.legend(loc='best') - _plt.show() - - print('Actual peak amp: {:.2f}. Retrieved peak amp: {:.2f}.'.format(amp, out)) - print('Within 1% agreement: {}'.format(_np.isclose(amp, out, rtol=.01))) - - print('\n\n--------- 2D Simple Test--------') - _plt.figure() - - amp = 100 - pk = 50 - tr1 = 20 - tr2 = 80 - - N=2 - - x = _np.arange(100) - signal = amp*_np.exp(-(x-pk)**2/(10**2)) - baseline = x - y = signal + baseline - mask = _np.ones((N,N)) - y = _np.dot(mask[...,None], y[None,:]) - - _plt.plot(y.reshape((-1,x.size)).T, label='Signal') - _plt.plot(x,baseline, label='baseline') - _plt.plot(x, signal.T,label='Signal - Baseline') - - out = MeasurePeakBWTroughs.measure(signal, pk, tr1, tr2) - - for out_pk in out.ravel(): - _plt.plot((pk, pk), (0, out_pk), 'k', lw=3, label='Calculated Amp') - _plt.xlabel('X') - _plt.ylabel('Amplitude (au)') - _plt.legend(loc='best') - - print('Actual peak(s) amp: {:.2f}. Retrieved peak amps: {}.'.format(amp, out.ravel())) - print('Within 1% agreement: {}'.format(_np.isclose(amp, out.ravel(), rtol=.01))) - print('All agree within 1%: {}'.format(_np.allclose(amp, out.ravel(), rtol=.01))) - - _plt.show() - - print('\n\n--------- 2D More Complicated Test--------') - _plt.figure() - - amp = 100 - pk = 50 - tr1 = 20 - tr2 = 80 - - N=2 - - x = _np.arange(100) - signal = amp*_np.exp(-(x-pk)**2/(10**2)) - mask = _np.ones((N,N)) - rndm = _np.random.randint(0,10,size=(N,N)) - baseline = _np.dot((rndm*mask)[...,None],x[None,:]) - - y = signal[None,None,:] + baseline - - #y = _np.dot(mask[...,None], y[None,:]) - - _plt.plot(y.reshape((-1,x.size)).T, label='Signal') - _plt.plot(x,baseline.reshape((-1,x.size)).T, label='baseline') - _plt.plot(x, signal.T,label='Signal - Baseline') - - #pbwt = MeasurePeakBWTroughs(pk=pk, tr1=tr1, tr2=tr2) - #out = pbwt.calculate(y) - out = MeasurePeakBWTroughs.measure(signal, pk, tr1, tr2) - - for out_pk in out.ravel(): - _plt.plot((pk, pk), (0, out_pk), 'k', lw=3, label='Calculated Amp') - _plt.xlabel('X') - _plt.ylabel('Amplitude (au)') - _plt.legend(loc='best') - - print('Actual peak(s) amp: {:.2f}. Retrieved peak amps: {}.'.format(amp, out.ravel())) - print('Within 1% agreement: {}'.format(_np.isclose(amp, out.ravel(), rtol=.01))) - print('All agree within 1%: {}'.format(_np.allclose(amp, out.ravel(), rtol=.01))) - - _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/measurement/peakfind.html b/docs/build/html/_modules/crikit/measurement/peakfind.html deleted file mode 100644 index 961d294..0000000 --- a/docs/build/html/_modules/crikit/measurement/peakfind.html +++ /dev/null @@ -1,501 +0,0 @@ - - - - - - - - - - - crikit.measurement.peakfind — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.measurement.peakfind
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.measurement.peakfind

-"""
-Peak-finding utilities
-
-
-Notes
------
-"""
-import copy as _copy
-import numpy as _np
-import timeit as _timeit
-
-from scipy.signal import (convolve as _convolve,
-                          argrelmin as _argrelmin)
-
-
[docs]class PeakFinder: - """ - Find peaks and shoulders of a signal. - - Parameters - ---------- - QQ : int - Peak location in pixel coordinates - - Attributes - ---------- - amp : float or ndarray - Amplitude of peak - - Methods - ------- - calculate : Calculate the amplitude - - Static Methods - -------------- - measure : Same as calculate but static (returns the amplitude directly) - - """ - def __init__(self, noise_sigma, cwt_width=10, n_noise_tests=1000, - cutoff_d1=None, cutoff_d2=None, verbose=True): - self.cwt_width = cwt_width # Width, in pixels, of wavelet - self.noise_sigma = noise_sigma # Standard deviation of signal noise - - # If cutoffs not specified, # of Monte Carlo tests to estimate cutoff values - self.n_noise_tests = n_noise_tests - self.cutoff_d1 = cutoff_d1 # Amplitude cutoff for 1st derivative - self.cutoff_d2 = cutoff_d2 # Amplitude cutoff for 2nd derivative - - self.verbose = verbose - - # Array elements - self.x = None # Independent variable - self.y = None # Dependent variable - self.x_pix = None # Independent variable (pixel-units) - - self.amps = None # Retrieved amplitudes - self.centers = None # Retrieved peak centers (x-units) - self.sigmas = None # Retrieved Gaussian widths (x-units) - self.shoulder = None # Is a peak a shoulder - - self.centers_pix = None # Retrieved peak centers (pixel-units) - self.sigmas_pix = None # Retrieved peak widths (standard deviation) (pixel-units) - - self.y_retrieved = None # Estimated coarse peak fitting - - @property - def cwt_width(self): - return self._cwt_width - - @cwt_width.setter - def cwt_width(self, value): - if value <= 0: - raise ValueError('cwt_width must be positive') - else: - self._cwt_width = value - - @property - def noise_sigma(self): - return self._noise_sigma - - @noise_sigma.setter - def noise_sigma(self, value): - if value < 0: - raise ValueError('noise_sigma must be non-negtaive') - else: - self._noise_sigma = value - -
[docs] @staticmethod - def haar(width): - """ - Create Haar wavelet (wv) with specified width (width) - """ - wv = _np.zeros((width)) - midpoint = int(_np.floor(width/2)) - wv[0:midpoint] = 1 - wv[midpoint::] = -1 - - # Set midpoint == 0 for odd-length. Not technically correct, but needed - # for computations - if width % 2 == 1: - wv[midpoint] = 0 - - return wv
- -
[docs] @staticmethod - def cwt_diff(signal, wv_width, order=1, method='auto'): - """ - Take a numerical derivative using a Haar wavelet (noise-supression) - - Parameters - ---------- - signal : ndarray (1D) - Signal data - - wv_width : int - Width of wavelet to use (balance noise suppression and distortion) - - order : int, optional (default=1) - Order of derivative (e.g., 1st-order derivative) - - method : str {'auto' (default), 'fft', 'direct'} - - Returns - ------- - deriv : ndarray (1D) - Derivative of input signal - """ - deriv = _copy.deepcopy(signal) - for count in range(order): - try: - deriv = _convolve(deriv, PeakFinder.haar(wv_width), mode='same', - method=method) - except: - print('peakfind.py | cwt_diff: Likely using an old version of SciPy (no convolve method parameter)') - deriv = _convolve(deriv, PeakFinder.haar(wv_width), mode='same') - return deriv
- - # @staticmethod - # def measure(signal, noise_sigma, x=None, cwt_width=10, n_noise_tests=1000, - # cutoff_d1=None, cutoff_d2=None, verbose=True): - # pass - -
[docs] def calculate(self, y, x=None, recalc_cutoff=True, method='auto'): - """ Find peaks """ - self.y = y - self.x_pix = _np.arange(self.y.size) - - # Will update in the future for 1D x and ND y - if x is not None: - if x.size == y.size: - self.x = x - else: - self.x = None - - self._calc_cutoff(recalc_cutoff=recalc_cutoff, method=method) - - tmr = _timeit.default_timer() - d1 = PeakFinder.cwt_diff(self.y, wv_width=self._cwt_width, order=1, method=method) - d2 = PeakFinder.cwt_diff(self.y, wv_width=self._cwt_width, order=2, method=method) - - loc_mins_d2 = _argrelmin(d2, order=10)[0] - loc_mins_d2 = loc_mins_d2[d2[loc_mins_d2] < 0] - loc_mins_d2 = loc_mins_d2[_np.abs(d2[loc_mins_d2]) > self.cutoff_d2] - loc_mins_d2 = loc_mins_d2[loc_mins_d2 > 10] - loc_mins_d2 = loc_mins_d2[loc_mins_d2 < (d2.size - 10)] - peak = _np.sign(d1[loc_mins_d2-10])+_np.sign(d1[loc_mins_d2+10])==0 - shoulder = ~peak - - - loc_mins_d1 = _argrelmin(d1, order=10)[0] - loc_mins_d1 = loc_mins_d1[d1[loc_mins_d1] < 0] - loc_mins_d1 = loc_mins_d1[_np.abs(d1[loc_mins_d1]) > self.cutoff_d1] - - sigma_retr = [] - sigma_retr_locs = [] - for l in loc_mins_d2: - if self.x is not None: - sigma_retr.append(x[l] - x[loc_mins_d1[_np.argmin(_np.abs(l - loc_mins_d1))]]) - sigma_retr_locs.append(loc_mins_d1[_np.argmin(_np.abs(l - loc_mins_d1))]) - - if self.x is not None: - sigma_retr = _np.abs(_np.array(sigma_retr)) - omegas_retr = x[loc_mins_d2] - sigma_retr_locs = _np.array(sigma_retr_locs) - omegas_retr_locs = loc_mins_d2 - - amps_retr = [] - for l, s in zip(omegas_retr_locs, sigma_retr_locs): - dl = _np.abs(_np.ceil((l - s)/10)).astype(_np.integer) - amps_retr.append(_np.median(y[l-dl:l+dl+1])) - amps_retr = _np.array(amps_retr) - - tmr -= _timeit.default_timer() - self._timer = 1*tmr - - if self.verbose: - print('Time for peak finding: {:.2e} sec'.format(-tmr)) - - y_retrieved = _np.zeros(*self.x_pix.shape) - - for num, (a, o, s) in enumerate(zip(amps_retr, omegas_retr_locs, sigma_retr_locs)): - y_retrieved += a*_np.exp(-(self.x_pix-o)**2/(2*(s)**2)) - - self.amps = 1*amps_retr # Retrieved amplitudes - - if self.x is not None: - self.centers = 1*omegas_retr # Retrieved peak centers (x-units) - self.sigmas = 1*sigma_retr # Retrieved Gaussian widths (x-units) - self.shoulder = shoulder # Is a peak a shoulder - - self.centers_pix = 0+omegas_retr_locs # Retrieved peak centers (pixel-units) - self.sigmas_pix = 1*sigma_retr_locs # Retrieved peak widths (standard deviation) (pixel-units) - - self.y_retrieved = 1*y_retrieved # Estimated coarse peak fitting
- -
[docs] def _calc_cutoff(self, recalc_cutoff=True, method='auto'): - if (self.cutoff_d1 is None) or (self.cutoff_d2 is None) or (recalc_cutoff == True): - y_blank = self._noise_sigma*_np.random.randn(self.n_noise_tests,self.x_pix.size) - y_blank_d2 = _np.zeros(y_blank.shape) - y_blank_d1 = _np.zeros(y_blank.shape) - for num, temp in enumerate(y_blank): - y_blank_d1[num, :] = PeakFinder.cwt_diff(temp, wv_width=self._cwt_width, order=1, method=method) - y_blank_d2[num, :] = PeakFinder.cwt_diff(temp, wv_width=self._cwt_width, order=2, method=method) - - if (self.cutoff_d2 is None) or (recalc_cutoff == True): - self.cutoff_d2 = _np.max(_np.abs(y_blank_d2)) - if (self.cutoff_d1 is None) or (recalc_cutoff == True): - self.cutoff_d1 = _np.max(_np.abs(y_blank_d1)) - - if self.verbose: - print('1st-Deriv cutoff: {:.2f}'.format(self.cutoff_d1)) - print('2nd-Deriv cutoff: {:.2f}'.format(self.cutoff_d2))
- -if __name__ == '__main__': - - x = _np.linspace(0,100,1000) - - A = _np.array([80, 100, 40]) - Omega = _np.array([30, 50, 60]) - Sigma = _np.array([3, 4, 4]) - - y = _np.zeros(x.shape) - - for a, o, s in zip(A, Omega, Sigma): - y += a*_np.exp(-(x-o)**2/(2*s**2)) - - noise_sigma = 3 - noise = noise_sigma*_np.random.randn(*x.shape) - y_noisy = y + noise - - pkfind = PeakFinder(noise_sigma=noise_sigma, cwt_width=50, n_noise_tests=1000, - cutoff_d1=None, cutoff_d2=None, verbose=True) - - print('\n====================================\n') - pkfind.calculate(y, x=x, recalc_cutoff=True, method='fft') - - - print('\nActual Center: {}'.format(Omega)) - print('Calculated Centers: {}\n'.format(['{:.2f}'.format(x) for x in pkfind.centers])) - - print('\nActual Amplitudes: {}'.format(A)) - print('Calculated Amplitudes: {}\n'.format(['{:.2f}'.format(x) for x in pkfind.amps])) - - print('\nActual Widths: {}'.format(Sigma)) - print('Calculated Widths: {}\n'.format(['{:.2f}'.format(x) for x in pkfind.sigmas])) - - print('Is Shoulder: {}\n'.format(pkfind.shoulder)) - # print(pkfind.sigmas) - # print(pkfind.__dict__) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/measurement/tests/test_peakfind.html b/docs/build/html/_modules/crikit/measurement/tests/test_peakfind.html deleted file mode 100644 index cfebe31..0000000 --- a/docs/build/html/_modules/crikit/measurement/tests/test_peakfind.html +++ /dev/null @@ -1,284 +0,0 @@ - - - - - - - - - - - crikit.measurement.tests.test_peakfind — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.measurement.tests.test_peakfind
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.measurement.tests.test_peakfind

-"""
-Testing for Hilbert transform method
-
-Using the math relation a^2 / (a^2 + x^2) (Lorentz/Cauchy) has an 
-analytical Hilbert transform: x^2 / (a^2 + x^2)
-"""
-
-import numpy as np
-from numpy.testing import assert_allclose
-
-from crikit.measurement.peakfind import PeakFinder
-
-
[docs]def test_peakfind(): - x = np.linspace(0,100,1000) - - A = np.array([80, 100]) - Omega = np.array([30, 50]) - Sigma = np.array([3, 4]) - - y = np.zeros(x.shape) - - for a, o, s in zip(A, Omega, Sigma): - y += a*np.exp(-(x-o)**2/(2*s**2)) - - noise_sigma = 0.001 - noise = noise_sigma*np.random.randn(*x.shape) - y_noisy = y + noise - - pkfind = PeakFinder(noise_sigma=noise_sigma, cwt_width=50, n_noise_tests=1000, - cutoff_d1=None, cutoff_d2=None, verbose=False) - - print('\n====================================\n') - pkfind.calculate(y, x=x, recalc_cutoff=True, method='fft') - - assert_allclose(np.array(Omega), pkfind.centers, rtol=0.01) - assert_allclose(np.array(A), pkfind.amps, rtol=0.01) - assert_allclose(np.array(Sigma), pkfind.sigmas, rtol=0.1) - assert_allclose(np.array([False, False]), pkfind.shoulder) - - print('\nActual Center: {}'.format(Omega)) - print('Calculated Centers: {}\n'.format(['{:.2f}'.format(x) for x in pkfind.centers])) - - print('\nActual Amplitudes: {}'.format(A)) - print('Calculated Amplitudes: {}\n'.format(['{:.2f}'.format(x) for x in pkfind.amps])) - - print('\nActual Widths: {}'.format(Sigma)) - print('Calculated Widths: {}\n'.format(['{:.2f}'.format(x) for x in pkfind.sigmas])) - - print('Is Shoulder: {}\n'.format(pkfind.shoulder))
-if __name__ == '__main__': - test_peakfind() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/algorithms/abstract_als.html b/docs/build/html/_modules/crikit/preprocess/algorithms/abstract_als.html deleted file mode 100644 index 6a947d8..0000000 --- a/docs/build/html/_modules/crikit/preprocess/algorithms/abstract_als.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - crikit.preprocess.algorithms.abstract_als — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.algorithms.abstract_als
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.algorithms.abstract_als

-"""
-Created on Mon Dec  5 13:44:58 2016
-
-@author: chc
-"""
-import numpy as _np
-import timeit as _timeit
-
-from scipy.interpolate import UnivariateSpline as _USpline
-
-
[docs]class AbstractBaseline: - -
[docs] def setup(self, redux=1, verbose=False, order=2, fix_end_points=False, - fix_rng=None, max_iter=100, min_diff=1e-5): - self.redux = redux - self.order = order - self.fix_end_points = fix_end_points - self.fix_rng = fix_rng - self.max_iter = max_iter - self.min_diff = min_diff - - self.verbose = verbose - self.t = None - self.t_per_iter = None
- -
[docs] def calculate(self, signal): - sig_shape = signal.shape # Shape of input signal - sig_size = signal.shape[-1] # Length of spectral axis - - # N signals to detrend - sig_n_to_detrend = int(signal.size/signal.shape[-1]) - - tmr = _timeit.default_timer() - if self.redux == 1: - output = self._calc(signal) - else: # Sub-sample - # Dummy indep variable - x = _np.arange(sig_size) - x_sub = _np.linspace(x[0], x[-1], _np.round(x.size / - self.redux).astype(_np.integer)) - - sub_shape = list(sig_shape) - sub_shape[-1] = x_sub.size - - signal_sampled = _np.zeros(sub_shape) - - # Spline interpolation/sub-sampling - for coords in _np.ndindex(signal.shape[0:-1]): - spl = _USpline(x,signal[coords],s=0) - signal_sampled[coords] = spl(x_sub) - - # Baseline from sub-sampled signal - output_sampled = self._calc(signal_sampled) - - output = _np.zeros(signal.shape) - # Spline interpolation/super-sampling - for coords in _np.ndindex(output_sampled.shape[0:-1]): - spl2 = _USpline(x_sub,output_sampled[coords],s=0) - output[coords] = spl2(x) - - tmr -= _timeit.default_timer() - self.t = -tmr - self.t_per_iter = self.t/sig_n_to_detrend - - return output
- -
[docs] def _calc(self, signal): - raise NotImplementedError
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/algorithms/als.html b/docs/build/html/_modules/crikit/preprocess/algorithms/als.html deleted file mode 100644 index e80dd8c..0000000 --- a/docs/build/html/_modules/crikit/preprocess/algorithms/als.html +++ /dev/null @@ -1,453 +0,0 @@ - - - - - - - - - - - crikit.preprocess.algorithms.als — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.algorithms.als
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.algorithms.als

-"""
-Created on Mon Dec  5 12:12:51 2016
-
-@author: chc
-"""
-import numpy as _np
-
-import cvxopt as _cvxopt
-import cvxopt.cholmod as _cholmod
-_cvxopt.cholmod.options['supernodal'] = 1
-_cvxopt.cholmod.options['postorder'] = False
-
-from crikit.preprocess.algorithms.abstract_als import AbstractBaseline
-    
-
[docs]class AlsCvxopt(AbstractBaseline): - def __init__(self, smoothness_param=1e3, asym_param=1e-4, redux=1, - order=2, fix_end_points=False, fix_rng=None, max_iter=100, min_diff=1e-5, - verbose=False): - """ - Parameters - ---------- - smoothness_param : float, optional (default, 1e3) - Smoothness parameter - - asym_param : float, optional (default, 1e-4) - Assymetry parameter - - redux : int, optional (default, 1) - Reduction parameter to sub-sample input signal - - order : int, optional (default, 2) - Derivative regularization term. Order=2 for Whittaker-smoother - - fix_end_points : bool, optional (default, False) - Weight the baseline endpoints to approach equally the end-points - of the data. - - fix_rng : ndarray (1D), optional (default, None) - Pixels to weight so that the baseline strongly approaches the data - at these pixels. - - max_iter : int, optional (default, 100) - Maximum number of least-squares iterations to perform - - min_diff : float, optional (default, 1e-5) - Break iterative calculations if difference is less than min_diff - - verbose : bool, optional (default, False) - Display progress of detrending - - """ - - self.smoothness_param=smoothness_param - self._asym_param=asym_param - - self.setup(redux=redux, verbose=verbose, order=order, - fix_end_points=fix_end_points, fix_rng=fix_rng, - max_iter=max_iter, min_diff=min_diff) - - @property - def asym_param(self): - if _np.size(self._asym_param) == 1: - return self._asym_param - elif self.redux == 1: - return self._asym_param - elif self.redux > 1: - x = _np.arange(0, self._asym_param.size, self.redux, - dtype=_np.integer) - - - return self._asym_param[x] - - @asym_param.setter - def asym_param(self, value): - self._asym_param = value - -
[docs] def _calc(self, signal): - """ - Perform the ALS. Called from self.calculate (defined in - AbstractBaseline parent class) - - Parameters - ---------- - signal : ndarray (>= 1D) - Input signal - - Returns - ------- - baseline : ndarray - Baseline of input signal - """ - sig_shape = signal.shape # Shape of input signal -# sig_ndim = signal.ndim # N Signal dimensions - sig_size = signal.shape[-1] # Length of spectral axis - - # N signals to detrend - sig_n_to_detrend = int(signal.size/signal.shape[-1]) - - baseline_output = _np.zeros(sig_shape) - - # Cute linalg trick to create 2nd-order derivative transform matrix - difference_matrix = _np.diff(_np.eye(sig_size), - n=self.order, axis=0) - - # Convert into sparse matrix - difference_matrix = _cvxopt.sparse(_cvxopt.matrix(difference_matrix)) - - for ct, coords in enumerate(_np.ndindex(signal.shape[0:-1])): - signal_current = signal[coords] - - penalty_vector = _np.ones([sig_size]) - baseline_current = _np.zeros([sig_size]) - baseline_last = _np.zeros([sig_size]) - - # Iterative asymmetric least squares smoothing - for ct_iter in range(self.max_iter): - penalty_matrix = _cvxopt.spdiag(list(penalty_vector)) - - minimazation_matrix = (penalty_matrix + - _cvxopt.mul(self.smoothness_param, - difference_matrix.T) * - difference_matrix) - - x = _cvxopt.matrix(penalty_vector[:]*signal_current) - - try: - # Cholesky factorization A = LL' - # Solve A * baseline_current = w_sp * Signal - _cholmod.linsolve(minimazation_matrix,x,uplo='U') - - except: - print('Failure in Cholesky factorization') - break - else: - if ct_iter > 0: - baseline_last = baseline_current - - baseline_current = _np.array(x).squeeze() - - if ct_iter > 0: # Difference check b/w iterations - differ = _np.abs(_np.sum(baseline_current - - baseline_last, axis=0)) - - if differ < self.min_diff: - break - - # Apply asymmetric penalization - penalty_vector = _np.squeeze(self.asym_param * - (signal_current >= - baseline_current) + - (1-self.asym_param) * - (signal_current < - baseline_current)) - if self.fix_end_points: - penalty_vector[0] = 1 - penalty_vector[-1] = 1 - - if self.fix_rng is not None: - penalty_vector[self.fix_rng] = 1 - - baseline_output[coords] = baseline_current - - if self.verbose: - print('Number of iterations to converge: {}'.format(ct_iter)) - print('Finished detrending spectra {}/{}'.format(ct + 1, - sig_n_to_detrend)) - - return baseline_output
- -if __name__ == '__main__': - import matplotlib.pyplot as _plt - - x = _np.linspace(0,1000,800) - data = _np.exp(-(x-500)**2/300**2) + _np.abs(5/(300 - x -1j*10) + .005) - - N = 1 - D = 2 - - if D == 3: - data = _np.dot((_np.random.rand(N,N)*_np.ones((N,N)))[...,None], data[None,:]) - else: - data = _np.dot((_np.random.rand(N)*_np.ones((N)))[...,None], data[None,:]) - -# print('Data.shape: {}\n'.format(data.shape)) - -# asym_param = _np.logspace(-4, -7, x.size) - - _plt.plot(x,data.T) - - sp_vec = _np.logspace(0,6,7) - for num, sp in enumerate(sp_vec): -# for ap in _np.logspace(-6,0,10): - ap = sp/1e6 - als = AlsCvxopt(smoothness_param=sp, asym_param=ap, redux=1, - max_iter=1000, - verbose=False) - - baseline = als.calculate(data) - - scaled_num = (num)/(sp_vec.size) - color = _plt.cm.jet(scaled_num) - - _plt.plot(x, baseline.T, c=color, label='{:.1e}'.format(sp)) - _plt.legend() - _plt.show() -# print('Internal Timer: {:.4f} sec ({:.4f} per)'.format(als.t, -# als.t_per_iter)) - -# als = AlsCvxopt(smoothness_param=1, asym_param=1e-3, redux=10, -# max_iter=1000, -# verbose=False) -# -# baseline = als.calculate(data) -# print('Internal Timer: {:.4f} sec ({:.4f} per)'.format(als.t, -# als.t_per_iter)) -# -# if (D <= 2) & (N<21): -# _plt.plot(data.T,'k') -# _plt.plot(baseline.T,'r') -# _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/algorithms/anscombe.html b/docs/build/html/_modules/crikit/preprocess/algorithms/anscombe.html deleted file mode 100644 index ca8272e..0000000 --- a/docs/build/html/_modules/crikit/preprocess/algorithms/anscombe.html +++ /dev/null @@ -1,650 +0,0 @@ - - - - - - - - - - - crikit.preprocess.algorithms.anscombe — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.algorithms.anscombe
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.algorithms.anscombe

-"""Variance Stabilization
-
-Routines:
-    gen_anscombe_forward
-        Generalized forward Anscombe transformation
-
-    gen_anscombe_inverse_closed_form
-        Closed-form approximation of the exact unbiased inverse of Generalized \
-        Anscombe variance-stabilizing transformation
-
-    gen_anscombe_exact_unbiased
-        Exact unbiased inverse of Generalized Anscombe variance-stabilizing
-
-Notes
------
-This software is a direct translation (with minor alterations) of the \
-original MATLAB software created by Alessandro Foi and Markku Mäkitalo \
-(Tampere University of Technology - 2011-2012). Please cite the references \
-below if using this software. http://www.cs.tut.fi/~foi/
-
-References
-----------
-[1] M. Mäkitalo and A. Foi, "Optimal inversion of the generalized Anscombe
-    transformation for Poisson-Gaussian noise", IEEE Trans. Image Process.,
-    doi:10.1109/TIP.2012.2202675
-
-[2] J.L. Starck, F. Murtagh, and A. Bijaoui, Image  Processing  and  Data
-    Analysis, Cambridge University Press, Cambridge, 1998)
-
-"""
-
-import numpy as _np
-#import numexpr as _ne
-import os as _os
-
-resource_dir = None
-resource_dir = _os.path.join(_os.path.abspath(_os.path.dirname(__file__)),
-                             'resources')
-
-if _os.path.exists(resource_dir):
-    #print('Resource directory: {}'.format(_os.path.abspath(resource_dir)))
-    pass
-else:  # pragma: no cover
-    raise IOError('Cannot find resource directory for Anscombe')
-
-
[docs]def gen_anscombe_forward(signal, gauss_std, gauss_mean = 0, poisson_multi = 1): - """ - Applies the generalized Anscombe variance-stabilization transform - assuming a mixed Poisson-Gaussian noise model as: - - signal = poisson_multi*Poisson{signal0} + Gauss{gauss_mean, gauss_std}, - - where Poisson{} and Gauss{} are generalized descriptions of Poisson and - Gaussian noise. - - Parameters - ---------- - signal : ndarray - Noisy signal (1-,2-,3D) - - gauss_std : float, int - Standard deviation of Gaussian noise - - poisson_multi : float or int, optional (default = 1) - Effectively a multiplier that scales the effect of the Poisson - noise - - gauss_mean : float or int, optional (default = 0) - Mean Gaussian noise level - - Returns - ------- - fsignal : ndarray (matched to signal shape) - "Anscombe-transformed" signal with an approximate unity standard \ - deviation/variance (~ 1) - - Notes - ----- - This software is a direct translation (with minor alterations) of the - original MATLAB software created by Alessandro Foi and Markku Mäkitalo - (Tampere University of Technology - 2011-2012). Please cite the references - below if using this software. http://www.cs.tut.fi/~foi/ - - References - ---------- - [1] J.L. Starck, F. Murtagh, and A. Bijaoui, Image Processing and - Data Analysis, Cambridge University Press, Cambridge, 1998) - - """ - - SMALL_VAL = 1 - - fsignal = 2/poisson_multi * _np.sqrt(_np.fmax(SMALL_VAL,poisson_multi*signal + - (3/8)*poisson_multi**2 + - gauss_std**2 - - poisson_multi*gauss_mean)) -# fsignal = _ne.evaluate('2/poisson_multi * sqrt(where(poisson_multi*signal + (3/8)*poisson_multi**2 +\ -# gauss_std**2 - poisson_multi*gauss_mean > SMALL_VAL,\ -# poisson_multi*signal + (3/8)*poisson_multi**2 +\ -# gauss_std**2 - poisson_multi*gauss_mean, SMALL_VAL))') - #fsignal = 2/poisson_multi * _np.sqrt(_np.fmax(SMALL_VAL,fsignal)) - return fsignal
- -
[docs]def gen_anscombe_inverse_closed_form(fsignal, gauss_std, gauss_mean = 0, - poisson_multi = 1): - """ - Applies a closed-form approximation of the exact unbiased inverse of the - generalized Anscombe variance-stabilizing transformation assuming a - mixed Poisson-Gaussian noise model as: - - signal = poisson_multi*Poisson{signal0} + Gauss{gauss_mean, gauss_std}, - - where Poisson{} and Gauss{} are generalized descriptions of Poisson and - Gaussian noise. - - Parameters - ---------- - fsignal : ndarray - Forward Anscombe-transformed noisy signal (1-,2-,3D) - - gauss_std : float, int - Standard deviation of Gaussian noise - - (poisson_multi) : float, int (default = 1) - Effectively a multiplier that scales the effect of the Poisson - noise - - (gauss_mean) : float, int (default = 0) - Mean Gaussian noise level - - Returns - ------- - signal : ndarray (matched to signal shape) - Inverse Anscombe-transformed signal with mixed Gaussian-Poisson - noise - - Notes - ----- - This software is a direct translation (with minor alterations) of the - original MATLAB software created by Alessandro Foi and Markku Mäkitalo - (Tampere University of Technology - 2011-2012). Please cite the references - below if using this software. http://www.cs.tut.fi/~foi/ - - References - ---------- - [1] M. Mäkitalo and A. Foi, "Optimal inversion of the generalized Anscombe - transformation for Poisson-Gaussian noise", IEEE Trans. Image Process., - doi:10.1109/TIP.2012.2202675 - - [2] J.L. Starck, F. Murtagh, and A. Bijaoui, Image Processing and Data - Analysis, Cambridge University Press, Cambridge, 1998) - - """ - - SMALL_VAL = 0 - - gauss_std = gauss_std/poisson_multi - -# signal = _ne.evaluate('poisson_multi*where((fsignal/2)**2 + \ -# 1/4*sqrt(3/2)*fsignal**-1 -\ -# (11/8)*fsignal**-2 + 5/8*sqrt(3/2)*fsignal**-3 -\ -# (1/8) - gauss_std**2 > SMALL_VAL, (fsignal/2)**2 + \ -# 1/4*sqrt(3/2)*fsignal**-1 -\ -# (11/8)*fsignal**-2 + 5/8*sqrt(3/2)*fsignal**-3 -\ -# (1/8) - gauss_std**2, SMALL_VAL) + gauss_mean') - - signal = _np.fmax(SMALL_VAL, (fsignal/2)**2 + 1/4*_np.sqrt(3/2)*fsignal**-1 - - (11/8)*fsignal**-2 + 5/8*_np.sqrt(3/2)*fsignal**-3 - - (1/8) - gauss_std**2) - #signal[signal < SMALL_VAL] = SMALL_VAL - signal *= poisson_multi - -# signal = poisson_multi*where((fsignal/2)**2 + \ -# 1/4*sqrt(3/2)*fsignal**-1 -\ -# (11/8)*fsignal**-2 + 5/8*sqrt(3/2)*fsignal**-3 -\ -# (1/8) - gauss_std**2 > SMALL_VAL, (fsignal/2)**2 + \ -# 1/4*sqrt(3/2)*fsignal**-1 -\ -# (11/8)*fsignal**-2 + 5/8*sqrt(3/2)*fsignal**-3 -\ -# (1/8) - gauss_std**2, SMALL_VAL) \ -# + gauss_mean') - - return signal
- -
[docs]def gen_anscombe_inverse_exact_unbiased(fsignal, gauss_std, gauss_mean = 0, - poisson_multi = 1): - """ - Applies an exact, unbiased inverse of the generalized Anscombe - variance-stabilizing transformation assuming a mixed Poisson-Gaussian - noise model as: - - signal = poisson_multi*Poisson{signal0} + Gauss{gauss_mean, gauss_std}, - - where Poisson{} and Gauss{} are generalized descriptions of Poisson and - Gaussian noise. - - Parameters - ---------- - fsignal : ndarray - Forward Anscombe-transformed noisy signal (1-,2-,3D) - - gauss_std : float, int - Standard deviation of Gaussian noise - - (poisson_multi) : float, int (default = 1) - Effectively a multiplier that scales the effect of the Poisson - noise - - (gauss_mean) : float, int (default = 0) - Mean Gaussian noise level - - Returns - ------- - signal : ndarray (matched to signal shape) - Inverse Anscombe-transformed signal with mixed Gaussian-Poisson - noise - - Notes - ----- - This software is a direct translation (with minor alterations) of the - original MATLAB software created by Alessandro Foi and Markku Mäkitalo - (Tampere University of Technology - 2011-2012). Please cite the references - below if using this software. http://www.cs.tut.fi/~foi/ - - References - ---------- - [1] M. Mäkitalo and A. Foi, "Optimal inversion of the generalized Anscombe - transformation for Poisson-Gaussian noise", IEEE Trans. Image Process., - doi:10.1109/TIP.2012.2202675 - - [2] J.L. Starck, F. Murtagh, and A. Bijaoui, Image Processing and Data - Analysis, Cambridge University Press, Cambridge, 1998) - - """ - from scipy.io import loadmat - from scipy.interpolate import InterpolatedUnivariateSpline, interp2d - - SMALL_VAL = 0 - - mat_dict = loadmat(_os.path.join(resource_dir,'GenAnscombe_vectors.mat')) - - Efzmatrix = _np.squeeze(mat_dict['Efzmatrix']) - Ez = _np.squeeze(mat_dict['Ez']) - sigmas = _np.squeeze(mat_dict['sigmas']) - - gauss_std = gauss_std/poisson_multi; - - - # interpolate the exact unbiased inverse for the desired gauss_std - # gauss_std is given as input parameter - if (gauss_std > _np.max(sigmas)): - # for very large sigmas, use the exact unbiased inverse of - # Anscombe modified by a -gauss_std^2 addend - exact_inverse = anscombe_inverse_exact_unbiased(fsignal) - gauss_std**2 - - # this should be necessary, since anscombe_inverse_exact_unbiased(fsignal) is >=0 and gauss_std>=0. - - exact_inverse = _np.fmax(_np.zeros(exact_inverse.shape),exact_inverse) - - elif gauss_std > 0: - # interpolate Efz - - Efz = interp2d(sigmas,Ez,Efzmatrix,kind='linear')(gauss_std,Ez) - - # apply the exact unbiased inverse - exact_inverse = InterpolatedUnivariateSpline(Efz,Ez,k=1)(fsignal) - - # outside the pre-computed domain, use the exact unbiased inverse - # of Anscombe modified by a -gauss_std^2 addend - # (the exact unbiased inverse of Anscombe takes care of asymptotics) - outside_exact_inverse_domain = fsignal > _np.max(Efz.flatten()) - asymptotic = anscombe_inverse_exact_unbiased(fsignal) - gauss_std**2 - exact_inverse[outside_exact_inverse_domain] = asymptotic[outside_exact_inverse_domain] - outside_exact_inverse_domain = fsignal < _np.min(Efz); - exact_inverse[outside_exact_inverse_domain] = 0; - elif gauss_std == 0: - # if gauss_std is zero, then use exact unbiased inverse of Anscombe - # transformation (higher numerical precision) - exact_inverse = anscombe_inverse_exact_unbiased(fsignal); - else: # gauss_std < 0 - raise ValueError('Error: gauss_std must be non-negative!') - - # reverse the initial variable change - - exact_inverse *= poisson_multi; - exact_inverse += gauss_mean; - - return exact_inverse
- -
[docs]def anscombe_inverse_exact_unbiased(fsignal): - """ - Applies an exact, unbiased inverse of the Anscombe - variance-stabilizing transformation assuming a mixed Poisson-Gaussian - noise model as: - - signal = poisson_multi*Poisson{signal0} + Gauss{gauss_mean, gauss_std}, - - where Poisson{} and Gauss{} are generalized descriptions of Poisson and - Gaussian noise. - - Parameters - ---------- - fsignal : ndarray - Forward Anscombe-transformed noisy signal (1-,2-,3D) - - Returns - ------- - signal : ndarray (matched to signal shape) - Inverse Anscombe-transformed signal - - Notes - ----- - This software is a direct translation (with minor alterations) of the - original MATLAB software created by Alessandro Foi and Markku Mäkitalo - (Tampere University of Technology - 2011-2012). Please cite the references - below if using this software. http://www.cs.tut.fi/~foi/ - - References - ---------- - [1] M. Mäkitalo and A. Foi, "On the inversion of the Anscombe - transformation in low-count Poisson image denoising", Proc. Int. - Workshop on Local and Non-Local Approx. in Image Process., LNLA 2009, - Tuusula, Finland, pp. 26-32, August 2009. doi:10.1109/LNLA.2009.5278406 - - [2] M. Mäkitalo and A. Foi, "Optimal inversion of the Anscombe - transformation in low-count Poisson image denoising", IEEE Trans. - Image Process., vol. 20, no. 1, pp. 99-109, January 2011. - doi:10.1109/TIP.2010.2056693 - - [3] Anscombe, F.J., "The transformation of Poisson, binomial and - negative-binomial data", Biometrika, vol. 35, no. 3/4, pp. 246-254, - Dec. 1948. - - """ - import time - - from scipy.io import loadmat - from scipy.interpolate import InterpolatedUnivariateSpline - - mat_dict = loadmat(_os.path.join(resource_dir,'Anscombe_vectors.mat')) - - Efz = mat_dict['Efz'] - Ez = mat_dict['Ez'] - - asymptotic = (fsignal/2)**2 - 1/8; # asymptotically unbiased inverse [3] -# asymptotic = _ne.evaluate('(fsignal/2)**2 - 1/8') # asymptotically unbiased inverse [3] - - #start = time.process_time() - signal = InterpolatedUnivariateSpline(Efz,Ez,k=1)(fsignal) # exact unbiased inverse [1,2] - #stop = time.process_time() - #print(stop-start) - - outside_exact_inverse_domain = fsignal > _np.max(Efz) # for large values use asymptotically unbiased inverse instead of linear extrapolation of exact unbiased inverse outside of pre-computed domain - - signal[outside_exact_inverse_domain] = asymptotic[outside_exact_inverse_domain]; - - outside_exact_inverse_domain = fsignal < 2*_np.sqrt(3/8) # min(Efz(:)); - - signal[outside_exact_inverse_domain] = 0; - return signal
- -if __name__ == '__main__': # pragma: no cover - import numpy as np - import matplotlib as mpl - import matplotlib.pyplot as plt - - stddev = 20 - gain = 1 - - x = np.linspace(500,4000,10000) - y = 10e4*np.exp(-(x-2000)**2/(500**2)) - gnoise = stddev*np.random.randn(x.size) - ygn = y + gnoise - ymix = np.random.poisson(y) + gnoise -# ymix = _np.dot(_np.ones((1000,1)), ymix[None,:]) - ymix_ansc = gen_anscombe_forward(ymix, gauss_std=stddev, poisson_multi=gain) - y_ansc = gen_anscombe_forward(y, gauss_std=stddev, poisson_multi=gain) - - y_inv_ansc = gen_anscombe_inverse_exact_unbiased(y_ansc, gauss_std=stddev, - poisson_multi=gain) - - if ymix.ndim == 1: - plt.subplot(211) - plt.plot(x,y, label='Signal') - plt.hold(True) - plt.plot(x,ymix, label='Mixed Noise Signal') - plt.title('Signal') - plt.legend(loc='best') - - plt.subplot(212) - plt.plot(x,ymix-y, label='Mixed - Signal') - plt.title('Difference ($\sigma =$ {:.3f})'.format((ymix - y).std())) - plt.legend(loc='best') - - plt.figure() - plt.subplot(211) - plt.plot(x,ymix_ansc, label='Anscombe Mixed Signal') - plt.plot(x,y_ansc, label='Anscombe Signal') - plt.title('Anscombe Transformed') - plt.legend(loc='best') - - plt.subplot(212) - plt.plot(x,ymix_ansc - y_ansc, label='Ansc. Mixed - Ansc. Signal') - plt.title('Difference ($\sigma =$ {:.3f})'.format((ymix_ansc - y_ansc).std())) - plt.legend(loc='best') - - plt.figure() - plt.subplot(211) - plt.plot(x,y_inv_ansc, label='Inv. Anscombe Signal') - plt.plot(x,y, label='Signal') - plt.title('Inverse Anscombe Transformed') - plt.legend(loc='best') - - plt.subplot(212) - plt.plot(x,y_inv_ansc - ymix, label='Inv. Ansc. Signal - Mixed') - plt.title('Difference ($\sigma =$ {:.3f})'.format((y_inv_ansc - ymix).std())) - plt.legend(loc='best') - plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/algorithms/arpls.html b/docs/build/html/_modules/crikit/preprocess/algorithms/arpls.html deleted file mode 100644 index ca663ea..0000000 --- a/docs/build/html/_modules/crikit/preprocess/algorithms/arpls.html +++ /dev/null @@ -1,410 +0,0 @@ - - - - - - - - - - - crikit.preprocess.algorithms.arpls — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.algorithms.arpls
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.algorithms.arpls

-"""
-Created on Mon Dec  5 13:53:49 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-import cvxopt as _cvxopt
-import cvxopt.cholmod as _cholmod
-_cvxopt.cholmod.options['supernodal'] = 1
-_cvxopt.cholmod.options['postorder'] = False
-
-from crikit.preprocess.algorithms.abstract_als import AbstractBaseline
-    
-
[docs]class ArPlsCvxopt(AbstractBaseline): - def __init__(self, smoothness_param=1e-8, redux=1, order=2, - fix_end_points=False, max_iter=100, min_diff=1e-5, - verbose=False): - """ - Parameters - ---------- - smoothness_param : float, optional (default, 1e3) - Smoothness parameter - - redux : int, optional (default, 1) - Reduction parameter to sub-sample input signal - - order : int, optional (default, 2) - Derivative regularization term. Order=2 for Whittaker-smoother - - max_iter : int, optional (default, 100) - Maximum number of least-squares iterations to perform - - min_diff : float, optional (default, 1e-5) - Break iterative calculations if difference is less than min_diff - - verbose : bool, optional (default, False) - Display progress of detrending - - """ - - self.smoothness_param=smoothness_param - - self.setup(redux=redux, verbose=verbose, order=order, - fix_end_points=fix_end_points, max_iter=max_iter, - min_diff=min_diff) - -
[docs] def _calc(self, signal): - # Shut-off over-flow warning temporarily - _np.seterr(over = 'ignore') - - sig_shape = signal.shape # Shape of input signal -# sig_ndim = signal.ndim # N Signal dimensions - sig_size = signal.shape[-1] # Length of spectral axis - - # N signals to detrend - sig_n_to_detrend = int(signal.size/signal.shape[-1]) - - baseline_output = _np.zeros(sig_shape) - - # Cute linalg trick to create 2nd-order derivative transform matrix - difference_matrix = _np.diff(_np.eye(sig_size), - n=self.order, axis=0) - - # Convert into sparse matrix - difference_matrix = _cvxopt.sparse(_cvxopt.matrix(difference_matrix)) - - for ct, coords in enumerate(_np.ndindex(signal.shape[0:-1])): - signal_current = signal[coords] - - penalty_vector = _np.ones([sig_size]) - baseline_current = _np.zeros([sig_size]) -# baseline_last = _np.zeros([sig_size]) - - # Iterative asymmetric least squares smoothing - for ct_iter in range(self.max_iter): - penalty_matrix = _cvxopt.spdiag(list(penalty_vector)) - - minimazation_matrix = (penalty_matrix + - _cvxopt.mul(self.smoothness_param, - difference_matrix.T) * - difference_matrix) - - x = _cvxopt.matrix(penalty_vector[:]*signal_current) - - # Cholesky factorization A = LL' - # Solve A * baseline_current = w_sp * Signal - _cholmod.linsolve(minimazation_matrix,x,uplo='U') - -# if ct_iter > 0: -# baseline_last = baseline_current - - baseline_current = _np.array(x).squeeze() - - signal_baseline_differ = signal_current - baseline_current - neg_signal_baseline_differ = signal_baseline_differ[signal_baseline_differ < 0] - mean_neg_signal_baseline_differ = _np.mean(neg_signal_baseline_differ) - std_neg_signal_baseline_differ = _np.std(neg_signal_baseline_differ) - - penalty_vector_temp = 1 / (1 + - _np.exp(2*(signal_baseline_differ - - (2*std_neg_signal_baseline_differ - - mean_neg_signal_baseline_differ)) / - std_neg_signal_baseline_differ)) - - if ct_iter > 0: - norm_differ = (_np.linalg.norm(penalty_vector - - penalty_vector_temp) / - _np.linalg.norm(penalty_vector)) -# print('Norm differ: {:.2f}'.format(norm_differ)) -# print(norm_differ) -# print('norm: {:.6e}'.format(_np.linalg.norm(penalty_vector))) - if (norm_differ < self.min_diff) | (_np.isnan(norm_differ)): - break - - penalty_vector = penalty_vector_temp - - if self.fix_end_points: - penalty_vector[0] = 1 - penalty_vector[-1] = 1 - - if self.verbose: - print('Number of iterations to converge: {}'.format(ct_iter)) - - baseline_output[coords] = baseline_current - - if self.verbose: - print('Finished detrending spectra {}/{}'.format(ct + 1, - sig_n_to_detrend)) - - return baseline_output
- -if __name__ == '__main__': - import matplotlib.pyplot as _plt - - x = _np.linspace(0,1000,800) - data_orig = _np.abs(5/(300 - x -1j*10) + .005) - bg = _np.exp(-(x-500)**2/700**2) - data = bg + data_orig - - N = 1 - D = 2 - - if N > 1: - if D == 3: - data = _np.dot((_np.random.rand(N,N)*_np.ones((N,N)))[...,None], data[None,:]) - else: - data = _np.dot((_np.random.rand(N)*_np.ones((N)))[...,None], data[None,:]) - - print('Data.shape: {}\n'.format(data.shape)) - - arpls = ArPlsCvxopt(smoothness_param=1e-11, redux=1, max_iter=1000, - min_diff=1e-6, - verbose=False) - - baseline = arpls.calculate(data) - print('Internal Timer: {:.4f} sec ({:.4f} per)'.format(arpls.t, - arpls.t_per_iter)) - -# arpls = ArPlsCvxopt(smoothness_param=1e-15, redux=10, max_iter=50, -# verbose=False) -# -# baseline = arpls.calculate(data) -# print('Internal Timer: {:.4f} sec ({:.4f} per)'.format(arpls.t, -# arpls.t_per_iter)) -# - - if (D <= 2) & (N<21): - _plt.figure() - _plt.plot(data.T,'k') - _plt.plot(baseline.T,'r') - - _plt.figure() - _plt.plot(data_orig.T, 'k') - _plt.plot((data-baseline).T, 'r') - _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/crop.html b/docs/build/html/_modules/crikit/preprocess/crop.html deleted file mode 100644 index 759a60d..0000000 --- a/docs/build/html/_modules/crikit/preprocess/crop.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - crikit.preprocess.crop — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.crop
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.crop

-"""
-Created on Tue Jun 21 14:28:49 2016
-
-@author: chc
-"""
-
-import numpy as _np
-import copy as _copy
-
-
-
[docs]class ZeroColumn: - """ - Set first or last column that is not all 0's to 0. - - Parameters - ---------- - first_or_last : int, optional (default = 0 [first]) - Find first (= 0) or last (= -1) - - zero_col : int, optional (default = None) - Zero a specified column - """ - def __init__(self, first_or_last=0, zero_col=None): - self.zero_col = zero_col - self.fol = first_or_last - -
[docs] def _calc(self, data, ret_obj): - assert data.ndim == 3 - try: - if self.zero_col is None: - row_sums = data.sum(axis=(0, -1)) - self.zero_col = _np.nonzero(row_sums)[0][self.fol] - - ret_obj[:, self.zero_col, :] *= 0 - except: - return False - else: - return True
- -
[docs] def transform(self, data): - success = self._calc(data, ret_obj=data) - return success
- -
[docs] def calculate(self, data): - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- - -
[docs]class ZeroRow: - """ - Set first or last row that is not all 0's to 0. - - Parameters - ---------- - first_or_last : int, optional (default = 0 [first]) - Find first (= 0) or last (= -1) - - zero_row : int, optional (default = None) - Zero a specified row - """ - def __init__(self, first_or_last=0, zero_row=None): - self.zero_row = zero_row - self.fol = first_or_last - -
[docs] def _calc(self, data, ret_obj): - assert data.ndim == 3 - try: - if self.zero_row is None: - col_sums = data.sum(axis=(1, -1)) - self.zero_row = _np.nonzero(col_sums)[0][self.fol] - - ret_obj[self.zero_row, :, :] *= 0 - except: - return False - else: - return True
- -
[docs] def transform(self, data): - success = self._calc(data, ret_obj=data) - return success
- -
[docs] def calculate(self, data): - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- -if __name__ == '__main__': - - - temp = _np.random.rand(3,4,5) - z = ZeroColumn(first_or_last=0) - z.transform(temp) - print('Zero First Column') - print('Is first column sum-0?: {}'.format(temp.sum(axis=(0,-1))[0] == 0)) - print('Is first row sum-0?: {}'.format(temp.sum(axis=(1,-1))[0] == 0)) - - temp = _np.random.rand(3,4,5) - z = ZeroRow(first_or_last=0) - z.transform(temp) - print('\n\nZero First Row') - print('Is first column sum-0?: {}'.format(temp.sum(axis=(0,-1))[0] == 0)) - print('Is first row sum-0?: {}'.format(temp.sum(axis=(1,-1))[0] == 0)) - - temp = _np.random.rand(3,4,5) - z = ZeroColumn(first_or_last=-1) - z.transform(temp) - print('\n\nZero Last Column') - print('Is last column sum-0?: {}'.format(temp.sum(axis=(0,-1))[-1] == 0)) - print('Is last row sum-0?: {}'.format(temp.sum(axis=(1,-1))[-1] == 0)) - - temp = _np.random.rand(3,4,5) - z = ZeroRow(first_or_last=-1) - z.transform(temp) - print('\n\nZero First Row') - print('Is last column sum-0?: {}'.format(temp.sum(axis=(0,-1))[-1] == 0)) - print('Is last row sum-0?: {}'.format(temp.sum(axis=(1,-1))[-1] == 0)) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/denoise.html b/docs/build/html/_modules/crikit/preprocess/denoise.html deleted file mode 100644 index 1670a3d..0000000 --- a/docs/build/html/_modules/crikit/preprocess/denoise.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - - - - - crikit.preprocess.denoise — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.denoise
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.denoise

-"""
-Denoising
-
-Created on Fri Apr 22 23:55:22 2016
-
-@author: chc
-"""
-
-import copy as _copy
-
-import numpy as _np
-
-from numpy.linalg import svd as _svd
-
-from crikit.utils.datacheck import _rng_is_pix_vec
-
-__all__ = ['SVDDecompose', 'SVDRecompose']
-
-
-
[docs]class SVDDecompose: - """ - Compute the SVD of a signal (just wraps numpy.linalg.svd) i.e., decompose \ - the input into components. - - Parameters - ---------- - data : ndarray (2D or 3D). - Input array. - - rng : ndarray (1D), optional - Range of pixels to perform operation over. - - Returns - ------- - ndarray, ndarray, ndarray - U, s, Vh - - Notes - ----- - - U : ndarray (2D) - U-component from SVD decomposition (spatial componenet with crikit) - - Vh : ndarray (2D) - Vh-component from SVD decomposition (spectral componenet with crikit). - NOTE: this is the Hermitial/conjugate transpose of the normal - V-component in SVD - - s : ndarray (1D) - Diagonal elements of S-matrix describing the relative contributions - of each singular value - - S : ndarray (2D) - S-matrix derived from s - - References - ---------- - - """ - def __init__(self, rng=None): - self._U = None - self._s = None - self._Vh = None - - self.rng = _rng_is_pix_vec(rng) - - -
[docs] def _calc(self, data, ret_obj): - """ - Calculate SVD (wrap numpy SVD). - """ - try: - if self.rng is None: - self._U, self._s, self._Vh = _svd(data, full_matrices=False) - else: - self._U, self._s, self._Vh = _svd(data[..., self.rng], - full_matrices=False) - except: - return False - else: - return True
- -
[docs] def calculate(self, data): - """ - Calculate SVD and return U, s, and Vh. - """ - - # If 3D -> 2D - if data.ndim == 3: - success = self._calc(data.reshape((-1,data.shape[-1])), ret_obj=None) - else: - success = self._calc(data, ret_obj=None) - if success: - return self._U, self._s, self._Vh - else: - return None
- - -
[docs]class SVDRecompose: - """ - Reconstruct the original data using the SVD components. The reconstructed \ - signal shape is 2D (or if provided) or matches data_obj. - - Parameters - ---------- - U : ndarray (2D) - U-component from SVD decomposition (spatial componenet with crikit) - - s : ndarray (1D) - Diagonal elements of S-matrix describing the relative contributions - of each singular value - - Vh : ndarray (2D) - Vh-component from SVD decomposition (spectral componenet with crikit). - NOTE: this is the Hermitial/conjugate transpose of the normal - V-component in SVD - - data : ndarray (2D or 3D) - Original data (for overwrite if selected). - - rng : ndarray (1D), optional - Range of pixels to perform operation over. - - overwrite : bool, optional (default=True) - Overwrite the original data in data_obj - - Returns - ------- - ndarray (2D or 3D) - Recomposed data (U*S*Vh). If data_obj is not None, returned object \ - shape matches data_obj. Else 2D. - - None - Returns None if overwrite is True and overwrites input data_obj. - - Notes - ----- - - S : ndarray (2D) - S-matrix derived from s - - References - ---------- - - """ - def __init__(self, rng=None): - self.rng = _rng_is_pix_vec(rng) - self.svs = None - self.s_keep = None - - -
[docs] def _calc(self, U, s, Vh, ret_obj): - """ - Perform data reconstruction from U*S*Vh with selected s-values. - """ - - try: - ret_obj *= 0 - if ret_obj.ndim == 2: - if self.rng is None: - # out = U*S*Vh - # ret_obj += _np.dot(U, _np.dot(_np.diag(s), Vh)) - ret_obj += _np.dot(U[:, self.svs], _np.dot(_np.diag(s[self.svs]), Vh[self.svs, :])) - else: - # ret_obj[..., self.rng] += _np.dot(U, _np.dot(_np.diag(s), Vh)) - ret_obj[..., self.rng] += _np.dot(U[:, self.svs], _np.dot(_np.diag(s[self.svs]), Vh[self.svs, :])) - elif ret_obj.ndim == 3: - # If 3D (calculate is performed in 2D), reshape. - if self.rng is None: - # out = U*S*Vh - # ret_obj += _np.reshape(_np.dot(U, _np.dot(_np.diag(s), Vh)), - # ret_obj.shape) - ret_obj += _np.reshape(_np.dot(U[:, self.svs], - _np.dot(_np.diag(s[self.svs]), - Vh[self.svs, :])), ret_obj.shape) - else: - shp = list(ret_obj.shape) - shp[-1] = self.rng.size - # ret_obj[..., self.rng] += _np.reshape(_np.dot(U, _np.dot(_np.diag(s), Vh)), - # shp) - ret_obj[..., self.rng] += _np.reshape(_np.dot(U[:, self.svs], _np.dot(_np.diag(s[self.svs]),Vh[self.svs, :])), shp) - - except: - return False - else: - return True
- -
[docs] def _set_s_keep(self, s, svs): - """ - Set the singular value vector (s_keep) based on svs list/ndarray - """ - if svs is not None: - self.svs = svs - if self.svs is None: - self.svs = _np.arange(s.size) - - self.s_keep = 0*s - self.s_keep[self.svs] = s[self.svs]
- # print(self.s_keep) - # self.s_keep = s[svs] - -
[docs] def transform(self, data, U, s, Vh, svs=None): - # Set what singular values to keep - self._set_s_keep(s, svs) - - - success = self._calc(U, self.s_keep, Vh, ret_obj=data) - return success
- -
[docs] def calculate(self, data, U, s, Vh, svs=None): - # Set what singular values to keep - self._set_s_keep(s, svs) - - data_copy = _copy.deepcopy(data) - success = self._calc(U, self.s_keep, Vh, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- - -if __name__ == '__main__': # pragma: no cover - - y = _np.random.randn(100,1000) - - svd_decompose = SVDDecompose() - svd_recompose = SVDRecompose() - - U, s, Vh = svd_decompose.calculate(y) - - y2 = svd_recompose.calculate(y,U,s,Vh,svs=[]) - print('0 singular values selected...') - print('Returns matrix is all 0\'s: {}'.format(_np.allclose(y2,0) == True)) - - [U,s,Vh] = svd_decompose.calculate(y) - y2 = svd_recompose.calculate(y, U, s, Vh, svs=[1]) - print('\n1 singular value selected...') - print('Returns matrix is NOT all 0\'s: {}'.format(_np.allclose(y2,0) == False)) - print('Return matrix is all based on 1 component: {}'.format(_np.isclose(\ - _np.median(y2[0,:]/y2[50,:]),y2[0,0]/y2[50,0]))) - - print('\nReturned matrix is same shape {} as that entered: {}'.format(y.shape, y.shape == y2.shape)) - - y = _np.random.randn(10,10,1600) - rng = _np.arange(300,600) - svd_decompose = SVDDecompose(rng=rng) - svd_recompose = SVDRecompose(rng=rng) - U, s, Vh = svd_decompose.calculate(y) - - y2 = svd_recompose.calculate(y, U, s, Vh, svs=[]) - print('\nReturned matrix is same shape {} as that entered: {}'.format(y.shape, y.shape == y2.shape)) - - y = _np.random.randn(10,1000) - y_copy = _copy.deepcopy(y) - - [U,s,Vh] = svd_decompose.calculate(y) - y2 = svd_recompose.transform(y, U, s, Vh, svs=[]) - print('\nOverwrite input data...') - print('0 singular values selected...') - print('Input is NOT same as output: {}'.format(not _np.allclose(y,y_copy))) - print('Returns matrix is all 0\'s: {}'.format(_np.allclose(y,0) == True)) - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/standardize.html b/docs/build/html/_modules/crikit/preprocess/standardize.html deleted file mode 100644 index 6dab92e..0000000 --- a/docs/build/html/_modules/crikit/preprocess/standardize.html +++ /dev/null @@ -1,589 +0,0 @@ - - - - - - - - - - - crikit.preprocess.standardize — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.standardize
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.standardize

-"""
-Standardization
-
-Created on Thu Apr 14 08:53:08 2016
-
-@author: chc
-"""
-
-__all__ = ['Anscombe', 'AnscombeInverse']
-
-import copy as _copy
-import numpy as _np
-
-from crikit.preprocess.algorithms.anscombe import (gen_anscombe_forward as ansc,
-                                                   gen_anscombe_inverse_exact_unbiased as inv_ansc)
-
-from crikit.utils.datacheck import _rng_is_pix_vec
-
-
[docs]class Anscombe: - """ - Implement the generalized forward Anscombe transformation. - - Signal : :math:`X` - - Mean of Gaussian noise : :math:`<g>` - - Standard deviation of Gaussian noise : :math:`\sigma_g` - - Noise of type 'type' : :math:`N_{type}` - - Poisson noise multiplier : :math:`\\alpha` - - Model : :math:`X = \\alpha*N_{Poisson}\{X\} + N_{Gauss}\{<g>, \sigma_g\},` - - Parameters - ---------- - data : ndarray. - Signal with mixed Gaussian and Poisson noise to transform. - - gauss_std : float - Standard deviation of Gaussian noise. :math:`\sigma_g` in model. - - poisson_multi : float, optional (default=1.0) - A multiplier that scales the effect of the Poisson noise. \ - :math:`\\alpha` in model. - - gauss_mean : float, optional (default=0.0) - Mean Gaussian noise level. :math:`<g>` in model. - - rng : ndarray (1D), optional - Range of pixels to perform operation over. - - overwrite : bool, optional (default=True) - - Returns - ------- - ndarray - Altered data if overwrite is False - - None - Return None if overwrite is True - - See Also - ----- - * See the docstring of ./algorithms/anscombe for more information. - - References - ----------- - [1] M. Mäkitalo and A. Foi, "Optimal inversion of the generalized Anscombe \ - transformation for Poisson-Gaussian noise", IEEE Trans. Image Process., \ - doi:10.1109/TIP.2012.2202675 - - [2] J.L. Starck, F. Murtagh, and A. Bijaoui, Image Processing and Data \ - Analysis, Cambridge University Press, Cambridge, 1998) - - [3] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, \ - comparable coherent anti-Stokes Raman scattering (CARS) \ - spectroscopy: Correcting errors in phase retrieval," Journal of Raman \ - Spectroscopy 47, 408-415 (2016). arXiv:1507.06543. - """ - def __init__(self, gauss_std, gauss_mean=0.0, poisson_multi=1.0, rng=None): - - self.gauss_std = gauss_std - self.gauss_mean = gauss_mean - self.poisson_multi = poisson_multi - - self.rng = _rng_is_pix_vec(rng) - -
[docs] def _calc(self, data, ret_obj): - # Anscombe transform - if self.rng is None: - self.rng = _np.arange(data.shape[-1]) - out = ansc(data, gauss_std=self.gauss_std, - gauss_mean=self.gauss_mean, - poisson_multi=self.poisson_multi) - else: - out = ansc(data[..., self.rng], gauss_std=self.gauss_std, - gauss_mean=self.gauss_mean, - poisson_multi=self.poisson_multi) - - try: - ret_obj *= 0 - ret_obj[..., self.rng] = out - except: - return False - else: - return True
- -
[docs] def transform(self, data): - """ - Generalized Anscombe transform (Overwrite data). - - Parameters - ---------- - data : ndarray - Input data. - - Returns - ------- - bool - Returns the success state (True=success) - - """ - success = self._calc(data, ret_obj=data) - return success
- -
[docs] def calculate(self, data): - """ - Generalized Anscombe transform (Return copy). - - Parameters - ---------- - data : ndarray - Input data. - - Returns - ------- - ndarray - Returns Anscombe-transformed data (or None if fails) - - """ - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- - -
[docs]class AnscombeInverse: - """ - Applies an exact, unbiased inverse of the generalized Anscombe \ - variance-stabilizing transformation assuming a mixed Poisson-Gaussian \ - noise model as: - - - Signal : :math:`X` - - Mean of Gaussian noise : :math:`<g>` - - Standard deviation of Gaussian noise : :math:`\sigma_g` - - Noise of type 'type' : :math:`N_{type}` - - Poisson noise multiplier : :math:`\\alpha` - - Model : :math:`X = \\alpha*N_{Poisson}\{X\} + N_{Gauss}\{<g>, \sigma_g\},` - - Parameters - ---------- - data : Spectrum (or subclass) object or ndarray. - Signal with mixed Gaussian and Poisson noise to transform. - - gauss_std : float - Standard deviation of Gaussian noise. :math:`\sigma_g` in model. - - poisson_multi : float, optional (default=1.0) - A multiplier that scales the effect of the Poisson noise. \ - :math:`\\alpha` in model. - - gauss_mean : float, optional (default=0.0) - Mean Gaussian noise level. :math:`<g>` in model. - - rng : ndarray (1D), optional - Range of pixels to perform operation over. - - overwrite : bool, optional (default=True) - - See Also - ----- - * See the docstring of ./algorithms/anscombe for more information. - - References - ---------- - [1] M. Mäkitalo and A. Foi, "Optimal inversion of the generalized Anscombe \ - transformation for Poisson-Gaussian noise", IEEE Trans. Image Process., \ - doi:10.1109/TIP.2012.2202675 - - [2] J.L. Starck, F. Murtagh, and A. Bijaoui, Image Processing and Data \ - Analysis, Cambridge University Press, Cambridge, 1998) - - [3] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, \ - comparable coherent anti-Stokes Raman scattering (CARS) \ - spectroscopy: Correcting errors in phase retrieval," Journal of Raman \ - Spectroscopy 47, 408-415 (2016). arXiv:1507.06543. - """ - - def __init__(self, gauss_std, gauss_mean=0.0, poisson_multi=1.0, rng=None): - self.gauss_std = gauss_std - self.gauss_mean = gauss_mean - self.poisson_multi = poisson_multi - - self.rng = _rng_is_pix_vec(rng) - -
[docs] def _calc(self, data, ret_obj): - - # Inverse Anscombe transform - if self.rng is None: - self.rng = _np.arange(data.shape[-1]) - out = inv_ansc(data, gauss_std=self.gauss_std, - gauss_mean=self.gauss_mean, - poisson_multi=self.poisson_multi) - else: - out = inv_ansc(data[..., self.rng], gauss_std=self.gauss_std, - gauss_mean=self.gauss_mean, - poisson_multi=self.poisson_multi) - - try: - ret_obj *= 0 - ret_obj[..., self.rng] = out - except: - return False - else: - return True
- -
[docs] def transform(self, data): - """ - Generalized Inverse Anscombe transform (Overwrite data). - - Parameters - ---------- - data : ndarray - Input data. - - Returns - ------- - bool - Returns the success state (True=success) - - """ - success = self._calc(data, ret_obj=data) - return success
- -
[docs] def calculate(self, data): - """ - Generalized Inverse Anscombe transform (Return copy). - - Parameters - ---------- - data : ndarray - Input data. - - Returns - ------- - ndarray - Returns Anscombe-transformed data (or None if fails) - - """ - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- -if __name__ == '__main__': # pragma: no cover - - from crikit.data.spectrum import Spectrum as _Spectrum - - stddev = 20 - gain = 1 - - f = _np.linspace(500,4000,1000) - sig = 10e4*_np.exp(-(f-2000)**2/(500**2)) - - gnoise = stddev*_np.random.randn(f.size) - - sig_mix = _np.random.poisson(sig) + gnoise - - import matplotlib.pyplot as _plt - - anscombe = Anscombe(gauss_std=stddev, gauss_mean=0, poisson_multi=gain) - - sig2 = _Spectrum(sig) - - out = anscombe.calculate(sig2.data) - _plt.subplot(211) - _plt.plot(sig2.data, label='Data') - _plt.title('Untransformed Space') - _plt.legend(loc='best') - - _plt.subplot(212) - _plt.plot(out, label='Calculate') - - out2 = anscombe.transform(sig2.data) - _plt.plot(sig2.data, label='Transform') - _plt.legend(loc='best') - _plt.title('Anscombe Transform') - _plt.show() - - print('Transform and Calculate Equivalent: {}'.format(_np.allclose(out, - sig2.data))) - - inverse_anscombe = AnscombeInverse(gauss_std=stddev, gauss_mean=0, - poisson_multi=gain) - - sig2 = _Spectrum(sig) - sig2_ansc = anscombe.calculate(sig2.data) - - out = inverse_anscombe.calculate(sig2_ansc) - _plt.subplot(211) - _plt.plot(sig2.data, label='Data') - _plt.plot(out, label='Calculate') - _plt.title('Untransformed Space/Inverse Anscombe') - - _plt.legend(loc='best') - - _plt.subplot(212) - _plt.plot(sig2_ansc, label='Anscombe') - - - _plt.legend(loc='best') - _plt.title('Anscombe Transform') - _plt.show() - -# print('Data and Inverse of Anscombe Close: {}'.format(_np.allclose(out, -# sig2.data))) - - _plt.figure() - _plt.plot(out-sig2.data) - _plt.title('Inverse Anscombe - Original Data') - _plt.show() -# -# print((out-sig2.data)[0]) - -# # Recalc sig -# sig = 10e4*_np.exp(-(f-2000)**2/(500**2)) -# -# _plt.figure() -# sig_ansc = anscombe(sig.data, gauss_std=stddev, poisson_multi=gain, overwrite=False) -# out = anscombe_inverse(sig_ansc, gauss_std=stddev, poisson_multi=gain, overwrite=False) -# _plt.plot(sig) -# _plt.plot(out) -# anscombe_inverse(sig_ansc, gauss_std=stddev, poisson_multi=gain, overwrite=True) -# _plt.plot(sig_ansc) -# _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/subtract_baseline.html b/docs/build/html/_modules/crikit/preprocess/subtract_baseline.html deleted file mode 100644 index 3256118..0000000 --- a/docs/build/html/_modules/crikit/preprocess/subtract_baseline.html +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - - - - crikit.preprocess.subtract_baseline — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.subtract_baseline
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.subtract_baseline

-"""
-
-Subtract baseline
-
-Created on Sat May 28 00:41:41 2016
-
-@author: chc
-"""
-
-import copy as _copy
-
-import numpy as _np
-
-from crikit.preprocess.algorithms.als import (AlsCvxopt as _AlsCvxopt)
-
-from crikit.utils.datacheck import _rng_is_pix_vec
-
-
-
[docs]class SubtractBaselineALS: - """ - Subtract baseline using asymmetric least squares algorithm - - Parameters - ---------- - smoothness_param : float, optional (default=1.0) - Smoothness parameter aka 'lambda' - - asym_param : float, optional (default=1e-2) - Asymmetry parameter aka 'p' - - redux_factor : int, optional (default=10) - Down-sampling factor (more down-sampling leads to faster detrending, - but with more chance of non-optimal detrending) - - rng : ndarray (1D), optional (default=None) - Range in pixels to perform action over - - use_imag : bool, optional (default=True) - If spectrum(a) are complex-values, use the imaginary portion? - """ - def __init__(self, smoothness_param=1, asym_param=1e-2, - redux=10, order=2, rng=None, fix_end_points=False, - max_iter=100, min_diff=1e-5, use_imag=True, - **kwargs): - - self.rng = _rng_is_pix_vec(rng) - self._k = kwargs - - self._k.update({'smoothness_param' : smoothness_param, - 'asym_param' : asym_param, - 'redux' : redux, - 'order' : order, - 'fix_end_points' : fix_end_points, - 'max_iter' : max_iter, - 'min_diff' : min_diff}) - - self.use_imag = use_imag - -
[docs] def _calc(self, data, ret_obj, **kwargs): - - self._inst_als = _AlsCvxopt(**kwargs) - - try: - # Get the subarray shape - shp = data.shape[0:-2] - total_num = _np.array(shp).prod() - - # Iterate over the sub-array -- super slick way of doing it - for num, idx in enumerate(_np.ndindex(shp)): - print('Detrended iteration {} / {}'.format(num+1, total_num)) - # Imaginary portion set - if self.use_imag and _np.iscomplexobj(data): - if self.rng is None: - ret_obj[idx] -= 1j*self._inst_als.calculate(data[idx].imag) - else: - ret_obj[idx][..., self.rng] -= 1j*self._inst_als.calculate(data[idx][..., self.rng].imag) - else: # Real portion set or real object - if self.rng is None: - ret_obj[idx] -= self._inst_als.calculate(data[idx].real) - else: - ret_obj[idx][..., self.rng] -= self._inst_als.calculate(data[idx][..., self.rng].real) - except: - return False - else: -# print(self._inst_als.__dict__) - return True
- -
[docs] def transform(self, data, **kwargs): - self._k.update(kwargs) - - success = self._calc(data, ret_obj=data, **self._k) - return success
- -
[docs] def calculate(self, data, **kwargs): - - data_copy = _copy.deepcopy(data) - self._k.update(kwargs) - - success = self._calc(data, ret_obj=data_copy, **self._k) - if success: - return data_copy - else: - return None
- - -if __name__ == '__main__': - - from crikit.data.spectrum import Spectrum as _Spectrum - from crikit.data.spectra import Spectra as _Spectra - from crikit.data.hsi import Hsi as _Hsi - - import matplotlib.pyplot as _plt - sp = _Spectrum() - sp.data = _np.exp(-(_np.arange(1000)-500)**2/100**2) - - sub_baseline_als = SubtractBaselineALS(smoothness_param=1, asym_param=1e-1) - - _plt.plot(sp.data, label='Original') - out = sub_baseline_als.transform(sp.data) - _plt.plot(sp.data, label='Detrended') - _plt.title('Spectrum') - _plt.legend(loc='best') - _plt.show() - - sp.data = _np.exp(-(_np.arange(1000)-500)**2/100**2) - _plt.plot(sp.data, label='Original') - sub_baseline_als.redux_factor = 10 - out = sub_baseline_als.transform(sp.data) - _plt.plot(sp.data, label='Detrended (Redux)') - _plt.title('Spectrum') - _plt.legend(loc='best') - _plt.show() -# - spa = _Spectra() - sub_baseline_als = SubtractBaselineALS(smoothness_param=1e2, asym_param=1e-4) - spa.data = _np.dot(_np.ones((2,1)),_np.exp(-(_np.arange(1000)-500)**2/100**2)[None,:]) - _plt.plot(spa.data.T, label='Original') - out = sub_baseline_als.transform(spa.data) - _plt.plot(spa.data.T, label='Detrended') - _plt.title('Spectra') - _plt.legend(loc='upper right') - _plt.show() - - hsi = _Hsi() - sub_baseline_als.redux_factor = 10 - hsi.data = _np.dot(_np.ones((1,1,1)),_np.exp(-(_np.arange(1000)-500)**2/100**2)[None,:]) - - _plt.plot(hsi.data.reshape((-1,1000)).T, label='Original') - out = sub_baseline_als.calculate(hsi.data) - _plt.plot(out.reshape((-1,1000)).T, label='Detrended (Redux)') - _plt.plot(hsi.data.reshape((-1,1000)).T, label='Original (No Overwrite)') - _plt.title('HSI') - _plt.legend(loc='upper right') - _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/subtract_dark.html b/docs/build/html/_modules/crikit/preprocess/subtract_dark.html deleted file mode 100644 index 7aef6fb..0000000 --- a/docs/build/html/_modules/crikit/preprocess/subtract_dark.html +++ /dev/null @@ -1,372 +0,0 @@ - - - - - - - - - - - crikit.preprocess.subtract_dark — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.subtract_dark
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.subtract_dark

-"""
-Subtract mean value (optionally, over a range from all spectrum/spectra/hsi)
-
-Created on Thu May 26 14:31:39 2016
-
-@author: chc
-"""
-
-import numpy as _np
-import copy as _copy
-
-from crikit.data.spectrum import Spectrum as _Spectrum
-from crikit.data.spectra import Spectra as _Spectra
-from crikit.data.hsi import Hsi as _Hsi
-
-from crikit.utils.general import (expand_1d_to_ndim as _expand_1d_to_ndim,
-                                  mean_nd_to_1d as _mean_nd_to_1d)
-
-
[docs]class SubtractDark: - def __init__(self, dark): - self.dark = dark - -
[docs] def transform(self, data): - """ - Subtract dark spectrum (overwrite original data). - - - Parameters - ---------- - data : ndarray - Data from which dark is subtracted. - - Returns - ------- - bool - Returns the success state (True=success) - - """ - success = self._calc(data, ret_obj=data) - return success
- - -
[docs] def calculate(self, data): - """ - Subtract dark spectrum (return copy). - - Parameters - ---------- - data : ndarray - Data from which dark is subtracted. - - Returns - ------- - ndarray - Returns data with dark subtracted (or None if fails) - - """ - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- -
[docs] def _calc(self, data, ret_obj): - # Assume that an nD dark should be averaged to be 1D - self.dark = _mean_nd_to_1d(self.dark, axis=-1) - - # Expand dark dimensionality to match data.ndim - self.dark = _expand_1d_to_ndim(self.dark, data.ndim) - - try: - ret_obj -= self.dark - except: - return False - else: - return True
- -if __name__ == '__main__': # pragma: no cover - - x = _np.linspace(0,100,10) - y = _np.linspace(0,100,10) - freq = _np.arange(20) - data = _np.ones((10,10,20)) - - # OVERWRITE TEST - hs = _Hsi(data=_copy.deepcopy(data), freq=freq, x=x, y=y) - spa = _Spectra(data=_copy.deepcopy(data)[0,:,:], freq=freq) - sp = _Spectrum(data=_copy.deepcopy(data)[0,0,:], freq=freq) - - dark=0.5 * _copy.deepcopy(data) - dark_sub = SubtractDark(dark) - - print('\n---------TRANSFORM TEST----------\n') - print('\n3D----------') - print('Initial mean: {}'.format(hs.data.mean())) - out = dark_sub.transform(hs.data) - print('Success?: {}'.format(out)) - print('Final mean: {}\n'.format(hs.data.mean())) - - print('2D----------') - print('Initial mean: {}'.format(spa.data.mean())) - out = dark_sub.transform(spa.data) - print('Success?: {}'.format(out)) - print('Final mean: {}\n'.format(spa.data.mean())) - - print('1D----------') - print('Initial mean: {}'.format(sp.data.mean())) - out = dark_sub.transform(sp.data) - print('Success?: {}'.format(out)) - print('Final mean: {}'.format(sp.data.mean())) - - # NOT-OVERWRITE TEST - print('\n---------CALCULATE TEST----------\n') - - hs = _Hsi(data=_copy.deepcopy(data), freq=freq, x=x, y=y) - spa = _Spectra(data=_copy.deepcopy(data)[0,:,:], freq=freq) - sp = _Spectrum(data=_copy.deepcopy(data)[0,0,:], freq=freq) - - dark=0.5 * _copy.deepcopy(data) - dark_sub = SubtractDark(dark) - - print('\n3D----------') - print('Initial Data Mean: {}'.format(hs.data.mean())) - out = dark_sub.calculate(hs.data) - print('Returned Mean: {}'.format(out.mean())) - print('Final Data Mean: {}'.format(hs.data.mean())) - - print('2D----------') - print('Initial Data Mean: {}'.format(spa.data.mean())) - out = dark_sub.calculate(spa.data) - print('Returned Mean: {}'.format(out.mean())) - print('Final Data Mean: {}'.format(spa.data.mean())) - - print('1D----------') - print('Initial Data Mean: {}'.format(sp.data.mean())) - out = dark_sub.calculate(sp.data) - print('Returned Mean: {}'.format(out.mean())) - print('Final Data Mean: {}'.format(sp.data.mean())) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/preprocess/subtract_mean.html b/docs/build/html/_modules/crikit/preprocess/subtract_mean.html deleted file mode 100644 index f11d665..0000000 --- a/docs/build/html/_modules/crikit/preprocess/subtract_mean.html +++ /dev/null @@ -1,372 +0,0 @@ - - - - - - - - - - - crikit.preprocess.subtract_mean — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.preprocess.subtract_mean
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.preprocess.subtract_mean

-"""
-Subtract mean value (optionally, over a range from all spectrum/spectra/hsi)
-
-Created on Thu May 26 14:31:39 2016
-
-@author: chc
-"""
-import copy as _copy
-import numpy as _np
-
-from crikit.utils.general import find_nearest as _find_nearest
-from crikit.utils.datacheck import _rng_is_pix_vec
-
-
-
[docs]class SubtractMeanOverRange: - def __init__(self, rng=None): - self.rng = _rng_is_pix_vec(rng) - - -
[docs] def _calc(self, data, ret_obj): - if self.rng is None: - meaner = data.mean(axis=-1) - else: - meaner = data[..., self.rng].mean(axis=-1) - - try: - ret_obj -= meaner[..., None] - except: - return False - else: - return True
- - -
[docs] def transform(self, data): - """ - Subtract the mean intensity over a pixel range (rng). \ - (Overwrite data). - - Parameters - ---------- - data : ndarray - Input data. - - Returns - ------- - bool - Returns the success state (True=success) - - """ - success = self._calc(data, ret_obj=data) - return success
- -
[docs] def calculate(self, data): - """ - Subtract the mean intensity over a pixel range (rng). \ - (Return copy). - - Parameters - ---------- - data : ndarray - Input data. - - Returns - ------- - ndarray - Returns data with mean subtracted (or None if fails) - - """ - data_copy = _copy.deepcopy(data) - success = self._calc(data, ret_obj=data_copy) - if success: - return data_copy - else: - return None
- -if __name__ == '__main__': # pragma: no cover - - from crikit.data.spectrum import Spectrum as _Spectrum - from crikit.data.spectra import Spectra as _Spectra - from crikit.data.hsi import Hsi as _Hsi - - - - x = _np.linspace(0, 100, 10) - y = _np.linspace(0, 100, 10) - freq = _np.arange(20) - data = _np.ones((10, 10, 20)) - - hs = _Hsi(data=_copy.deepcopy(data), freq=freq, x=x, y=y) - spa = _Spectra(data=_copy.deepcopy(data), freq=freq) - sp = _Spectrum(data=_copy.deepcopy(data)[0, 0, :], freq=freq) - - mean_sub = SubtractMeanOverRange([5, 8]) - - print('\n---------TRANSFORM TEST----------\n') - print('\n3D----------') - print('Initial mean: {}'.format(hs.data.mean())) - out = mean_sub.transform(hs.data) - print('Success?: {}'.format(out)) - print('Final mean: {}\n'.format(hs.data.mean())) - - print('2D----------') - print('Initial mean: {}'.format(spa.data.mean())) - out = mean_sub.transform(spa.data) - print('Success?: {}'.format(out)) - print('Final mean: {}\n'.format(spa.data.mean())) - - print('1D----------') - print('Initial mean: {}'.format(sp.data.mean())) - out = mean_sub.transform(sp.data) - print('Success?: {}'.format(out)) - print('Final mean: {}'.format(sp.data.mean())) - - # NOT-OVERWRITE TEST - print('\n---------CALCULATE TEST----------\n') - - hs = _Hsi(data=_copy.deepcopy(data), freq=freq, x=x, y=y) - spa = _Spectra(data=_copy.deepcopy(data)[0, :, :], freq=freq) - sp = _Spectrum(data=_copy.deepcopy(data)[0, 0, :], freq=freq) - - mean_sub = SubtractMeanOverRange([5, 8]) - - print('\n3D----------') - print('Initial Data Mean: {}'.format(hs.data.mean())) - out = mean_sub.calculate(hs.data) - print('Returned Mean: {}'.format(out.mean())) - print('Final Data Mean: {}'.format(hs.data.mean())) - - print('2D----------') - print('Initial Data Mean: {}'.format(spa.data.mean())) - out = mean_sub.calculate(spa.data) - print('Returned Mean: {}'.format(out.mean())) - print('Final Data Mean: {}'.format(spa.data.mean())) - - print('1D----------') - print('Initial Data Mean: {}'.format(sp.data.mean())) - out = mean_sub.calculate(sp.data) - print('Returned Mean: {}'.format(out.mean())) - print('Final Data Mean: {}'.format(sp.data.mean())) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/classes_ui.html b/docs/build/html/_modules/crikit/ui/classes_ui.html deleted file mode 100644 index 5f7126c..0000000 --- a/docs/build/html/_modules/crikit/ui/classes_ui.html +++ /dev/null @@ -1,655 +0,0 @@ - - - - - - - - - - - crikit.ui.classes_ui — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.classes_ui
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.classes_ui

-"""
-User Interface and Visualization Classes (crikit.ui.classes_ui)
-===============================================================
-
-BW : Grayscale images
-
-SingleColor : Single-color images
-
-_ColorMath : Container of math operations
-
-"""
-
-import numpy as _np
-import copy as _copy
-import matplotlib as _mpl
-
-
[docs]class BW: - """ - - """ - - def __init__(self, **kwargs): - self._default_attributes = { - 'title':None, - 'setflag':0, - 'setmax':None, - 'setmin':None, - 'compress_low':None, - 'compress_high':None, - 'setgain':1, - 'xunits':'Pixels', - 'yunits':'Pixels' - } - self._default_attributes.update(kwargs) - - self._grayscaleimage = None - self.title = self._default_attributes['title'] - self.setflag = self._default_attributes['setflag'] - self.setmax = self._default_attributes['setmax'] - self.setmin = self._default_attributes['setmin'] - self.compress_high = self._default_attributes['compress_high'] - self.compress_low = self._default_attributes['compress_low'] - self.setgain = self._default_attributes['setgain'] - self.xunits = self._default_attributes['xunits'] - self.yunits = self._default_attributes['yunits'] - self._x = None - self._y = None - - @property - def image(self): - """ - For image from property settings (limits, compression, etc) - """ - img = self.grayscaleimage - - if (self.setmax is None or self.setmin is None): - return img*self.setgain - else: - mask_pass = (img >= self.setmin)*(img <= self.setmax) - mask_low = (img < self.setmin) - mask_high = (img > self.setmax) - img = (mask_pass*img + self.compress_low*mask_low*self.setmin + - self.compress_high*mask_high*self.setmax) - return img*self.setgain - - @property - def winextent(self): - return (self.x.min(), self.x.max(), self.y.min(), self.y.max()) - - @property - def maxer(self): - return self.grayscaleimage.max() - - @property - def minner(self): - return self.grayscaleimage.min() - - @property - def std(self): - try: - temp = self.grayscaleimage.std() - return temp - except: - return None - - @property - def mean(self): - try: - temp = self.grayscaleimage.mean() - return temp - except: - return None - - @property - def ylen(self): - return self._grayscaleimage.shape[0] - - @property - def xlen(self): - return self._grayscaleimage.shape[1] - - @property - def grayscaleimage(self): - return self._grayscaleimage - - @grayscaleimage.setter - def grayscaleimage(self, value): - try: - if value.ndim == 2: - self._grayscaleimage = value - if (_np.equal(self._x,None).any() or - _np.equal(self._y,None).any() or - self._x.size != value.shape[1] or - self._y.size != value.shape[0]): - - self._x = _np.linspace(1, value.shape[1], value.shape[1]) - self._y = _np.linspace(1, value.shape[0], value.shape[0]) - - - else: - pass - except: - print('Set grayscaleimage error') - - @grayscaleimage.deleter - def grayscaleimage(self): - self.__init__() - - @property - def x(self): - if self._x is not None: - return self._x - else: - self._x = _np.arange(self.xlen) - self.xunits = self._default_attributes['xunits'] - return self._x - - @x.deleter - def x(self): - self._x = _np.linspace(1, self.xlen, self.xlen) - self.xunits = self.XUNITS - - @property - def y(self): - if self._y is not None: - return self._y - else: - self._y = _np.arange(self.ylen) - self.yunits = self._default_attributes['yunits'] - return self._y - - @y.deleter - def y(self): - self._y = _np.linspace(1, self.ylen, self.ylen) - self.yunits = self.YUNITS - -
[docs] def set_x(self, value, units = None): - if value is None: - pass - else: - if self.xlen == value.size: - self._x = value - if units is not None: - self.xunits = units - else: - pass
- -
[docs] def set_y(self, value, units = None): - if value is None: - pass - else: - if self.ylen == value.size: - self._y = value - if units is not None: - self.yunits = units - else: - pass
- - -
[docs]class _ColorMath: - - opfreq1 = None - opfreq2 = None - opfreq3 = None - - operation = None - - condfreq1 = None - condfreq2 = None - condfreq3 = None - - condoperation = None - inequality = None - inequalityval = None - - def __init__(self): - pass
- -
[docs]class CompositeColor(BW): - """ - - """ - def __init__(self, sgl_color_list = None): - BW.__init__(self) - self.bgcolor = [0,0,0] - self.mode = 0 # 0: emission; 1: absorption - - if sgl_color_list is None: - self.sgl_color_list = [] - else: - self.sgl_color_list = sgl_color_list - - @property - def mode_txt(self): - if self.mode == 0: - return 'Emission' - else: - return 'Absorption' - - @property - def image(self): - #print(self.sgl_color_list) - if len(self.sgl_color_list) == 0: - return _np.zeros(self.grayscaleimage.shape) - else: - if self.mode == 0: # Emission - img_emission = _np.zeros(self.sgl_color_list[0].image.shape) - - list_imgs = _copy.deepcopy(self.sgl_color_list) - - for img in list_imgs: - img.bgcolor = [0,0,0] - img_emission += img.image - img_emission[img_emission>1] = 1 - return img_emission - elif self.mode == 1: # Absorption - img_absorption = _np.zeros(self.sgl_color_list[0].image.shape) - img_frac_coverage = _np.zeros(self.sgl_color_list[0].grayscaleimage.shape) - img_num_covered = _np.zeros(self.sgl_color_list[0].grayscaleimage.shape) - - list_imgs = _copy.deepcopy(self.sgl_color_list) - - for img in list_imgs: - if (img.grayscaleimage.nonzero()[0].size == 0) | (img.setgain == 0.0): - pass - else: - img.bgcolor = [0,0,0] - - temp = 1*img.imageGS - temp -= temp.min() - if temp.max() != 0: - temp /= temp.max() - - img_absorption += temp[:,:,None]*img.colormap - img_frac_coverage += temp - img_num_covered += (temp > 0) - img_frac_coverage[img_frac_coverage>1] = 1 - img_absorb_bg = (1-img_frac_coverage)[:,:,None]*[1,1,1] - img_absorb_bg[img_absorb_bg<0] = 0 - img_absorption /= (img_num_covered+1e-10)[:,:,None] - img_absorption += img_absorb_bg - return img_absorption - elif self.mode == 2: # Absorption version 2 - - img_emission = _np.zeros(self.sgl_color_list[0].image.shape) - list_imgs = _copy.deepcopy(self.sgl_color_list) - - # Start with emission image BUT white background - # This addition will BRIGHTEN as well - # thus needs contrast enhancement later - num = 0 - for img in list_imgs: - img.bgcolor = [1,1,1] - temp = img.image - if (temp.max() != temp.min()) & (img.setgain != 0.0): - img_emission += temp - num += 1 - - # Average - if num != 0: - img_emission /= num - - # This enhances contrast - # Yes, the first step cancels out the step above - # but this keep the norm. and contrast steps separate - img_emission *= num - img_emission -= (num-1) - - img_emission[img_emission<0] = 0 - img_emission[img_emission>1] = 1 - - return img_emission - - @property - def ylen(self): - return self.sgl_color_list[0].image.shape[0] -# return self.grayscaleimage.shape[0] - - @property - def xlen(self): - return self.sgl_color_list[0].image.shape[1]
-# return self.grayscaleimage.shape[1] - -
[docs]class SingleColor(BW, _ColorMath): - """ - - """ - - def __init__(self): - BW.__init__(self) - self.bgcolor = [0,0,0] - self.colormap = [1,0,0] - - def __add__(self, other): - return self.image + other.image - - @property - def image(self): - - if (self.setmax is None or self.setmin is None): - scaled_gs = SingleColor._imgnorm(self.grayscaleimage) - scaled_gain_gs = scaled_gs*self.setgain - final_scaled_gs = SingleColor._imgnormcompress(scaled_gain_gs) - return SingleColor._bwtocolor(final_scaled_gs, self.colormap, self.bgcolor) - - else: - fudge_factor = .001 - fudge_amt = _np.abs((self.setmax - self.setmin)*fudge_factor) - fudged_min = self.setmin - fudge_amt - fudged_max = self.setmax + fudge_amt - - # if self.compress == True: - mask_pass = (self.grayscaleimage >= fudged_min) * \ - (self.grayscaleimage <= fudged_max) - mask_low = (self.grayscaleimage < fudged_min) - mask_high = (self.grayscaleimage > fudged_max) - masked_img = mask_pass*self.grayscaleimage + \ - self.compress_low*mask_low*fudged_min + \ - self.compress_high*mask_high*fudged_max - - scaled_gs = SingleColor._imgnorm(masked_img) - scaled_gain_gs = scaled_gs*self.setgain - final_scaled_gs = SingleColor._imgnormcompress(scaled_gain_gs) - return SingleColor._bwtocolor(final_scaled_gs, self.colormap, self.bgcolor) - - # else: - # mask = (self.grayscaleimage >= fudged_min) * \ - # (self.grayscaleimage <= fudged_max) - # masked_img = self.grayscaleimage*mask - - # scaled_gs = SingleColor._imgnorm(masked_img) - # scaled_gain_gs = scaled_gs*self.setgain - # final_scaled_gs = SingleColor._imgnormcompress(scaled_gain_gs) - # return SingleColor._bwtocolor(final_scaled_gs, self.colormap) - - @property - def imageGS(self): - """ - Returns self.grayscaleimage with limits applied - """ - if (self.setmax is None or self.setmin is None): - return self.grayscaleimage - - else: - # if self.compress == True: - mask_pass = (self.grayscaleimage >= self.setmin)*(self.grayscaleimage <= self.setmax) - mask_low = (self.grayscaleimage < self.setmin) - mask_high = (self.grayscaleimage > self.setmax) - masked_img = (mask_pass*self.grayscaleimage + self.compress_low*mask_low*self.setmin + - self.compress_high*mask_high*self.setmax) - - return masked_img - - # else: - # mask = (self.grayscaleimage >= self.setmin)*(self.grayscaleimage <= self.setmax) - # masked_img = self.grayscaleimage*mask - - # return masked_img - -
[docs] @staticmethod - def _imgnorm(img, low = None, high = None): - """ - Normalize intensity (B&W) image. Values at - low -> 0 - high -> 1 - - """ - - # If now provided low or high values, set to min() and max() - if low is None: - low = img.min() - if high is None: - high = img.max() - - # Ensure high and low values are different - if high == low: - return 0*img # Return 0's, if same - else: - return (img - low)/(high - low)
- -
[docs] @staticmethod - def _imgnormcompress(img): - """ - Compress normalized image. Values: - > 1 -> 1 - < 0 -> 0 - """ - mask_pass = (img <= 1)*(img >= 0) - mask_high = (img > 1) - - return mask_pass*img + mask_high
- -
[docs] @staticmethod - def _bwtocolor(gs, colormap, bgcolor=[0,0,0]): - """ - Convert normalized [0,1] B&W image (gs) to color, applying a - 3-value list colormap (colormap) - """ - # img = _np.ones((gs.shape[0], gs.shape[1], 3)) - # gs_3d = _np.dot(gs[:,:,None],_np.ones((1,3))) - # return (img*colormap)*gs_3d - return (1-gs[:,:,None])*bgcolor + gs[:,:,None]*colormap
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_AbstractFactorization.html b/docs/build/html/_modules/crikit/ui/dialog_AbstractFactorization.html deleted file mode 100644 index aedad7e..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_AbstractFactorization.html +++ /dev/null @@ -1,548 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_AbstractFactorization — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_AbstractFactorization
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_AbstractFactorization

-"""
-Abstract Factorization Class
-
-Created on Mon Jul 25 10:44:03 2016
-
-@author: chc
-"""
-
-import sys as _sys
-import numpy as _np
-
-from PyQt5 import QtWidgets as _QtWidgets
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QDialog as _QDialog)
-import PyQt5.QtCore as _QtCore
-
-# Import from Designer-based GUI
-from crikit.ui.qt_Factorization import Ui_Dialog ### EDIT ###
-
-# Generic imports for MPL-incorporation
-import matplotlib as _mpl
-
-
-from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas
-
-_mpl.use('Qt5Agg')
-_mpl.rcParams['font.family'] = 'sans-serif'
-_mpl.rcParams['font.size'] = 12
-
-
[docs]class DialogAbstractFactorization(_QDialog): - """ - SubUiSVD : SVD SubUI - """ - def __init__(self, parent=None): - super(DialogAbstractFactorization, self).__init__(parent=parent) - -## def __init__(self, parent=None): -# raise NotImplementedError('This is an abstract class.') -## super(DialogAbstractFactorization, self).__init__(parent=parent) ### EDIT ### -## self.setup() -## self.setupData(img_shape=img_shape) -## self.ui_changes() -# pass - - -
[docs] def ui_changes(self): - """ - Any changes to ui labels or otherwise for particular implementation - """ - pass
- -
[docs] def setupData(self, img_shape): - self._img_shape = img_shape - self._img_size = int(_np.array(img_shape).prod()) - self._img_shape2D = tuple(_np.array(img_shape)[0:2]) - self._img_size2D = int(_np.array(img_shape)[0:2].prod()) - self._n_y = img_shape[0] - self._n_x = img_shape[1] - self._n_spectra = img_shape[2] - self._n_factors = self.max_factors() - - self.selected_factors = set() - self.cube_all = None - self.img_all = None - self.spect_all = None
- - -
[docs] def setup(self, parent = None): - - # Generic load/init designer-based GUI - # super(DialogAbstractFactorization, self).__init__(parent) ### EDIT ### - - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.pushButtonNext.clicked.connect(self.advance) - self.ui.pushButtonPrev.clicked.connect(self.advance) - self.ui.pushButtonGoTo.clicked.connect(self.advance) - self.ui.pushButtonCancel.clicked.connect(self.reject) - self.ui.pushButtonOk.clicked.connect(self.accept) - self.ui.pushButtonClear.clicked.connect(self.clear) - self.ui.pushButtonApply.clicked.connect(self.applyCheckBoxes) - self.ui.pushButtonScript.clicked.connect(self.runScript) - - self._first_factor_visible = 0 - self._num_factor_visible = 6 - - self.ui.lcdSelectedFactors.display(0) - self.ui.lcdMaxFactors.display(self.max_factors()) - - self.factorWins = [] - self.factorLabelCheckBoxes = [self.ui.checkBox, - self.ui.checkBox_2, - self.ui.checkBox_3, - self.ui.checkBox_4, - self.ui.checkBox_5, - self.ui.checkBox_6] - - for count in range(self._num_factor_visible): - self.factorWins.append(_MplCanvas(subplot=211)) - self.factorWins[count].ax[0].axis('Off') - self.factorWins[count].ax[1].hold('Off') - - self.ui.gridLayout.addWidget(self.factorWins[0],1,0) - self.ui.gridLayout.addWidget(self.factorWins[1],1,1) - self.ui.gridLayout.addWidget(self.factorWins[2],1,2) - - self.ui.gridLayout.addWidget(self.factorWins[3],3,0) - self.ui.gridLayout.addWidget(self.factorWins[4],3,1) - self.ui.gridLayout.addWidget(self.factorWins[5],3,2) - - self.reconCurrent = _MplCanvas(subplot=211) - self.reconCurrent.ax[0].axis('Off') - self.reconCurrent.ax[1].hold('Off') - - self.reconRemainder = _MplCanvas(subplot=211) - self.reconRemainder.ax[0].axis('Off') - self.reconRemainder.ax[1].hold('Off') - - - self.ui.verticalLayout_3.insertWidget(1,self.reconCurrent) - self.ui.verticalLayout_3.insertWidget(-1,self.reconRemainder) - - for count in range(self._num_factor_visible): - self.factorLabelCheckBoxes[count].setText('Keep: ' + str(count))
- - @property - def unselected_factors(self): - all_factors = set(_np.arange(self._n_factors)) - return all_factors - self.selected_factors - -
[docs] def applyCheckBoxes(self): - """ - Add checked singular values (and remove un-checked SVs) - """ - for count, checkBox in enumerate(self.factorLabelCheckBoxes): - if checkBox.isChecked() == True: - self.selected_factors.add(self._first_factor_visible+count) - else: - try: - self.selected_factors.remove(self._first_factor_visible+count) - except: - pass - - #print('Self.S: {}'.format(self.svddata.S[0:3])) - self.ui.lcdSelectedFactors.display(len(self.selected_factors)) - self.updateCurrentRemainder()
- -
[docs] def advance(self): - """ - View next set of SVs - """ - sender = self.sender().objectName() - if sender == 'pushButtonPrev': - self.updatePlots(startnum=self._first_factor_visible-self._num_factor_visible) - elif sender == 'pushButtonNext': - self.updatePlots(startnum=self._first_factor_visible+self._num_factor_visible) - elif sender == 'pushButtonGoTo': - self.updatePlots(startnum=self.ui.spinBoxGoTo.value()) - else: - pass
-
[docs] def runScript(self): - """ - Run "script" of singular value selection - - Example: - [1,2,3,5:7] = 1,2,3,5,6,7 - """ - script = self.ui.lineEditSelections.text() - script = script.strip('[').strip(']') - script = script.split(',') - for count in script: - if ':' in count: - temp = count.split(':') - self.selected_factors.update(set(_np.arange(int(temp[0]),int(temp[1])+1))) - elif count.strip() == '': - pass - else: - self.selected_factors.add(int(count)) - self.updatePlots(startnum=self._first_factor_visible) - self.ui.lcdSelectedFactors.display(len(self.selected_factors)) - self.updateCurrentRemainder()
- -
[docs] def max_factors(self): - raise NotImplementedError('max_factors method not implemented')
- -
[docs] def combiner(self, factors=None): - raise NotImplementedError('combiner method not implemented')
- -
[docs] def mean_spatial(self, cube): - raise NotImplementedError('mean_spatial method not implemented')
- -
[docs] def mean_spectral(self, cube): - raise NotImplementedError('mean_spectral method not implemented')
- -
[docs] def get_spatial_slice(self, num): - raise NotImplementedError('get_spatial_slice method not implemented.')
- -
[docs] def get_spectral_slice(self, num): - raise NotImplementedError('get_spectral_slice method not implemented.')
- -
[docs] def updateCurrentRemainder(self): - """ - Update image reconstructed (mean over spectral vector) using remaining \ - (unselected) singular values - """ - cube_select = self.combiner(self.selected_factors) - img_select = self.mean_spatial(cube_select) - spect_select = self.mean_spectral(cube_select) - - # cube_nonselect = self.combiner(self.unselected_factors) - - # cube_nonselect = self.cube_all - cube_select - # img_nonselect = self.mean_spatial(cube_nonselect) - # spect_nonselect = self.mean_spectral(cube_nonselect) - img_nonselect = self.img_all - img_select - print('Spect_select: {}'.format(spect_select)) - print('Spect_select is None: {}'.format(spect_select is None)) - spect_nonselect = self.spect_all - spect_select - - self.reconCurrent.ax[0].cla() - self.reconCurrent.ax[1].cla() - - # s_lim = _np.abs(img_select).max() - s_lim = _np.abs(img_select.mean() + 3*img_select.std()) - - self.reconCurrent.ax[0].imshow(img_select, interpolation='None', - cmap = 'bwr', origin='lower', vmin=0, vmax=s_lim) - self.reconCurrent.ax[1].plot(spect_select) - self.reconCurrent.draw() - - self.reconRemainder.ax[0].cla() - self.reconRemainder.ax[1].cla() - - # s_lim = _np.abs(img_nonselect).max() - s_lim = _np.abs(img_nonselect.mean() + 3*img_nonselect.std()) - self.reconRemainder.ax[0].imshow(img_nonselect, interpolation='None', - cmap = 'bwr', origin='lower', vmin=-s_lim, vmax=s_lim) - self.reconRemainder.ax[1].plot(spect_nonselect) - self.reconRemainder.draw()
- - -
[docs] def updatePlots(self, startnum=0): - """ - Update images and spectra of set of singular values starting at SV \ - number startnum - """ - if startnum <= 0: - startnum = 0 - self.ui.pushButtonPrev.setEnabled(False) - self.ui.pushButtonNext.setEnabled(True) - elif startnum > self._n_factors - self._num_factor_visible: - startnum = self._n_factors - self._num_factor_visible - self.ui.pushButtonPrev.setEnabled(True) - self.ui.pushButtonNext.setEnabled(False) - else: - self.ui.pushButtonPrev.setEnabled(True) - self.ui.pushButtonNext.setEnabled(True) - - self._first_factor_visible = startnum - - for count in range(self._num_factor_visible): - self.factorWins[count].ax[0].clear() - - sl = self.get_spatial_slice(count + self._first_factor_visible) - # sl_lim = _np.abs(sl).max() - sl_lim = _np.abs(sl.mean() + 3*sl.std()) - self.factorWins[count].ax[0].imshow(sl, vmin=-sl_lim, vmax=sl_lim, - interpolation='none', - cmap = 'bwr' , origin='lower') - - self.factorWins[count].ax[0].axis('Off') - - self.factorWins[count].ax[1].clear() - self.factorWins[count].ax[1].plot(self.get_spectral_slice(count + self._first_factor_visible)) - - self.factorLabelCheckBoxes[count].setText('Keep: ' + str(startnum + count)) - self.factorWins[count].draw() - if self._first_factor_visible + count in self.selected_factors: - self.factorLabelCheckBoxes[count].setChecked(True) - else: - self.factorLabelCheckBoxes[count].setChecked(False)
- -
[docs] def clear(self): - """ - Clear selected singular values (i.e., none will be selected) - """ - self.selected_factors = set() - self.ui.lcdSelectedFactors.display(len(self.selected_factors)) - self.updateCurrentRemainder() - self.updatePlots(startnum=self._first_factor_visible)
- - -if __name__ == '__main__': - pass -# app = _QApplication(_sys.argv) -# app.setStyle('Cleanlooks') -# x = _np.linspace(100,200,50) -# y = _np.linspace(200,300,50) -# f = _np.linspace(500,3000,800) -# Ex = 30*_np.exp((-(f-1750)**2/(200**2))) -# Spectrum = _np.convolve(_np.flipud(Ex),Ex,mode='same') - -# data = _np.zeros((y.size,x.size,f.size)) - -# for count in range(y.size): -# data[count,:,:] = y[count]*_np.random.poisson(_np.dot(x[:,None],Spectrum[None,:])) - -# win = DialogAbstractFactorization.dialogAbstractFactorization(data, data.shape) ### EDIT ### - -# print(win) - - -# _sys.exit(app.exec_()) -# # _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_AbstractPlotEffect.html b/docs/build/html/_modules/crikit/ui/dialog_AbstractPlotEffect.html deleted file mode 100644 index 148eab9..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_AbstractPlotEffect.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_AbstractPlotEffect — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_AbstractPlotEffect
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_AbstractPlotEffect

-"""
-Created on Thu Dec 22 10:04:39 2016
-
-@author: chc
-"""
-
-from PyQt5.QtWidgets import (QWidget as _QWidget)
-from PyQt5.QtCore import (pyqtSignal as _pyqtSignal)
-
-
[docs]class AbstractPlotEffectPlugin(_QWidget): - - parameters = { - 'name' : 'Name', - 'long_name' : 'Longer Name' - } - - labels_orig = { - 'x_label' : 'x', - 'y_label' : 'y', - 'title' : 'Original' - } - - labels_affected = { - 'x_label' : 'x', - 'y_label' : 'y', - 'title' : 'Affected' - } - - changed = _pyqtSignal() - -# def __init__(self): -# raise NotImplementedError - -
[docs] def fcn(self, data_in): - raise NotImplementedError
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_SVD.html b/docs/build/html/_modules/crikit/ui/dialog_SVD.html deleted file mode 100644 index f543a3a..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_SVD.html +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_SVD — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_SVD
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_SVD

-"""
-Created on Mon Jul 25 13:57:24 2016
-
-@author: chc
-"""
-import sys as _sys
-# import timeit
-import numpy as _np
-
-from PyQt5.QtWidgets import (QApplication as _QApplication, QWidget as _QWidget)
-
-from crikit.ui.dialog_AbstractFactorization import DialogAbstractFactorization
-
-from scipy.linalg import diagsvd as _diagsvd
-
-
[docs]class DialogSVD(DialogAbstractFactorization): - """ - SVD Class - """ - def __init__(self, data, img_shape, mask=None, use_imag=True, img_all=None, spect_all=None, - parent=None): - super(DialogSVD, self).__init__(parent=parent) ### EDIT ### - self.setup(parent=parent) - self.setupData(img_shape=img_shape) - self.ui_changes() - - self.U = data[0] - self.s = data[1] - self.Vh = data[2] - self._n_factors = self.s.size - - self.mask = mask - - self._use_imag = use_imag # By default, use imag portion of complex data - - if (img_all is None) and (spect_all is None): - cube_all = self.combiner(selections=_np.arange(self._n_factors)) - self.img_all = self.mean_spatial(cube_all) - self.spect_all = self.mean_spectral(cube_all) - else: - self.img_all = img_all.real - if _np.iscomplexobj(spect_all): - if self._use_imag: - self.spect_all = spect_all.imag - else: - self.spect_all = spect_all.real - else: - self.spect_all = spect_all - - self.updatePlots(0) - self.updateCurrentRemainder() - -
[docs] @staticmethod - def dialogSVD(data, img_shape, mask=None, use_imag=True, img_all=None, spect_all=None, parent=None): - dialog = DialogSVD(data=data, img_shape=img_shape, mask=mask, - use_imag=use_imag, img_all=img_all, spect_all=spect_all, parent=parent) - result = dialog.exec_() - - if result == 1: - svs = list(dialog.selected_factors) - if len(svs) == 0: - svs = None - else: - svs.sort() - svs = _np.array(svs) - else: - svs = None - return svs
- -
[docs] def max_factors(self): - """ - Return maximum number of factors. Since DialogAbstractFactorization - (parent) is initialized first (before self.s), need to return None - at first. - """ - try: - return self.s.size - except: - return None
- -
[docs] def combiner(self, selections=None): - """Performs U*S*Vh""" - - # Straight-forward way, but slow - # tmr = timeit.default_timer() - # S = self.s_from_selected(selections=selections) - # ret = _np.dot(self.U, _np.dot(S, self.Vh)) - # tmr -= timeit.default_timer() - # # print('Selections: {}'.format(selections)) - # print('S (head): {}'.format(_np.diag(S)[0:10])) - # print('Old way: {}'.format(-tmr)) - - # New faster method - # tmr = timeit.default_timer() - ret = _np.dot(self.U[:, list(selections)], _np.dot(_np.diag(self.s[list(selections)]), self.Vh[list(selections), :])) - # tmr -= timeit.default_timer() - # print('S (head): {}'.format(self.s[list(selections)])) - # print('New way: {}'.format(-tmr)) - # print('Old == New: {}\n'.format(_np.allclose(ret,ret2))) - - return ret
- -
[docs] def mean_spatial(self, cube): - ret = cube.mean(axis=-1) - ret = ret.reshape((self._n_y, self._n_x)) - if _np.iscomplexobj(ret): - if self._use_imag: - return _np.imag(ret) - else: - return _np.real(ret) - else: - return ret
- -
[docs] def mean_spectral(self, cube): - ret = cube.mean(axis=0) - - if _np.iscomplexobj(ret): - if self._use_imag: - return _np.imag(ret) - else: - return _np.real(ret) - else: - return ret
- -
[docs] def s_from_selected(self, selections=None): - """ - Return SVD S-matrix of SELECTED singular values - """ - M = self.U.shape[-1] - N = self.Vh.shape[0] - - if selections is None: - S = _diagsvd(self.s, M, N) - return S - else: - if isinstance(selections, set): - selections = list(selections) - s_select = _np.zeros(self.s.size) - s_select[selections] = self.s[selections] - - S = _diagsvd(s_select, M, N) - return S
- -
[docs] def get_spatial_slice(self, num): - img = self.U[...,num].reshape((self._n_y, self._n_x)) - return _np.real(img)
- - # Used to return complex, but the SVD of complex numbers tends to - # shove everything in U into the real component - - # if _np.iscomplexobj(img): - # if self._use_imag: - # return _np.imag(img) - # else: - # return _np.real(img) - # else: - # return img - - - -
[docs] def get_spectral_slice(self, num): - spect = self.Vh[num,:] - - if _np.iscomplexobj(spect): - if self._use_imag: - return _np.imag(spect) - else: - return _np.real(spect) - else: - return spect
- -if __name__ == '__main__': - from scipy.linalg import svd as _svd - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - x = _np.linspace(100, 200, 100) - y = _np.linspace(200, 300, 100) - - - f = _np.linspace(500,3000,900) - Ex = 30*_np.exp((-(f-1750)**2/(200**2))) - Spectrum = _np.convolve(_np.flipud(Ex),Ex,mode='same') -# - hsi = _np.zeros((y.size,x.size,f.size)) -# - for count in range(y.size): - # hsi[count,:,:] = y[count]*_np.random.poisson(_np.dot(x[:,None],Spectrum[None,:])) - hsi[count,:,:] = y[count]*_np.dot(x[:,None],Spectrum[None,:]) - hsi = 0*hsi + 1j*hsi - - data = _svd(hsi.reshape((-1,f.size)), full_matrices=False) - - # Class method route - #ret = DialogSVD.main(data, hsi.shape) - #print(ret) - - # Full route - obj = _QWidget() - svs = DialogSVD.dialogSVD(data, hsi.shape, img_all=hsi.mean(axis=-1), spect_all=hsi.mean(axis=(0,1)) ,parent=obj) - - print('Factors selected: {}'.format(svs)) - -## app.exec_() - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_kkOptions.html b/docs/build/html/_modules/crikit/ui/dialog_kkOptions.html deleted file mode 100644 index 854e56e..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_kkOptions.html +++ /dev/null @@ -1,391 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_kkOptions — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_kkOptions
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_kkOptions

-"""
-Kramers-Kronig phase retrieval
-
-References
-----------
-[1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \
-Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \
-Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543.
-
-"""
-
-import sys as _sys
-import os as _os
-import numpy as _np
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QDialog as _QDialog)
-
-
-# Import from Designer-based GUI
-from crikit.ui.qt_KKOptions import Ui_Dialog as Ui_KKOptions
-
-from crikit.ui.dialog_ploteffect import (DialogPlotEffectFuture as 
-                                                _DialogPlotEffect)
-from crikit.ui.widget_KK import (widgetKK as _widgetKK)
-
-# Generic imports for MPL-incorporation
-import matplotlib as _mpl
-_mpl.use('Qt5Agg')
-_mpl.rcParams['font.family'] = 'sans-serif'
-_mpl.rcParams['font.size'] = 10
-
-
-
[docs]class DialogKKOptions(_QDialog): - """ - DialogKKOptions : Phase-Retrieval (only Kramers-Kronig currently \ - supported) options dialog - - Methods - -------- - dialogKKOptions : Used to call UI and retrieve results of dialog - - References - ---------- - [1] Y. Liu, Y. J. Lee, and M. T. Cicerone, "Broadband CARS spectral \ - phase retrieval using a time-domain Kramers-Kronig transform," \ - Opt. Lett. 34, 1363-1365 (2009). - - [2] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - NORM_TO_NRB = True - NRB_AMP = 0.0 - CARS_AMP = 0.0 - PHASE_OFFSET = 0.0 - PAD_FACTOR = 1 - - def __init__(self, parent=None, data=None): - super(DialogKKOptions, self).__init__(parent) ### EDIT ### - self.ui = Ui_KKOptions() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.doubleSpinBoxCARSAmp.setValue(self.CARS_AMP) - self.ui.doubleSpinBoxNRBAmp.setValue(self.NRB_AMP) - self.ui.doubleSpinBoxPhase.setValue(self.PHASE_OFFSET) - self.ui.checkBoxNormToNRB.setChecked(self.NORM_TO_NRB) - self.ui.spinBoxPadFactor.setValue(self.PAD_FACTOR) - - self.norm_to_nrb = self.NORM_TO_NRB - - self.data = data - - if data is None: - self.ui.pushButtonInteractive.setEnabled(False) - else: - self.ui.pushButtonInteractive.pressed.connect(self.goInteractive) - -
[docs] def goInteractive(self): - - plugin = _widgetKK() - - winPlotEffect = _DialogPlotEffect.dialogPlotEffect(self.data[1:], - x=self.data[0], - plugin=plugin, - parent=self) - - if winPlotEffect is not None: - self.ui.doubleSpinBoxCARSAmp.setValue(winPlotEffect.parameters['cars_amp_offset']) - self.ui.doubleSpinBoxNRBAmp.setValue(winPlotEffect.parameters['nrb_amp_offset']) - self.ui.checkBoxNormToNRB.setChecked(winPlotEffect.parameters['norm_to_nrb']) - self.ui.doubleSpinBoxPhase.setValue(winPlotEffect.parameters['phase_offset']) - self.ui.spinBoxPadFactor.setValue(winPlotEffect.parameters['pad_factor'])
- -
[docs] @staticmethod - def dialogKKOptions(parent=None, data=None): - """ - Retrieve dark subtraction dialog results - - Parameters - ---------- - None : None - - Returns - ---------- - out : dict{'cars_amp' : float, 'nrb_amp' : float, - 'phase_offset' : float, 'norm_to_nrb' : bool, - 'pad_factor' : int} - In order: CARS amp offset, NRB amp offset, phase offset, normalize - by NRB, pad factor - """ - dialog = DialogKKOptions(parent=parent,data=data) - - result = dialog.exec_() - - if result == 1: - ret = {} - ret['cars_amp'] = dialog.ui.doubleSpinBoxCARSAmp.value() - ret['nrb_amp'] = dialog.ui.doubleSpinBoxNRBAmp.value() - ret['phase_offset'] = dialog.ui.doubleSpinBoxPhase.value() - ret['norm_to_nrb'] = dialog.ui.checkBoxNormToNRB.isChecked() - ret['pad_factor'] = dialog.ui.spinBoxPadFactor.value() - return ret - else: - return None
- -if __name__ == '__main__': - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - -# winDark = DialogDarkOptions.dialogDarkOptions(darkloaded=True) - - from crikit.data.hsi import Hsi as _Hsi - - temp = _Hsi() - - WN = _np.linspace(500,4000,1000) - - CARS = _np.zeros((20,20,WN.size)) - CARS[:,:,:] = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - temp.data = CARS - temp.freq.data = WN - - - NRB = 0*WN + .055 - - - winKK = DialogKKOptions.dialogKKOptions(data=[WN, NRB, - temp.get_rand_spectra(10, pt_sz=3, quads=False)]) - - print('KK return: {}'.format(winKK)) - - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_model.html b/docs/build/html/_modules/crikit/ui/dialog_model.html deleted file mode 100644 index f049dd5..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_model.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_model — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_model
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_model

-"""
-Dialog for creating BCARS or Raman numerical phantom
-"""
-import sys as _sys
-
-import numpy as _np
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QWidget as _QWidget, QDialog as _QDialog,
-                             QMainWindow as _QMainWindow,
-                             QSizePolicy as _QSizePolicy,
-                             QFileDialog as _QFileDialog)
-import PyQt5.QtCore as _QtCore
-
-from crikit.ui.qt_Model import Ui_Dialog
-from crikit.datasets.model import Model
-
-
[docs]class DialogModel(_QDialog): - """ - Dialog for creating BCARS or Raman numerical phantom - """ - def __init__(self, cplx=True, parent=None): - super().__init__(parent) - self.cplx = cplx # Is dataset complex-valued - - self.ui = Ui_Dialog() - self.ui.setupUi(self) - self.ui.pushButtonCancel.setDefault(False) - self.ui.pushButtonCancel.setAutoDefault(False) - self.ui.pushButtonOk.setDefault(False) - self.ui.pushButtonOk.setAutoDefault(False) - self.ui.spinBoxSubsample.setFocus() - - self.ui.pushButtonOk.pressed.connect(self.accept) - self.ui.pushButtonCancel.pressed.connect(self.reject) - - self.ui.spinBoxSubsample.valueChanged.connect(self.changeSize) - self.ui.spinBoxStart.valueChanged.connect(self.changeSize) - self.ui.spinBoxEnd.valueChanged.connect(self.changeSize) - self.ui.spinBoxSpectrographStep.valueChanged.connect(self.changeSize) - self.ui.spinBoxProbe.valueChanged.connect(self.changeSize) - - self.changeSize() - -
[docs] def changeSize(self): - subsample = self.ui.spinBoxSubsample.value() - start = self.ui.spinBoxStart.value() - stop = self.ui.spinBoxEnd.value() - slope = self.ui.spinBoxSpectrographStep.value() - probe = self.ui.spinBoxProbe.value() - - m = Model._M - n = Model._N - - x = _np.arange(n) - y = _np.arange(m) - - rows = y[::subsample].size - cols = x[::subsample].size - - lam_start = 0.01 / (start + 0.01/(probe*1e-9)) # meters - lam_start *= 1e9 # nm - - lam_end = 0.01 / (stop + 0.01/(probe*1e-9)) # meters - lam_end *= 1e9 # nm - - lam_ctr = (lam_start + lam_end) / 2 # nm - - n_pix = _np.abs(_np.ceil((lam_end-lam_start) / slope)).astype(int) - - datasize = rows * cols * n_pix - if self.cplx: - datasize *= (128/8) # Assume complex128, for now - else: - datasize *= (64/8) # Assume float64, for now - datasize *= 1e-9 # Gigbytes (Gb) - - self.ui.spinBoxOutputColors.setValue(n_pix) - self.ui.spinBoxOutputRows.setValue(rows) - self.ui.spinBoxOutputCols.setValue(cols) - self.ui.spinBoxMemory.setValue(datasize)
-
[docs] @staticmethod - def dialogModel(cplx=True, parent=None): - """ - - """ - dialog = DialogModel(cplx=cplx, parent=parent) - result = dialog.exec_() - if result == 1: - settings = {} - settings['subsample'] = dialog.ui.spinBoxSubsample.value() - settings['wn_start'] = dialog.ui.spinBoxStart.value() - settings['wn_end'] = dialog.ui.spinBoxEnd.value() - settings['wl_slope'] = dialog.ui.spinBoxSpectrographStep.value() - settings['probe'] = dialog.ui.spinBoxProbe.value() - - settings['gnoise_bool'] = dialog.ui.checkBoxGNoise.isChecked() - settings['pnoise_bool'] = dialog.ui.checkBoxPNoise.isChecked() - settings['dark_bool'] = dialog.ui.checkBoxDark.isChecked() - - settings['gnoise_stddev'] = dialog.ui.spinBoxGStdDev.value() - settings['pnoise_gain'] = dialog.ui.spinBoxPMulti.value() - settings['dark_level'] = dialog.ui.spinBoxDark.value() - return settings - else: - return None
- -if __name__ == '__main__': - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - win = DialogModel.dialogModel(cplx=False, parent=None) - print(win) - - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_ploteffect.html b/docs/build/html/_modules/crikit/ui/dialog_ploteffect.html deleted file mode 100644 index 23aada2..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_ploteffect.html +++ /dev/null @@ -1,608 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_ploteffect — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_ploteffect
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_ploteffect

-"""
-Extensible Dialog that shows the effect of a plugin on input data.
-
-Created on Wed Dec 21 21:36:00 2016
-
-@author: chc
-"""
-import numpy as _np
-
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QDialog as _QDialog)
-
-from crikit.ui.qt_PlotEffect import Ui_Dialog as Ui_DialogPlotEffect
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin 
-                                                     as
-                                                     _AbstractPlotEffectPlugin)
-
-from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas
-
-
[docs]class DialogPlotEffectFuture(_QDialog): - """ - Extensible Dialog that shows the effect of a plugin on input data. - - Parameters - ---------- - - data : ndarray (ND) - Input data - - x : ndarray (1D) - Independent variable - - plugin : sub-class of AbstractPlotEffectPlugin - Plugin class instance - - parent : QObject - Parent - """ - - def __init__(self, data, x=None, plugin=None, parent=None): - super(DialogPlotEffectFuture, self).__init__(parent) - self.ui = Ui_DialogPlotEffect() - self.ui.setupUi(self) - - self.data = data - - # Setup MPL containers - self.mpl_orig = _MplCanvas(subplot=111) - self.mpl_affected = _MplCanvas(subplot=111) - - # Show(), although not needed, enables mpl-tight_layout - # to work later on - self.show() - - self.ui.verticalLayout.insertWidget(1, self.mpl_orig) - self.ui.verticalLayout.insertWidget(1, self.mpl_orig.toolbar) - - self.ui.verticalLayout.insertWidget(3, self.mpl_affected) - self.ui.verticalLayout.insertWidget(3, self.mpl_affected.toolbar) - - # Plugin that brings functionality to PlotEffect - self.plugin = plugin - - - # Signal emited when something changes in the plugin widget - self.plugin.changed.connect(self.widget_changed) - - # Setup indep. variable - if x is None: - self.x = _np.linspace(0,data.shape[0],self.data.shape[0]) - else: - self.x = x - - # If data is a list (assumed to be a list of ndarrays), - # plot each item in list - if isinstance(data, _np.ndarray): - try: - self.mpl_orig.ax.plot(self.x,data) - except: - self.mpl_orig.ax.plot(self.x,data.T) - elif isinstance(data, list): - for d in data: - try: - self.mpl_orig.ax.plot(self.x,d) - except: - self.mpl_orig.ax.plot(self.x,d.T) - - - self.plot_labels() - - if self.plugin is not None: - self.ui.verticalLayout.insertWidget(8, plugin) - - self.show() - self.widget_changed() - self.mpl_orig.draw() - self.mpl_affected.draw() - - self.ui.pushButtonOk.clicked.connect(self.accept) - self.ui.pushButtonCancel.clicked.connect(self.reject) - -
[docs] @staticmethod - def dialogPlotEffect(data, x = None, plugin=None, parent = None): - """ - Static method that is actually called - """ - dialog = DialogPlotEffectFuture(data, x=x, plugin=plugin, - parent=parent) - - result = dialog.exec_() # 1 = Accepted, 0 = Rejected/Canceled - - if result == 1: - return dialog.plugin - else: - return None
- -
[docs] def widget_changed(self): - """ - Plugin widget has changed. Re-submit data to plugin function. - """ - try: - affected_data = self.plugin.fcn(self.data) - except: - print('Error in plugin.fcn') - else: - # If affected_data is a list, [0] is added to the original data - # plots and is bolded - if isinstance(affected_data, list): - # Split affected data into the addon and te affected axis - # data - orig_data_addon = affected_data[0] - affected_data = affected_data[1] - - else: - orig_data_addon = None - - # If there already exists an original plot, keep those - # axis limits upon re-plotting - if len(self.mpl_orig.ax.lines) > 0: - lim_orig = self.mpl_orig.ax.axis() - else: - lim_orig = None - - self.mpl_orig.ax.clear() - - - if isinstance(self.data, _np.ndarray): - try: - self.mpl_orig.ax.plot(self.x,self.data) - except: - self.mpl_orig.ax.plot(self.x,self.data.T) - - # If data is a list (assumed to be a list of ndarrays), - # plot each item in list - elif isinstance(self.data, list): - for d in self.data: - try: - self.mpl_orig.ax.plot(self.x,d) - except: - self.mpl_orig.ax.plot(self.x,d.T) - - if orig_data_addon is not None: - try: - self.mpl_orig.ax.plot(self.x,orig_data_addon, lw=2) - except: - self.mpl_orig.ax.plot(self.x,orig_data_addon.T, lw=2) - - # If there already exists an affected plot, keep those - # axis limits upon re-plotting - if len(self.mpl_affected.ax.lines) > 0: - lim_affected = self.mpl_affected.ax.axis() - else: - lim_affected = None - - # If affected data return is None, hide the affected axis - if affected_data is None: - self.mpl_affected.setVisible(False) - self.mpl_affected.toolbar.setVisible(False) - else: - self.mpl_affected.setVisible(True) - self.mpl_affected.toolbar.setVisible(True) - - self.mpl_affected.ax.clear() - try: - self.mpl_affected.ax.plot(self.x,affected_data) - except: - self.mpl_affected.ax.plot(self.x,affected_data.T) - - self.plot_labels() # Update x-,y-, and title-labels on plots - - self.mpl_orig.fig.tight_layout() - self.mpl_affected.fig.tight_layout() - - # Reset axis limits to previous setting before re-plotting - if lim_orig is not None: - self.mpl_orig.ax.axis(lim_orig) - - # Reset axis limits to previous setting before re-plotting - if lim_affected is not None: - self.mpl_affected.ax.axis(lim_affected) - - self.mpl_orig.draw() - self.mpl_affected.draw()
- -
[docs] def plot_labels(self): - """ - Add axis labels and titles - """ - self._plot_labels_ax(self.mpl_orig.ax, self.plugin.labels_orig) - self._plot_labels_ax(self.mpl_affected.ax, self.plugin.labels_affected)
- -
[docs] def _plot_labels_ax(self, ax, labels): - for k in labels: - val = labels[k] - k_lower = k.lower() - if k_lower == 'x_label': - ax.set_xlabel(val) - elif k_lower == 'y_label': - ax.set_ylabel(val) - elif k_lower == 'title': - ax.set_title(val)
- - -
[docs]class widgetDemoPlotEffectPlugin(_AbstractPlotEffectPlugin): - """ - Very simple demo of a plugin - """ - - parameters = {'name' : 'DEMO', - 'long_name' : 'Demo of PlotEffectPlugins'} - - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Original' - } - - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Output Int (au)', - 'title' : 'Affected' - } - - def __init__(self, offset=0.1, parent=None): - super(widgetDemoPlotEffectPlugin, self).__init__(parent) ### EDIT ### - - self.parameters['offset'] = offset - -
[docs] def fcn(self, data_in): - """ - If return list, [0] goes to original, [1] goes to affected - """ - return [0*data_in + .1, data_in + .1]
- - -if __name__ == '__main__': - - import sys as _sys - - app = _QApplication(_sys.argv) - -# WN = _np.linspace(500,4000,800) - - calib_dict = {'n_pix' : 1600, - 'ctr_wl' : 730, - 'ctr_wl0' : 730, - 'a_vec' : [-0.167740721307557, 863.8736708961577], - 'probe': 771.461} - - pix = _np.arange(calib_dict['n_pix']) - wl = calib_dict['a_vec'][0]*pix + calib_dict['a_vec'][1] - WN = .01/(wl*1e-9) - .01/(calib_dict['probe']*1e-9) - - CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - NRB = 0*WN + .055 - CARS = _np.dot(_np.ones((5,1)),CARS[None,:]) - - - - NRB_LEFT = 20e3*_np.exp(-(WN)**2/(1000**2)) + 500 - NRB_RIGHT = 6e3*_np.exp(-(WN-2500)**2/(400**2)) + 500 - - NRB_LEFT[WN<500] *= 0 - NRB_LEFT[WN<500] += 1e-6 - NRB_RIGHT[WN<500] *= 0 - NRB_RIGHT[WN<500] += 1e-6 - - from crikit.cri.merge_nrbs import MergeNRBs as _MergeNRBs - from crikit.utils.general import find_nearest as _find_nearest - NRB2 = _MergeNRBs(nrb_left=NRB_LEFT, nrb_right=NRB_RIGHT, - pix=_find_nearest(WN, 1885.0)[1], - left_side_scale=False).calculate() - - CARS2 = _np.abs(500*(1/(1000-WN-1j*20) + 1/(2700-WN-1j*20)) + NRB2**0.5)**2 - CARS2 = _np.dot(_np.ones((10,1), dtype=_np.double),CARS2[None,:]) - -# # Demo -# plugin = widgetDemoPlotEffectPlugin() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -# plugin=plugin) -# if winPlotEffect is not None: -# print(winPlotEffect.parameters) -# -## # ALS -## from crikit.ui.widget_ALS import widgetALS as _widgetALS -## -## plugin = _widgetALS() -## winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -## plugin=plugin) -## if winPlotEffect is not None: -## print(winPlotEffect.parameters) -# -# # ArPLS -# from crikit.ui.widget_ArPLS import widgetArPLS as _widgetArPLS -# plugin = _widgetArPLS() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -# plugin=plugin) -# if winPlotEffect is not None: -# print(winPlotEffect.parameters) -# -# # Detrending -# from crikit.ui.widget_DeTrending import (widgetDeTrending as -# _widgetDeTrending) -# plugin = _widgetDeTrending() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -# plugin=plugin) -# if winPlotEffect is not None: -# print(winPlotEffect.parameters) -# -# # SG -# from crikit.ui.widget_SG import (widgetSG as _widgetSG) -# plugin = _widgetSG() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -# plugin=plugin) -# if winPlotEffect is not None: -# print(winPlotEffect.parameters) -# -# # KK -# from crikit.ui.widget_KK import (widgetKK as _widgetKK) -# plugin = _widgetKK() -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect([NRB,CARS], x=WN, -# plugin=plugin) -# if winPlotEffect is not None: -# print(winPlotEffect.parameters) -# -# # Calibrate -# from crikit.ui.widget_Calibrate import (widgetCalibrate as -# _widgetCalibrate) -# plugin = _widgetCalibrate(calib_dict) -# winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS, x=WN, -# plugin=plugin) -# if winPlotEffect is not None: -# print(winPlotEffect.parameters) - - # Merge NRBs - from crikit.ui.widget_mergeNRBs import (widgetMergeNRBs as - _widgetMergeNRBs) - plugin = _widgetMergeNRBs(WN, NRB_LEFT, NRB_RIGHT) - winPlotEffect = DialogPlotEffectFuture.dialogPlotEffect(CARS2, x=WN, - plugin=plugin) - if winPlotEffect is not None: - print(winPlotEffect.parameters) - - - - - - - -# print('P-Value: {}'.format(winPlotEffect.p)) -# print('Lambda-Value: {}'.format(winPlotEffect.lam)) -# print('Redux: {}'.format(winPlotEffect.redux)) -# - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_save.html b/docs/build/html/_modules/crikit/ui/dialog_save.html deleted file mode 100644 index 4de2d8f..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_save.html +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_save — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_save
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_save

-"""
-CRIkit Save Dialog (crikit.ui.dialog_save)
-=======================================================
-
-Classes that present dialog boxes that retrieve options
-
-DialogSave : Save Dialog
-
-"""
-
-# Append sys path
-import sys as _sys
-import os as _os
-import datetime as _datetime
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QWidget as _QWidget, QDialog as _QDialog,
-                             QMainWindow as _QMainWindow,
-                             QSizePolicy as _QSizePolicy,
-                             QFileDialog as _QFileDialog)
-import PyQt5.QtCore as _QtCore
-
-# Other imports
-import numpy as _np
-
-# Import from Designer-based GUI
-from crikit.ui.qt_Save import Ui_Dialog
-
-
[docs]class DialogSave(_QDialog): - """ - DialogDarkOptions : Dark subtraction options dialog - - Methods - -------- - dialogSave : Used to call UI and retrieve results of dialog - - """ - - def __init__(self, current_filename=None, current_path=None, - current_dataset_name=None, save_filename=None, - save_path=None, save_dataset_name=None, suffix=None, - parent=None): - super(DialogSave, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - self.ui.lineEditFilename.setFocus() - -# print('Current filename: {}'.format(current_filename)) - if save_filename is not None and save_filename != '': - self.filename = save_filename - elif current_filename is not None and current_filename != '': - self.filename = current_filename - else: - self.filename = None - - if save_path is not None and save_path != '': - self.path = save_path - elif current_path is not None and current_path != '': - self.path = current_path - else: - self.path = None - - if save_dataset_name is not None and save_dataset_name != '': - self.dataset_name = save_dataset_name - elif current_dataset_name is not None and current_dataset_name != '': - self.dataset_name = current_dataset_name - else: - self.dataset_name = None - - - self.current_filename=current_filename - self.current_path=current_path - self.current_dataset_name=current_dataset_name - self.save_filename=save_filename - self.save_path=save_path - self.save_dataset_name=save_dataset_name - - self.suffix = suffix - - self.ui.lineEditFilename.setText(self.filename) - self.generateFilename() - self.ui.lineEditPath.setText(self.path) - self.ui.lineEditDataset.setText(self.dataset_name) - self.ui.lineReadDataset.setText(self.dataset_name) - self.generateDatasetName() - - self.ui.buttonCancel.pressed.connect(self.reject) - self.ui.buttonOK.pressed.connect(self.accept) - - self.ui.lineEditFilename.editingFinished.connect(self.changeFilename) - self.ui.lineEditPath.editingFinished.connect(self.changePath) - self.ui.lineEditDataset.editingFinished.connect(self.changeDataset) - self.ui.buttonGetFilename.pressed.connect(self.getFilename) - self.ui.buttonGetPath.pressed.connect(self.getPath) - self.ui.buttonGenerateFilename.pressed.connect(self.generateFilename) - self.ui.buttonGenerateDatasetname.pressed.connect(self.generateDatasetName) - -
[docs] def changeFilename(self): - self.filename = self.ui.lineEditFilename.text() - self.filename = self.filename.split('.h5')[0] - self.filename = self.filename + '.h5' - - self.ui.lineEditFilename.setText(self.filename) - - if self.path is None or self.path == '': - self.ui.lineReadFileNamePath.setText('./' + self.filename) - else: - self.ui.lineReadFileNamePath.setText(self.path + self.filename)
- -
[docs] def changePath(self): - self.path = self.ui.lineEditPath.text() - self.changeFilename()
- -
[docs] def changeDataset(self): - self.dataset_name = self.ui.lineEditDataset.text() - self.ui.lineReadDataset.setText(self.dataset_name)
- -
[docs] def getFilename(self): - filename,_ = _QFileDialog.getSaveFileName(self, "Open H5 File", "./",\ - "HDF5 Files (*.h5 *.hdf);;All Files (*.*)",options=_QFileDialog.Options(4)) - - if filename != '': - self.path = _os.path.dirname(filename) + '/' - self.filename = filename.split(_os.path.dirname(filename))[1][1::] - self.ui.lineEditFilename.setText(self.filename) - self.ui.lineReadFileNamePath.setText(self.path + self.filename) - self.ui.lineEditPath.setText(self.path)
- -
[docs] def getPath(self): - path = _QFileDialog.getExistingDirectory(self) - - if path != '': - self.path = path + '/' - self.ui.lineEditPath.setText(self.path) - self.changeFilename()
- -
[docs] def generateFilename(self): - curr_time = _datetime.datetime.now() - rnd_fname = 'PROCESS_' + str(curr_time.year) + str(curr_time.month) + \ - str(curr_time.day) + '_' + str(curr_time.hour) + '_' + \ - str(curr_time.minute) + '_' + str(curr_time.second) + '_' + \ - str(curr_time.microsecond) + '.h5' - if self.filename is None or self.filename == '': - self.filename = rnd_fname - self.ui.lineEditFilename.setText(self.filename) - else: - self.filename = self.filename.split('.h5')[0] + '_' + rnd_fname - self.ui.lineEditFilename.setText(self.filename) - - if self.path is None or self.path == '': - self.ui.lineReadFileNamePath.setText('./' + self.filename) - else: - self.ui.lineReadFileNamePath.setText(self.path + self.filename)
-
[docs] def generateDatasetName(self): - if self.save_dataset_name is not None: - if self.suffix is not None: - self.dataset_name = self.save_dataset_name + self.suffix - else: - curr_time = _datetime.datetime.now() - self.dataset_name = self.save_dataset_name + '_' + str(curr_time.year) + str(curr_time.month) + \ - str(curr_time.day) + '_' + str(curr_time.hour) + '_' + \ - str(curr_time.minute) + '_' + str(curr_time.second) + '_' + \ - str(curr_time.microsecond) - elif self.current_dataset_name is not None: - if self.suffix is not None: - self.dataset_name = self.current_dataset_name + self.suffix - else: - curr_time = _datetime.datetime.now() - self.dataset_name = self.current_dataset_name + '_PROCESS_' + str(curr_time.year) + str(curr_time.month) + \ - str(curr_time.day) + '_' + str(curr_time.hour) + '_' + \ - str(curr_time.minute) + '_' + str(curr_time.second) + '_' + \ - str(curr_time.microsecond) - else: - if self.suffix is not None: - self.dataset_name = 'PROCESS_' + self.suffix - else: - curr_time = _datetime.datetime.now() - self.dataset_name = 'PROCESS_' + str(curr_time.year) + str(curr_time.month) + \ - str(curr_time.day) + '_' + str(curr_time.hour) + '_' + \ - str(curr_time.minute) + '_' + str(curr_time.second) + '_' + \ - str(curr_time.microsecond) - - self.ui.lineEditDataset.setText(self.dataset_name) - self.ui.lineReadDataset.setText(self.dataset_name)
- - - -
[docs] @staticmethod - def dialogSave(current_filename=None, current_path=None, - current_dataset_name=None, save_filename=None, - save_path=None, save_dataset_name=None, suffix=None, - parent=None): - """ - Retrieve save dialog results - - Parameters - ---------- - current_filename : str - Filename of HDF5 file from where current data resided - - current_path : str - Path to HDF5 file from where current data resided - - current_dataset_name : str - Dataset path and name where current data resided - - save_filename : str - Filename of HDF5 file where previously saved (if so) - - save_path : str - Path of HDF5 file where previously saved (if so) - - save_dataset_name : str - Dataset path and name where previously saved (if so) - - suffix : str - Suffix to append to _dataset_name based on processing steps - - NOTE : save_ parameters supercede current_ parameters - - Returns - ---------- - out : (tuple) - Filename : str - Path : str - Dataset_name_path : str - """ - dialog = DialogSave(current_filename=current_filename, - current_path=current_path, - current_dataset_name=current_dataset_name, - save_filename=save_filename, - save_path=save_path, - save_dataset_name=save_dataset_name, - suffix=suffix, parent=parent) - - result = dialog.exec_() - if result == 1: - if dialog.filename is not None and dialog.path is not None and dialog.dataset_name is not None: - return (dialog.filename, dialog.path, dialog.dataset_name) - else: - return None - else: - return None
- -if __name__ == '__main__': - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - win = DialogSave.dialogSave() - print(win) - - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_subResidualOptions.html b/docs/build/html/_modules/crikit/ui/dialog_subResidualOptions.html deleted file mode 100644 index eeb2177..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_subResidualOptions.html +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_subResidualOptions — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_subResidualOptions
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_subResidualOptions

-"""
-
-
-References
-----------
-[1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \
-Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \
-Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543.
-"""
-
-import sys as _sys
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QDialog as _QDialog)
-
-# Import from Designer-based GUI
-from crikit.ui.qt_SubResidualOptions import Ui_Dialog as Ui_ResidualOptions ### EDIT ###
-
-# Generic imports for MPL-incorporation
-import matplotlib as _mpl
-_mpl.use('Qt5Agg')
-_mpl.rcParams['font.family'] = 'sans-serif'
-_mpl.rcParams['font.size'] = 10
-
-
[docs]class DialogSubResidualOptions(_QDialog): - """ - - """ - RESIDUAL_FREQ = [-1500, -400] - - def __init__(self, parent = None): - super(DialogSubResidualOptions, self).__init__(parent) ### EDIT ### - self.ui = Ui_ResidualOptions() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.spinBoxMax.setValue(self.RESIDUAL_FREQ[0]) - self.ui.spinBoxMax.setValue(self.RESIDUAL_FREQ[1]) - - -
[docs] @staticmethod - def dialogSubResidualOptions(parent = None, - imgloaded = False, - nrbloaded = False): - """ - Retrieve dark subtraction dialog results - - Parameters - ---------- - imgloaded : (bool) - Is there an HSI image loaded? - - nrbloaded : (bool) - Is there an NRB loaded? - - Returns - ---------- - out : dict{'submain' : bool, 'subnrb' : bool, 'subrange' : list} - In order: subtract residual from image, subtract residual from NRB, - range to subtract from. - """ - dialog = DialogSubResidualOptions(parent) - - # If nrb loaded, check and enable checkbox - dialog.ui.checkBoxBG.setChecked(nrbloaded) - dialog.ui.checkBoxBG.setEnabled(nrbloaded) - dialog.subnrb = nrbloaded - - # If img is loaded, check and enable checkbox - dialog.ui.checkBoxMain.setChecked(imgloaded) - dialog.ui.checkBoxMain.setEnabled(imgloaded) - dialog.submain = imgloaded - - result = dialog.exec_() - - if result == 1: - ret = {} - freq = [dialog.ui.spinBoxMin.value(), - dialog.ui.spinBoxMax.value()] - ret['subrange'] = freq - ret['submain'] = dialog.ui.checkBoxMain.isChecked() - ret['subnrb'] = dialog.ui.checkBoxBG.isChecked() - - return ret - else: - return None
- -if __name__ == '__main__': - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - out = DialogSubResidualOptions.dialogSubResidualOptions(imgloaded=True, nrbloaded=True) - print(out) - app.exec_() - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/dialog_varstabAnscombeOptions.html b/docs/build/html/_modules/crikit/ui/dialog_varstabAnscombeOptions.html deleted file mode 100644 index 1a9113b..0000000 --- a/docs/build/html/_modules/crikit/ui/dialog_varstabAnscombeOptions.html +++ /dev/null @@ -1,308 +0,0 @@ - - - - - - - - - - - crikit.ui.dialog_varstabAnscombeOptions — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.dialog_varstabAnscombeOptions
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.dialog_varstabAnscombeOptions

-"""
-Created on Sat Jul 23 21:38:08 2016
-
-@author: chc
-"""
-import sys as _sys
-from PyQt5.QtWidgets import QApplication as _QApplication
-from PyQt5.QtWidgets import QDialog as _QDialog
-from crikit.ui.qt_AnscombeOptions import Ui_Dialog as Ui_AnscombeOptions
-
-
[docs]class DialogAnscombeOptions(_QDialog): - """ - DialogAnscombeOptions : Anscombe Transformation options dialog - - Methods - ------- - dialogAnscombeOptions : Used to call UI and retrieve results of dialog - - References - ---------- - [1] C H Camp Jr, Y J Lee, and M T Cicerone, "Quantitative, Comparable Coherent \ - Anti-Stokes Raman Scattering (CARS) Spectroscopy: Correcting Errors in Phase \ - Retrieval," Journal of Raman Spectroscopy (2016). arXiv:1507.06543. - - """ - - def __init__(self, stddev=12.44, gain=1.4, parent = None): - super(DialogAnscombeOptions, self).__init__(parent) ### EDIT ### - self.ui = Ui_AnscombeOptions() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.spinBoxGain.setValue(gain) - self.ui.spinBoxStdDev.setValue(stddev) - - -
[docs] @staticmethod - def dialogAnscombeOptions(stddev=12.44, gain=1.4, parent=None): - """ - Retrieve Anscombe Transform dialog results - - Parameters - ---------- - None : None - - Returns - ---------- - out : dict{'gain' : float, 'stddev' : float} - Standard deviation of Gaussian noise : (float) - Detector gain of Poisson noise : (float) - """ - dialog = DialogAnscombeOptions(stddev=stddev, gain=gain, - parent=parent) - - result = dialog.exec_() - - ret = {} - - ret['stddev'] = dialog.ui.spinBoxStdDev.value() - ret['gain'] = dialog.ui.spinBoxGain.value() - - if result == 1: - return ret - else: - return None
- - -if __name__ == '__main__': - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - out = DialogAnscombeOptions.dialogAnscombeOptions() - print(out) - app.exec_() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/helper_plotOptions.html b/docs/build/html/_modules/crikit/ui/helper_plotOptions.html deleted file mode 100644 index 96c6400..0000000 --- a/docs/build/html/_modules/crikit/ui/helper_plotOptions.html +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - crikit.ui.helper_plotOptions — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.helper_plotOptions
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.helper_plotOptions

-"""
-Created on Sun Oct  4 00:28:16 2015
-
-@author: camp
-"""
-
-import numpy as _np
-from PyQt5.QtGui import (QColor as _QColor)
-
-
[docs]class plotStyle: - - COLOR_DICT = {'Blue':[0, 0, 1], - 'Red':[1, 0, 0], - 'Green':[0, .5, 0], - 'Cyan':[0, .8, .8], - 'Magenta':[1, 0, 1], - 'Yellow':[.8, .8, 0] - } - - COLOR_VEC = ['Blue', 'Green', 'Red', 'Magenta', 'Yellow', 'Cyan'] - - LINEWIDTH = 1.0 - - MARKER_VEC = ['None', #none - '.', #point - ',', #pixel - 'o', #circle - 'v', #triangle_down - '^', #triangle_up - '<', #triangle_left - '>', #triangle_right - '8', #octagon - 's', #square - 'p', #pentagon - '*', #star - 'h', #hexagon1 - 'H', #hexagon2 - '+', #plus - 'x', #x - 'D', #diamond - 'd', #thin_diamond - '|', #vline - '_'] #hline - - MARKER_VEC_STR = ['None', - 'Point', - 'Pixel', - 'Circle', - 'Triangle Down', - 'Triangle Up', - 'Triangle Left', - 'Triangle Right', - 'Octagon', - 'Square', - 'Pentagon', - 'Star', - 'Hexagon 1', - 'Hexagon 2', - 'Plus', - 'X', - 'Diamond', - 'Thin Diamondd', - 'Vert Line', - 'Horiz Line'] - - MARKERSIZE=5.0 - LINESTYLE_VEC = ['-', '--', '-.', ':', 'None'] - LINESTYLE_VEC_STR = ['Solid','Dashed','Dash-Dot','Dotted','None'] - - def __init__(self, num_current_plots=0): - - color, linestyle, marker = self.getLineStyle(num_current_plots=num_current_plots) - - self.color = color - self.linewidth = self.LINEWIDTH - self.linestyle = linestyle - self.marker = marker - self.markersize = self.MARKERSIZE - - @property - def linestyle_str(self): - index = self.LINESTYLE_VEC.index(self.linestyle) - return self.LINESTYLE_VEC_STR[index] - - @property - def qcolor(self): - color = self.color - color_256 = [color[0]*255, color[1]*255, color[2]*255] - return _QColor(color_256[0], color_256[1], color_256[2]) - - @property - def marker_str(self): - index = self.MARKER_VEC.index(self.marker) - return self.MARKER_VEC_STR[index] - -
[docs] def getLineStyle(self, num_current_plots = 0): - num_colors = len(self.COLOR_VEC) - num_linestyles = len(self.LINESTYLE_VEC) - num_markers = len(self.MARKER_VEC) - - max_styles = num_colors*num_linestyles*num_markers - - if num_current_plots > max_styles: - num_current_plots = num_current_plots - max_styles - - color_iter = num_current_plots%num_colors - style_iter = int(_np.floor(num_current_plots/num_colors))%num_linestyles - marker_iter = int(_np.floor(num_current_plots/(num_colors*num_linestyles)))%num_markers - - color = self.COLOR_DICT[self.COLOR_VEC[color_iter]] - #print(style_iter) - linestyle = self.LINESTYLE_VEC[style_iter] - marker = self.MARKER_VEC[marker_iter] - - return (color, linestyle, marker)
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/helper_roiselect.html b/docs/build/html/_modules/crikit/ui/helper_roiselect.html deleted file mode 100644 index fe40ba1..0000000 --- a/docs/build/html/_modules/crikit/ui/helper_roiselect.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - - - - - - - crikit.ui.helper_roiselect — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.helper_roiselect
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.helper_roiselect

-"""
-"""
-
-# Append sys path
-import sys as _sys
-import os as _os
-
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QWidget as _QWidget,
-                             QDialog as _QDialog,
-                             QMainWindow as _QMainWindow,
-                             QSizePolicy as _QSizePolicy,
-                             QTableWidgetItem as _QTableWidgetItem,
-                             QTableView as _QTableView,
-                             QColorDialog as _QColorDialog,
-                             QDoubleSpinBox as _QDoubleSpinBox,
-                             QComboBox as _QComboBox,
-                             QPushButton as _QPushButton,
-                             QLineEdit as _QLineEdit,
-                             QStyle as _QStyle,
-                             QStyledItemDelegate as _QStyledItemDelegate)
-
-from PyQt5.QtCore import (QAbstractItemModel as _QAbstractItemModel,
-                          QAbstractTableModel as _QAbstractTableModel,
-                          QModelIndex as _QModelIndex,
-                          QVariant as _QVariant,
-                          Qt as _Qt)
-
-from PyQt5.QtGui import (QPixmap as _QPixmap,
-                         QIcon as _QIcon,
-                         QColor as _QColor)
-
-# Other imports
-import numpy as _np
-
-# Import from Designer-based GUI
-from crikit.ui.helper_plotOptions import plotStyle
-
-# Generic imports for MPL-incorporation
-import matplotlib as _mpl
-_mpl.use('Qt5Agg')
-_mpl.rcParams['font.family'] = 'sans-serif'
-_mpl.rcParams['font.size'] = 10
-_mpl.rcParams['savefig.dpi'] = 300
-_mpl.rcParams['figure.figsize'] = (4, 4)
-#_mpl.rcParams['figure.autolayout'] = True
-_mpl.rcParams['legend.fontsize'] = 10
-
-from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as _FigureCanvas, \
-    NavigationToolbar2QT as _NavigationToolbar)
-
-from matplotlib.figure import Figure as _Figure
-
-
[docs]class _PointsData: - def __init__(self, num_current_plots=0): - self.x = None - self.y = None - self.xpix = None - self.ypix = None - - self.style = plotStyle(num_current_plots)
- - -
[docs]class ImageSelection: - def __init__(self, parent=None): - self.pointdata_list = [] - - @property - def num_selections(self): - return len(self.pointdata_list) - -
[docs] def clear_all(self): - self.__init__()
- -
[docs] def append_selection(self, xpix, ypix, x=None, y=None): - pt = _PointsData(self.num_selections) - if xpix is not None: - pt.xpix = xpix - pt.ypix = ypix - - if (x is not None and y is not None): - pt.x = x - pt.y = y - else: - pt.x = xpix - pt.y = ypix - else: - pass - self.pointdata_list.append(pt)
- -if __name__ == '__main__': - - from PyQt5 import QtCore, QtGui, QtWidgets - - class Ui_MainWindow(object): - - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.resize(984, 658) - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") - self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) - self.gridLayout.setObjectName("gridLayout") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.pushbutton = QtWidgets.QPushButton('Test') - self.verticalLayout.addWidget(self.pushbutton) - self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 984, 21)) - self.menubar.setObjectName("menubar") - MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - - self.retranslateUi(MainWindow) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) - - class testWindow(_QMainWindow): - def __init__(self, parent=None): - super(testWindow, self).__init__(parent) ### EDIT ### - self.ui = Ui_MainWindow() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - def buttonPress(): - winTest.cid = winTest.ui.mpl.canvas.mpl_connect('button_press_event', pointClick) - - def pointClick(event): - if event.inaxes == winTest.ui.mpl.ax: - x = int(_np.round(event.xdata)) - y = int(_np.round(event.ydata)) - - - selectiondata.append_selection(x,y) - updatePlot() - winTest.ui.mpl.canvas.mpl_disconnect(winTest.cid) - - def updatePlot(): - winTest.ui.mpl.ax.clear() - winTest.ui.mpl.img = winTest.ui.mpl.ax.imshow(data_slice, interpolation='none', cmap = _mpl.cm.gray , origin='lower') - getx = winTest.ui.mpl.ax.get_xlim() - gety = winTest.ui.mpl.ax.get_ylim() - - winTest.ui.mpl.ax.hold(True) - for pts in selectiondata.pointdata_list: - winTest.ui.mpl.ax.plot(pts.x, pts.y, - marker='+', - markersize=pts.style.markersize, - markerfacecolor=pts.style.color, - markeredgecolor=pts.style.color, - linestyle='None') - - winTest.ui.mpl.ax.set_xlim(getx) - winTest.ui.mpl.ax.set_ylim(gety) - - winTest.ui.mpl.canvas.draw() - - class _winMpl: - def __init__(self): - self.fig = None - self.ax = None - self.img = None - self.canvas = None - self.toolbar = None - - app = _QApplication(_sys.argv) - - winTest = testWindow() - winTest.ui.mpl = _winMpl() - winTest.ui.mpl.fig = _Figure() - winTest.ui.mpl.ax = winTest.ui.mpl.fig.add_subplot(111) - - data = _np.random.rand(20,20,50) - data_slice = data[:,:,25] - - winTest.ui.mpl.img = winTest.ui.mpl.ax.imshow(data_slice, interpolation='none', cmap = _mpl.cm.gray , origin='lower') - winTest.ui.mpl.canvas = _FigureCanvas(winTest.ui.mpl.fig) - - winTest.ui.verticalLayout.insertWidget(0,winTest.ui.mpl.canvas) - - winTest.ui.pushbutton.pressed.connect(buttonPress) - - winTest.show() - - selectiondata = ImageSelection() - - _sys.exit(app.exec_()) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/subui_hdf_load.html b/docs/build/html/_modules/crikit/ui/subui_hdf_load.html deleted file mode 100644 index 3dded26..0000000 --- a/docs/build/html/_modules/crikit/ui/subui_hdf_load.html +++ /dev/null @@ -1,456 +0,0 @@ - - - - - - - - - - - crikit.ui.subui_hdf_load — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.subui_hdf_load
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.subui_hdf_load

-"""
-HDF5 LOAD DATA QDialog (crikit.vis.subguis.h5loadgui)
-=======================================================
-
-    H5LoadGUI : A graphical user interface (GUI) to select HDF5 dataset(s)
-
-    Method : H5LoadGUI.getFileDataSets()
-
-    Return (tuple) : (path [str], filename [str], dataset(s) [list], selection_made [bool])
-
-"""
-
-
-# Append sys path
-import sys as _sys
-import os as _os
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication, \
-QDialog as _QDialog, QFileDialog as _QFileDialog, \
-QTableWidgetItem as _QTableWidgetItem)
-
-# Other imports
-import numpy as _np
-import crikit.utils.h5 as _h5utils
-
-# Import from Designer-based GUI
-from crikit.ui.qt_HDFLoad import Ui_Dialog ### EDIT ###
-
-
[docs]class SubUiHDFLoad(_QDialog): ### EDIT ### - """ GUI Loader Class for H5 Files """ - - def __init__(self, parent = None): - - # Generic load/init designer-based GUI - super(SubUiHDFLoad, self).__init__(parent) ### EDIT ### - self.ui = Ui_Dialog() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - # Set static GUI parameters - - # Set signal(s)-slot(s) connection/actions - - self.ui.pushButtonOk.clicked.connect(self.accept) - self.ui.pushButtonCancel.clicked.connect(self.reject) - self.ui.dataGroupSelect.currentTextChanged.connect(self.datagroupchange) - self.ui.dataSetList.itemClicked.connect(self.datasetselected) - self.ui.filterButton.clicked.connect(self.filterlist) - self.ui.resetFilter.clicked.connect(self.datagroupchange) - # Setup GUI variables - self.path = None - self.filename = None - self.allselect=None - # Initial Actions - -
[docs] @staticmethod - def getFileDataSets(start_path='./', parent = None): - """ - Retrieve the filename and datasets selected by the user (via GUI) - - Parameters - ---------- - start_path : str - Home directory to start in - - Returns - ---------- - out : (tuple) - path : str - filename : (str) - dataset(s) : (list[str]) - """ - if start_path is None: - start_path = './' - - dialog = SubUiHDFLoad(parent) - - ret_fileopen = dialog.fileopen(start_path) - - if ret_fileopen is None: - return None - - # Execute dialog, which defined by QDialog class returns - # QDialog.Accepted or QDialog.Rejected - ret_dset_select = dialog.exec_() - if ret_dset_select == _QDialog.Rejected: - return None - elif dialog.allselect is None: - return None - else: - return (dialog.path, dialog.filename, dialog.allselect)
- -
[docs] def fileopen(self, start_path='./'): - """ Select HDF5 File """ - - if start_path is None: - start_path = './' - - filename = _QFileDialog.getOpenFileName(self, "Open H5 File", - start_path,\ - "HDF5 Files (*.h5 *.hdf);;All Files (*.*)") - - if filename[0]: - self.filename = filename[0] - self.path = _os.path.dirname(self.filename) + '/' - self.filename = self.filename.split(_os.path.dirname(self.filename))[1][1::] - - self.group_dset_dict = _h5utils.retrieve_group_dataset_dict(self.path + self.filename) - self.ui.dataGroupSelect.clear() - for count in self.group_dset_dict: - self.ui.dataGroupSelect.addItem(count) - return [self.path, self.filename] - else: - return None
-
[docs] def datagroupchange(self): - """ Action : ComboBox containing Groups with DataSets has changed""" - - #self.dsetlist = QListWidget(self.verticalLayoutWidget) - self.ui.dataSetList.clear() - self.ui.dataSetList.addItems(self.group_dset_dict[self.ui.dataGroupSelect.currentText()])
- #print('Changed') - -
[docs] def datasetselected(self): - """ Action : One or more DataSets were selected from the list """ - - #print('Selection changed') - self.currentdset = self.ui.dataGroupSelect.currentText() + '/' + \ - self.ui.dataSetList.currentItem().text() - -# print('Current Selection : {}'.format(self.currentdset)) - self.allselect = ['/' + str(self.ui.dataGroupSelect.currentText() +\ - '/' + i.text()) for i in self.ui.dataSetList.selectedItems()] - - - if len(self.allselect) == 0: - self.allselect = None - self.ui.currentDatasetText.setText('') - attrs = {} - self.ui.dataSetAttribs.setRowCount(0) - self.ui.dataSetMemo.setText('') - else: - if len(self.allselect) == 1: - self.ui.currentDatasetText.setText(self.currentdset) - else: - self.ui.currentDatasetText.setText(self.currentdset + ' ( + ' +\ - str(len(self.allselect)-1) + ' others)' ) - - self.ui.dataSetAttribs.setSortingEnabled(False) - self.ui.dataSetAttribs.setRowCount(0) - self.ui.dataSetAttribs.setColumnCount(2) - - attrs = _h5utils.retrieve_dataset_attribute_dict(self.path + self.filename,self.currentdset) - - for count, key in enumerate(attrs.keys()): - self.ui.dataSetAttribs.insertRow(self.ui.dataSetAttribs.rowCount()) - self.ui.dataSetAttribs.setItem(count,0,_QTableWidgetItem(str(key))) - temp = attrs[key] - if isinstance(temp,_np.bytes_): - self.ui.dataSetAttribs.setItem(count,1,_QTableWidgetItem(temp.decode())) - else: - self.ui.dataSetAttribs.setItem(count,1,_QTableWidgetItem(str(temp))) - - self.ui.dataSetAttribs.setSortingEnabled(True) - self.ui.dataSetAttribs.sortItems(0) - - try: - self.ui.dataSetMemo.setText(attrs['Memo'].decode()) - except: - pass
- -
[docs] def filterlist(self): - """ Action : Filter available dataset list (.ui.dataSetList) based on - include or exclude strings (or comma-separated strings) - """ - - temp_list = [] - - for count in range(self.ui.dataSetList.count()): - temp_list.append(self.ui.dataSetList.item(count).text()) - - temp_list_filt = temp_list - - # Has strings to Exclude - if self.ui.filterExcludeString.text() != '': - # Convert comma-separated string to list-of-strings - strexclude = str.split(self.ui.filterExcludeString.text(),',') - - # Strip white-space - strexclude = [str.strip(strexclude) for strexclude in strexclude] - - # Exclude Filter - for count in strexclude[0::]: - temp_list_filt = ([i for i in temp_list_filt if str.find(i,count) == -1]) - #print(count) - else: - pass - - # Has strings to Include - if self.ui.filterIncludeString.text() != '': - # Convert comma-separated string to list-of-strings - strinclude = str.split(self.ui.filterIncludeString.text(),',') - - # Strip white-space - strinclude = [str.strip(strinclude) for strinclude in strinclude] - - # Include Filter - for count in strinclude: - temp_list_filt = ([i for i in temp_list_filt if str.find(i,count) != -1]) - else: - pass - - # Update GUI - self.ui.dataSetList.clear() - self.ui.dataSetList.addItems(temp_list_filt)
- -if __name__ == '__main__': - - app = _QApplication(_sys.argv) - #win = H5LoadGUI() ### EDIT ### - result = SubUiHDFLoad.getFileDataSets() - print('Result: {}'.format(result)) - - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/utils/roi.html b/docs/build/html/_modules/crikit/ui/utils/roi.html deleted file mode 100644 index 25e3ede..0000000 --- a/docs/build/html/_modules/crikit/ui/utils/roi.html +++ /dev/null @@ -1,307 +0,0 @@ - - - - - - - - - - - crikit.ui.utils.roi — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.ui.utils.roi

-"""
-Visualization General Utilities (crikit.ui.visgentuils)
-=======================================================
-
-    roimask : Create a region-of-interest binary mask
-
-"""
-
-from matplotlib.path import Path as _Path
-import numpy as _np
-
-
-
[docs]def roimask(imgx, imgy, xvec, yvec): - """ - Create a region-of-interest binary mask from vertices. - - Parameters - ---------- - imgx : ndarray - X-axis vector in physical units - - imgy : ndarray - Y-axis vector in physical units - - xvec : ndarray - Vector of x-locations of selected points - - yvec : ndarray - Vector of y-locations of selected points - - Returns - ------- - mask : ndarray - Binary mask - - path : MPL path object - Matplotlib path object describing ROI - """ - verts = _pts_to_verts(xvec, yvec) - path = _verts_to_path(verts) - mask = _mask_from_path(imgx, imgy, path) - return (mask, path)
- - -
[docs]def _pts_to_verts(xvec, yvec): - """ - Convert points to vertices, i.e., convert from 2 1D arrays (or list) of \ - x- and y-coordinates to a list-of-lists of [x,y] pairs - """ - verts = [] - for count in range(len(xvec)): - verts.append([xvec[count],yvec[count]]) - return verts
- - -
[docs]def _verts_to_path(verts, isclose = True): - """ - Convert vertices to paths - """ - if not isclose: - verts += verts[0] - else: - pass - codes = [_Path.MOVETO] + [_Path.LINETO]*(len(verts)-2) + [_Path.CLOSEPOLY] - return _Path(verts, codes)
- - -
[docs]def _mask_from_path(x, y, path): - """ - Create mask from path - """ - X, Y = _np.meshgrid(x, y) - allpts = _np.hstack((X.flatten()[:, None], Y.flatten()[:, None])) - return _np.reshape(path.contains_points(allpts, radius=1e-12),[y.size, x.size])
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_ALS.html b/docs/build/html/_modules/crikit/ui/widget_ALS.html deleted file mode 100644 index 844d2e2..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_ALS.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_ALS — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_ALS
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_ALS

-"""
-Widget for PlotEffect that adjusts the parameters appropriate for
-asymmetric least squares (ALS)
-
-Created on Thu Dec 22 01:16:01 2016
-
-@author: chc
-"""
-import numpy as _np
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                 as _AbstractPlotEffectPlugin)
-
-from crikit.ui.qt_PlotEffect_ALS import Ui_Form as _Ui_Form
-
-from crikit.ui.widget_scientificspin import (ScientificDoubleSpinBox as
-                                             _SciSpin)
-
-from crikit.preprocess.algorithms.als import AlsCvxopt as _Als
-
-
[docs]class widgetALS(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that adjusts the parameters appropriate for - asymmetric least squares (ALS) - - Parameters - ---------- - smoothness_param : float, optional (default, 1e3) - Smoothness parameter - - asym_param : float, optional (default, 1e-4) - Assymetry parameter - - redux : int, optional (default, 1) - Reduction parameter to sub-sample input signal - - order : int, optional (default, 2) - Derivative regularization term. Order=2 for Whittaker-smoother - - fix_end_points : bool, optional (default, False) - Weight the baseline endpoints to approach equally the end-points - of the data. - - max_iter : int, optional (default, 100) - Maximum number of least-squares iterations to perform - - min_diff : float, optional (default, 1e-5) - Break iterative calculations if difference is less than min_diff - - parent: QObject - Parent - - Methods - ------- - fcn : Perform ALS detrending - - Signals: - changed : a value in the UI has changed - """ - - # Parameter dict that will be returned from PlotEffect - # Will be updated later in program to contain all parameters - # to pass to underlying algorithm - parameters = {'name' : 'ALS', - 'long_name' : 'Asymmetric least squares'} - - # Labeling options for original data plot - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Original' - } - - # Labeling options for affected data plot - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Output Int (au)', - 'title' : 'Detrended' - } - - def __init__(self, asym_param=1e-2, smoothness_param=1, redux=10, - pstart=1e-2, pend=1e-3, fixed_p=False, fix_end_points=True, - max_iter=100, min_diff=1e-6, parent = None): - - super(widgetALS, self).__init__(parent) ### EDIT ### - - self.ui = _Ui_Form() - self.ui.setupUi(self) - - # Update parameter dict - self.parameters['smoothness_param'] = smoothness_param - self.parameters['asym_param'] = asym_param - self.parameters['fixed_p'] = fixed_p - self.parameters['asym_param_start'] = pstart - self.parameters['asym_param_end'] = pend - self.parameters['redux'] = redux - self.parameters['fix_end_points'] = fix_end_points - self.parameters['max_iter'] = max_iter - self.parameters['min_diff'] = min_diff - - self.setup_asym() # Setup controls for asymmetry parameter - self.setup_smoothness() # Setup controls for smoothness parameter - - # Redux factor - self.ui.spinBoxRedux.setValue(self.parameters['redux']) - - # Fixed ends - self.ui.checkBox.setChecked(self.parameters['fix_end_points']) - - # Max iterations - self.ui.spinBoxMaxIter.setValue(self.parameters['max_iter']) - - # Min Difference - self.ui.spinBoxMinDiff = _SciSpin() - self.ui.verticalLayout_9.insertWidget(4, self.ui.spinBoxMinDiff) - self.ui.spinBoxMinDiff.setValue(self.parameters['min_diff']) - - # SIGNALS & SLOTS - self.ui.spinBoxP.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxLambda.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxRedux.editingFinished.connect(self.spinBoxChanged) - - self.ui.spinBoxPStart.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxPEnd.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxMaxIter.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxMinDiff.editingFinished.connect(self.spinBoxChanged) - - self.ui.radioButtonFixedP.clicked.connect(self.selectFixedOrLog) - self.ui.radioButtonLogLinearP.clicked.connect(self.selectFixedOrLog) - self.ui.checkBox.clicked.connect(self.selectFixedEnds) - - -
[docs] def fcn(self, data_in): - """ - If return list, [0] goes to original, [1] goes to affected - """ - - data_out = _np.zeros(data_in.shape) - baseline = _np.zeros(data_in.shape) - - if callable(self.parameters['asym_param']): - self.parameters['asym_param'] = \ - self.parameters['asym_param'](data_in.shape[-1]) - - smoothness_param = self.parameters['smoothness_param'] - asym_param = self.parameters['asym_param'] - redux = self.parameters['redux'] - fep = self.parameters['fix_end_points'] - max_iter = self.parameters['max_iter'] - min_diff = self.parameters['min_diff'] - - _als = _Als(smoothness_param=smoothness_param, - asym_param=asym_param, - redux=redux, fix_end_points=fep, - max_iter=max_iter, - min_diff=min_diff) - - if data_in.ndim == 1: - baseline = _als.calculate(data_in) - data_out = data_in - baseline - else: - for num, spectrum in enumerate(data_in): - baseline[num,:] = _als.calculate(spectrum) - data_out[num,:] = spectrum - baseline[num,:] - return [baseline, data_out]
- - -
[docs] def setup_smoothness(self): - """ - Lambda/smoothness parameter rlated - """ - - self.ui.label_2.setText('{} (Smoothness)'.format(u'\u03BB')) - self.ui.spinBoxLambda = _SciSpin() - self.ui.verticalLayout_2.insertWidget(1, self.ui.spinBoxLambda) - self.ui.spinBoxLambda.setValue(self.parameters['smoothness_param'])
- -
[docs] def setup_asym(self): - """ - P/asymmetry parameter related - """ - - - self.ui.spinBoxP = _SciSpin() - self.ui.verticalLayout.insertWidget(1, self.ui.spinBoxP) - self.ui.spinBoxP.setValue(self.parameters['asym_param']) - if self.parameters['fixed_p']: - self.ui.radioButtonFixedP.setChecked(True) - self.ui.radioButtonLogLinearP.setChecked(False) - else: - self.ui.radioButtonFixedP.setChecked(False) - self.ui.radioButtonLogLinearP.setChecked(True) - self.selectFixedOrLog() - - self.ui.spinBoxPStart = _SciSpin() - self.ui.verticalLayout_5.insertWidget(1, self.ui.spinBoxPStart) - self.ui.spinBoxPStart.setValue(self.parameters['asym_param_start']) - - self.ui.spinBoxPEnd = _SciSpin() - self.ui.verticalLayout_6.insertWidget(1, self.ui.spinBoxPEnd) - self.ui.spinBoxPEnd.setValue(self.parameters['asym_param_end'])
- -
[docs] def spinBoxChanged(self): - """ - Controller for all spinBoxes - """ - - sdr = self.sender() - - if sdr == self.ui.spinBoxPStart: - self.parameters['asym_param_start'] = self.ui.spinBoxPStart.value() - self.selectFixedOrLog() - - elif sdr == self.ui.spinBoxPEnd: - self.parameters['asym_param_end'] = self.ui.spinBoxPEnd.value() - self.selectFixedOrLog() - - elif sdr == self.ui.spinBoxLambda: - self.parameters['smoothness_param'] = self.ui.spinBoxLambda.value() - - elif sdr == self.ui.spinBoxP: - self.parameters['asym_param'] = self.ui.spinBoxP.value() - - elif sdr == self.ui.spinBoxRedux: - self.parameters['redux'] = self.ui.spinBoxRedux.value() - - elif sdr == self.ui.spinBoxMaxIter: - self.parameters['max_iter'] = self.ui.spinBoxMaxIter.value() - - elif sdr == self.ui.spinBoxMinDiff: - self.parameters['min_diff'] = self.ui.spinBoxMinDiff.value() - - self.changed.emit()
- -
[docs] def selectFixedEnds(self): - """ - Check selection of fixed end-points - """ - - self.parameters['fix_end_points'] =self.ui.checkBox.isChecked() - self.changed.emit()
- -
[docs] def selectFixedOrLog(self): - """ - Check fixed or log-linear asymmetry parameter - """ - - self.parameters['fixed_p'] = self.ui.radioButtonFixedP.isChecked() - if self.parameters['fixed_p']: - self.ui.radioButtonFixedP.setChecked(True) - self.ui.radioButtonLogLinearP.setChecked(False) - self.ui.frame_2.setEnabled(False) - self.ui.frame.setEnabled(True) -# self.p = lambda x: self.ui.spinBoxP.value() - self.parameters['asym_param'] = self.ui.spinBoxP.value() - - else: - self.ui.radioButtonFixedP.setChecked(False) - self.ui.radioButtonLogLinearP.setChecked(True) - self.ui.frame_2.setEnabled(True) - self.ui.frame.setEnabled(False) - self.parameters['asym_param'] = \ - lambda x: _np.logspace(_np.log10(self.parameters['asym_param_start']), - _np.log10(self.parameters['asym_param_end']),x) - - self.changed.emit()
- - -if __name__ == '__main__': - import sys as _sys - from PyQt5.QtWidgets import (QApplication as _QApplication) - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - winALS = widgetALS() - - winALS.show() - - app.exec_() - print(winALS.parameters) - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_ArPLS.html b/docs/build/html/_modules/crikit/ui/widget_ArPLS.html deleted file mode 100644 index ad780ca..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_ArPLS.html +++ /dev/null @@ -1,432 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_ArPLS — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_ArPLS
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_ArPLS

-"""
-Widget for PlotEffect that adjusts the parameters appropriate for
-asymmetrically reweights penalized least squares (arPLS)
-
-Created on Thu Dec 22 01:16:01 2016
-
-@author: chc
-"""
-import numpy as _np
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                     as
-                                                     _AbstractPlotEffectPlugin)
-
-from crikit.ui.qt_PlotEffect_ArPLS import Ui_Form as _Ui_Form
-
-from crikit.ui.widget_scientificspin import (ScientificDoubleSpinBox as
-                                             _SciSpin)
-
-from crikit.preprocess.algorithms.arpls import ArPlsCvxopt as _Arpls
-
-
[docs]class widgetArPLS(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that adjusts the parameters appropriate for - asymmetrically reweights penalized least squares (arPLS) - - Parameters - ---------- - smoothness_param : float, optional (default, 1e3) - Smoothness parameter - - redux : int, optional (default, 1) - Reduction parameter to sub-sample input signal - - order : int, optional (default, 2) - Derivative regularization term. Order=2 for Whittaker-smoother - - fix_end_points : bool, optional (default, False) - Weight the baseline endpoints to approach equally the end-points - of the data. - - max_iter : int, optional (default, 100) - Maximum number of least-squares iterations to perform - - min_diff : float, optional (default, 1e-5) - Break iterative calculations if difference is less than min_diff - - parent: QObject - Parent - - Methods - ------- - fcn : Perform arPLS detrending - - Signals: - changed : a value in the UI has changed - """ - - # Parameter dict that will be returned from PlotEffect - # Will be updated later in program to contain all parameters - # to pass to underlying algorithm - parameters = {'name' : 'arPLS', - 'long_name' : 'Asymmetrically reweighted penalized least \ - squares'} - - # Labeling options for original data plot - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Original' - } - - # Labeling options for affected data plot - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Output Int (au)', - 'title' : 'Detrended' - } - - def __init__(self, smoothness_param=1, redux=1, fix_end_points=True, - max_iter=100, min_diff=1e-6, parent = None): - - super(widgetArPLS, self).__init__(parent) ### EDIT ### - - self.ui = _Ui_Form() - self.ui.setupUi(self)## - - # Update parameter dict - self.parameters['smoothness_param'] = smoothness_param - self.parameters['redux'] = redux - self.parameters['fix_end_points'] = fix_end_points - self.parameters['max_iter'] = max_iter - self.parameters['min_diff'] = min_diff - - - # Lambda/smoothness parameter rlated - self.ui.label_2.setText('{} (Smoothness)'.format(u'\u03BB')) - self.ui.spinBoxLambda = _SciSpin() - self.ui.verticalLayout_2.insertWidget(1, self.ui.spinBoxLambda) - self.ui.spinBoxLambda.setValue(self.parameters['smoothness_param']) - - # Redux factor - self.ui.spinBoxRedux.setValue(self.parameters['redux']) - - # Fixed ends - self.ui.checkBox.setChecked(self.parameters['fix_end_points']) - - # Max iterations - self.ui.spinBoxMaxIter.setValue(self.parameters['max_iter']) - - # Min Difference - self.ui.spinBoxMinDiff = _SciSpin() - self.ui.verticalLayout_9.insertWidget(4, self.ui.spinBoxMinDiff) - self.ui.spinBoxMinDiff.setValue(self.parameters['min_diff']) - - # SIGNALS & SLOTS - self.ui.spinBoxLambda.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxRedux.editingFinished.connect(self.spinBoxChanged) - - self.ui.spinBoxMaxIter.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxMinDiff.editingFinished.connect(self.spinBoxChanged) - - self.ui.checkBox.clicked.connect(self.selectFixedEnds) - - -
[docs] def fcn(self, data_in): - """ - If return list, [0] goes to original, [1] goes to affected - """ - - data_out = _np.zeros(data_in.shape) - baseline = _np.zeros(data_in.shape) - - smoothness_param = self.parameters['smoothness_param'] - redux = self.parameters['redux'] - fep = self.parameters['fix_end_points'] - max_iter = self.parameters['max_iter'] - min_diff = self.parameters['min_diff'] - - _arpls = _Arpls(smoothness_param=smoothness_param, - redux=redux, fix_end_points=fep, - max_iter=max_iter, - min_diff=min_diff, verbose=False) - - if data_in.ndim == 1: - baseline = _arpls.calculate(data_in) - data_out = data_in - baseline - else: - for num, spectrum in enumerate(data_in): - baseline[num,:] = _arpls.calculate(spectrum) - data_out[num,:] = spectrum - baseline[num,:] - return [baseline, data_out]
- - -
[docs] def spinBoxChanged(self): - """ - Controller for all spinBoxes - """ - - sdr = self.sender() - - if sdr == self.ui.spinBoxLambda: - self.parameters['smoothness_param'] = self.ui.spinBoxLambda.value() - - elif sdr == self.ui.spinBoxRedux: - self.parameters['redux'] = self.ui.spinBoxRedux.value() - - elif sdr == self.ui.spinBoxMaxIter: - self.parameters['max_iter'] = self.ui.spinBoxMaxIter.value() - - elif sdr == self.ui.spinBoxMinDiff: - self.parameters['min_diff'] = self.ui.spinBoxMinDiff.value() - - self.changed.emit()
- -
[docs] def selectFixedEnds(self): - """ - Check selection of fixed end-points - """ - - self.parameters['fix_end_points'] =self.ui.checkBox.isChecked() - self.changed.emit()
- - -if __name__ == '__main__': - import sys as _sys - from PyQt5.QtWidgets import (QApplication as _QApplication) - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - winArPLS = widgetArPLS() - - winArPLS.show() - - app.exec_() - print(winArPLS.parameters) - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_Calibrate.html b/docs/build/html/_modules/crikit/ui/widget_Calibrate.html deleted file mode 100644 index f8b657a..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_Calibrate.html +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_Calibrate — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_Calibrate
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_Calibrate

-"""
-Widget for PlotEffect that adjusts the parameters appropriate for
-calibration
-
-Created on Thu Dec 22 14:27:46 2016
-
-@author: chc
-"""
-import copy as _copy
-
-import numpy as _np
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                 as _AbstractPlotEffectPlugin)
-
-from scipy.interpolate import UnivariateSpline as _UnivariateSpline
-
-from crikit.data.frequency import (calib_pix_wn as _calib_pix_wn)
-
-#from crikit.utils.general import find_nearest as _find_nearest
-
-from crikit.ui.qt_PlotEffect_Calibrate import Ui_Form as _Ui_Form
-
-
-
[docs]class widgetCalibrate(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that adjusts the parameters appropriate for - calibration - - Parameters - ---------- - calib_dict : dict - Calibration dictionary - - Methods - ------- - fcn : Perform arPLS detrending - - Signals: - changed : a value in the UI has changed - - """ - # Parameter dict that will be returned from PlotEffect - # Will be updated later in program to contain all parameters - # to pass to underlying algorithm - parameters = {'name' : 'Calibrate', - 'long_name' : 'Spectral Calibration'} - - # Labeling options for original data plot - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Uncalibrated' - } - - # Labeling options for affected data plot - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Output Int (au)', - 'title' : 'Calibrated' - } - - def __init__(self, calib_dict, parent=None): - super(widgetCalibrate, self).__init__(parent) ### EDIT ### - - self.ui = _Ui_Form() - self.ui.setupUi(self) - - self.parameters['orig_calib_dict'] = calib_dict - - if isinstance(self.parameters['orig_calib_dict']['a_vec'], tuple): - self.parameters['orig_calib_dict']['a_vec'] = \ - list(self.parameters['orig_calib_dict']['a_vec']) - - self.parameters['new_calib_dict'] = \ - _copy.deepcopy(self.parameters['orig_calib_dict']) - - self.setup_calib() -# self.orig_wn = _calib_pix_wn(self.parameters['orig_calib_dict']) -# self.new_wn = _calib_pix_wn(self.parameters['new_calib_dict']) - - self.ui.spinBoxMeas.setValue(1004.0) - self.ui.spinBoxCorrect.setValue(1004.0) - - # SIGNALS & SLOTS - # New - self.ui.spinBoxNPix_2.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxCenterWL_2.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxProbeWL_2.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxIntercept_2.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxSlope_2.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxCalibWL_2.editingFinished.connect(self.spinBoxChanged) - - self.ui.spinBoxCorrect.editingFinished.connect(self.meas_vs_ideal) - self.ui.spinBoxMeas.editingFinished.connect(self.meas_vs_ideal) - -
[docs] def spinBoxChanged(self): - """ - Controller for all spinBoxes - """ - - sdr = self.sender() - - # Original - if sdr == self.ui.spinBoxNPix_2: - self.parameters['new_calib_dict']['n_pix'] = \ - self.ui.spinBoxNPix_2.value() - - elif sdr == self.ui.spinBoxCenterWL_2: - self.parameters['new_calib_dict']['ctr_wl'] = \ - self.ui.spinBoxCenterWL_2.value() - - elif sdr == self.ui.spinBoxCalibWL_2: - self.parameters['new_calib_dict']['ctr_wl0'] = \ - self.ui.spinBoxCalibWL_2.value() - - elif sdr == self.ui.spinBoxSlope_2: - self.parameters['new_calib_dict']['a_vec'][0] = \ - self.ui.spinBoxSlope_2.value() - - elif sdr == self.ui.spinBoxIntercept_2: - self.parameters['new_calib_dict']['a_vec'][1] = \ - self.ui.spinBoxIntercept_2.value() - - elif sdr == self.ui.spinBoxProbeWL_2: - self.parameters['new_calib_dict']['probe'] = \ - self.ui.spinBoxProbeWL_2.value() - - self.changed.emit()
- -
[docs] def meas_vs_ideal(self): - meas = self.ui.spinBoxMeas.value() - ideal = self.ui.spinBoxCorrect.value() - - delta_lambda = (1 / ((ideal / 1e7) + - (1 / self.parameters['orig_calib_dict']['probe'])) - - 1 / ((meas/1e7) + - (1 / self.parameters['orig_calib_dict']['probe']))) - - self.parameters['new_calib_dict']['a_vec'][1] = \ - self.parameters['orig_calib_dict']['a_vec'][1] + delta_lambda - - self.setup_calib() - self.changed.emit()
- -
[docs] def fcn(self, data_in): - """ - Returns a shifted version of the input spectrum to mimic the effect - of calibration. (Real calibration doesn't shift the spectrum, but - rather the independent variable) - - """ - orig_wn = _calib_pix_wn(self.parameters['orig_calib_dict'])[0] - new_wn = _calib_pix_wn(self.parameters['new_calib_dict'])[0] - - if data_in.ndim == 1: - spl = _UnivariateSpline(new_wn, data_in, s=0, ext=0) - output = spl(orig_wn) - elif data_in.ndim == 2: - output = _np.zeros(data_in.shape) - for num, spect in enumerate(data_in): - spl = _UnivariateSpline(new_wn, spect, s=0, ext=0) - output[num,:] = spl(orig_wn) - return output
- -
[docs] def setup_calib(self): - - # Original - self.ui.spinBoxNPix.setValue(self.parameters['orig_calib_dict']['n_pix']) - self.ui.spinBoxCenterWL.setValue(self.parameters['orig_calib_dict']['ctr_wl']) - self.ui.spinBoxCalibWL.setValue(self.parameters['orig_calib_dict']['ctr_wl0']) - self.ui.spinBoxSlope.setValue(self.parameters['orig_calib_dict']['a_vec'][0]) - self.ui.spinBoxIntercept.setValue(self.parameters['orig_calib_dict']['a_vec'][1]) - self.ui.spinBoxProbeWL.setValue(self.parameters['orig_calib_dict']['probe']) - - # New - self.ui.spinBoxNPix_2.setValue(self.parameters['new_calib_dict']['n_pix']) - self.ui.spinBoxCenterWL_2.setValue(self.parameters['new_calib_dict']['ctr_wl']) - self.ui.spinBoxProbeWL_2.setValue(self.parameters['new_calib_dict']['probe']) - self.ui.spinBoxIntercept_2.setValue(self.parameters['new_calib_dict']['a_vec'][1]) - self.ui.spinBoxSlope_2.setValue(self.parameters['new_calib_dict']['a_vec'][0]) - self.ui.spinBoxCalibWL_2.setValue(self.parameters['new_calib_dict']['ctr_wl0'])
- - -if __name__ == '__main__': - import sys as _sys - from PyQt5.QtWidgets import (QApplication as _QApplication) - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - - calib_dict = {'n_pix' : 1600, - 'ctr_wl' : 730, - 'ctr_wl0' : 730, - 'a_vec' : [-0.167740721307557, 863.8736708961577], - 'probe': 771.461} - - pix = _np.arange(calib_dict['n_pix']) - wl = calib_dict['a_vec'][0]*pix + calib_dict['a_vec'][1] - WN = .01/(wl*1e-9) - .01/(calib_dict['probe']*1e-9) - - CARS = _np.abs(1/(1000-WN-1j*20) + 1/(3000-WN-1j*20) + .055) - NRB = 0*WN + .055 - CARS = _np.dot(_np.ones((5,1)),CARS[None,:]) - - - winCalib = widgetCalibrate(calib_dict) - winCalib.show() - - - app.exec_() - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_DeTrending.html b/docs/build/html/_modules/crikit/ui/widget_DeTrending.html deleted file mode 100644 index 89bf74e..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_DeTrending.html +++ /dev/null @@ -1,378 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_DeTrending — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_DeTrending
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_DeTrending

-"""
-Widget for PlotEffect that contains and presents different detrending
-algorithms. Whichever algorithm is plugged in effectively acts as the
-widget as far as PlotEffect is concerned.
-
-Created on Wed Dec  7 13:36:48 2016
-
-@author: chc
-"""
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QRadioButton as _QRadioButton,
-                             QButtonGroup as _QButtonGroup)
-
-from crikit.ui.qt_PlotEffect_DeTrending import Ui_Form as _Ui_Form
-
-# At Minimum import ALS
-from crikit.ui.widget_ALS import widgetALS
-_widget_list_names = ['ALS']
-_widget_list_classes = [widgetALS]
-
-# Try to add arPLS to detrend options
-try:
-    from crikit.ui.widget_ArPLS import widgetArPLS
-except:
-    pass
-else:
-    _widget_list_names.append('ArPLS')
-    _widget_list_classes.append(widgetArPLS)
-    
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                 as _AbstractPlotEffectPlugin)
-
-
[docs]class widgetDeTrending(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that contains and presents different detrending - algorithms. Whichever algorithm is plugged in effectively acts as the - widget as far as PlotEffect is concerned. - - """ - - def __init__(self, parent = None): - super(widgetDeTrending, self).__init__(parent) ### EDIT ### - self.ui = _Ui_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - self.ui.widget_list_names = _widget_list_names - self.ui.widget_list = [] - for cl in _widget_list_classes: - self.ui.widget_list.append(cl()) - - self.ui.buttonGroup = _QButtonGroup() - self.ui.radio_button_list = [] - - for num, (wdgt, name) in enumerate(zip(self.ui.widget_list, - self.ui.widget_list_names)): - - self.ui.verticalLayoutWidgets.insertWidget(num, wdgt) - self.ui.radio_button_list.append(_QRadioButton(name)) - self.ui.verticalLayoutButtons.insertWidget(num, self.ui.radio_button_list[num]) - self.ui.buttonGroup.addButton(self.ui.radio_button_list[num],0) - if num == 0: - wdgt.setVisible(True) - self.ui.radio_button_list[0].setChecked(True) - self.fcn = wdgt.fcn - self.parameters = wdgt.parameters - self.labels_orig = wdgt.labels_orig - self.labels_affected = wdgt.labels_affected - - # Connect the changed-signal from the active widget - # to this container's version of the change-signal - try: - wdgt.changed.connect(self.widgetOptionsChanged) - except: - pass - else: - wdgt.setVisible(False) - try: - wdgt.changed.disconnect(self.widgetOptionsChanged) - except: - pass - - # SIGNALS & SLOTS - - # Active widget changed - self.ui.buttonGroup.buttonClicked.connect(self.changeWidget) - -
[docs] def widgetOptionsChanged(self): - """ - Options within the active widget were changed - """ - self.changed.emit()
- -
[docs] def changeWidget(self, buttonId): - """ - Change active widget - """ - - selection = self.ui.radio_button_list.index(buttonId) - - for num, (wdgt, name) in enumerate(zip(self.ui.widget_list, - self.ui.widget_list_names)): - if num == selection: - wdgt.setVisible(True) - self.ui.radio_button_list[num].setChecked(True) - self.fcn = wdgt.fcn - self.parameters = wdgt.parameters - self.labels_orig = wdgt.labels_orig - self.labels_affected = wdgt.labels_affected - - # Connect the changed-signal from the active widget - # to this container's version of the change-signal - try: - wdgt.changed.connect(self.widgetOptionsChanged) - except: - pass - else: - wdgt.setVisible(False) - - # Disconnect non-active widget's changed-signal - try: - wdgt.changed.disconnect(self.widgetOptionsChanged) - except: - pass - - self.changed.emit()
- - -if __name__ == '__main__': - - import sys as _sys - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - win = widgetDeTrending() - - win.show() - - app.exec_() - print(win.parameters) - _sys.exit() - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_Jupyter.html b/docs/build/html/_modules/crikit/ui/widget_Jupyter.html deleted file mode 100644 index e6ad1b7..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_Jupyter.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_Jupyter — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_Jupyter
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_Jupyter

-"""
-Created on Wed Mar  2 17:12:54 2016
-
-@author: chc
-"""
-
-import os
-os.environ['QT_API'] = 'pyqt5'
-
-from PyQt5 import QtWidgets
-from PyQt5 import QtGui
-# ipython won't work if this is not correctly installed. And the error message will be misleading
-from PyQt5 import QtSvg 
-
-# Import the console machinery from ipython
-from qtconsole.rich_jupyter_widget import RichJupyterWidget
-from qtconsole.inprocess import QtInProcessKernelManager
-#from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
-#from IPython.qt.inprocess import QtInProcessKernelManager
-
-
-
[docs]class QJupyterWidget(RichJupyterWidget): - """ Convenience class for a live IPython console widget. We can replace the standard banner using the customBanner argument""" - def __init__(self,customBanner=None,*args,**kwargs): - super(QJupyterWidget, self).__init__(*args,**kwargs) - if customBanner!=None: self.banner=customBanner - self.kernel_manager = kernel_manager = QtInProcessKernelManager() - kernel_manager.start_kernel() - kernel_manager.kernel.gui = 'qt' - - self.kernel_client = kernel_client = self._kernel_manager.client() - kernel_client.start_channels() - - def stop(): - kernel_client.stop_channels() - kernel_manager.shutdown_kernel() - #get_app_qt5().exit() - self.exit_requested.connect(stop) - -
[docs] def pushVariables(self,variableDict): - """ Given a dictionary containing name / value pairs, push those variables to the IPython console widget """ - self.kernel_manager.kernel.shell.push(variableDict)
-
[docs] def clearTerminal(self): - """ Clears the terminal """ - self._control.clear()
-
[docs] def printText(self,text): - """ Prints some plain text to the console """ - self._append_plain_text(text, False)
- - - -
[docs] def executeCommand(self,command): - """ Execute a command in the frame of the console widget """ - self._execute(command,False)
- -if __name__ == '__main__': - class ExampleWidget(QtWidgets.QMainWindow): - """ Main GUI Window including a button and IPython Console widget inside vertical layout """ - def __init__(self, parent=None): - super(ExampleWidget, self).__init__(parent) - self.setWindowTitle('iPython in PyQt5 app example') - self.mainWidget = QtWidgets.QWidget(self) - self.setCentralWidget(self.mainWidget) - layout = QtWidgets.QVBoxLayout(self.mainWidget) - self.button = QtWidgets.QPushButton('Another widget') - self.ipyConsole = QJupyterWidget(customBanner="Welcome to the embedded ipython console\n") - layout.addWidget(self.button) - layout.addWidget(self.ipyConsole) - # This allows the variable foo and method print_process_id to be accessed from the ipython console - self.ipyConsole.pushVariables({"foo":43,"print_process_id":print_process_id}) - self.ipyConsole.printText("The variable 'foo' and the method 'print_process_id()' are available. Use the 'whos' command for information.\n\nTo push variables run this before starting the UI:\n ipyConsole.pushVariables({\"foo\":43,\"print_process_id\":print_process_id})") - self.setGeometry(300, 300, 800, 600) - - def print_process_id(): - print('Process ID is:', os.getpid()) - - def get_app_qt5(*args, **kwargs): - """Create a new qt5 app or return an existing one.""" - app = QtWidgets.QApplication.instance() - if app is None: - if not args: - args = ([''],) - app = QtWidgets.QApplication(*args, **kwargs) - return app - - - app = get_app_qt5() - widget = ExampleWidget() - - widget.show() - - - app.exec_() - - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_KK.html b/docs/build/html/_modules/crikit/ui/widget_KK.html deleted file mode 100644 index 4d2f50c..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_KK.html +++ /dev/null @@ -1,437 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_KK — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.ui.widget_KK

-"""
-Widget for PlotEffect that adjusts the parameters appropriate for
-the Kramers-Kronig relation
-
-Created on Thu Dec 22 11:43:42 2016
-
-@author: chc
-"""
-import numpy as _np
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                 as _AbstractPlotEffectPlugin)
-
-from crikit.ui.qt_PlotEffect_KK import Ui_Form as _Ui_Form
-
-from crikit.cri.kk import KramersKronig as _KramersKronig
-
-
[docs]class widgetKK(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that adjusts the parameters appropriate for - the Kramers-Kronig (KK) relation phase retrieval. - - Attributes - ---------- - cars_amp_offset : float, optional (default=0.0) - DC offset applied to CARS spectrum(a) prior to KK relation. - - nrb_amp_offset : float, optional (default=0.0) - DC offset applied to NRB spectrum(a) prior to KK relation. - - phase_offset : float or ndarray, optional (default=0.0) - Phase constant or ndarray applied to retrieved phase prior to - separating the real and imaginary components. - - norm_to_nrb : bool, optional (default=True) - Normalize the amplitude by sqrt(NRB). This effectively removes several \ - system reponse functions. - - pad_factor : int, optional (default=1) - Multiple size of spectral-length to pad the ends of each spectra with. \ - Padded with a constant value corresponding to the value at that end of \ - the spectrum. - - Methods - --------- - fcn : Performs the KK - - Signals: - changed : a value in the UI has changed - - """ - - # Parameter dict that will be returned from PlotEffect - # Will be updated later in program to contain all parameters - # to pass to underlying algorithm - parameters = {'name' : 'KK', - 'long_name' : 'Kramers-Kronig Relation'} - - # Labeling options for original data plot - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Original' - } - - # Labeling options for affected data plot - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Raman-Like Int (au)', - 'title' : 'KK-Raman' - } - - def __init__(self, cars_amp_offset=0.0, nrb_amp_offset=0.0, - phase_offset=0.0, norm_to_nrb=True, pad_factor=1, - parent = None): - - super(widgetKK, self).__init__(parent) - - self.ui = _Ui_Form() - self.ui.setupUi(self) - - self.lock_cars_nrb_bias = True - - # Update parameter dict - self.parameters['cars_amp_offset'] = cars_amp_offset - self.parameters['nrb_amp_offset'] = nrb_amp_offset - self.parameters['phase_offset'] = phase_offset - self.parameters['norm_to_nrb'] = norm_to_nrb - self.parameters['pad_factor'] = pad_factor - - self.setupKK() - -
[docs] def setupKK(self): - - self.ui.checkBoxNRBNorm.setChecked(self.parameters['norm_to_nrb']) - self.ui.checkBoxLockBias.setChecked(self.lock_cars_nrb_bias) - - self.ui.spinBoxCARSBias.setValue(self.parameters['cars_amp_offset']) - self.ui.spinBoxNRBBias.setValue(self.parameters['nrb_amp_offset']) - self.ui.spinBoxPhaseLin.setValue(self.parameters['phase_offset']) - self.ui.spinBoxPadFactor.setValue(self.parameters['pad_factor']) - - # SIGNALS & SLOTS - self.ui.spinBoxCARSBias.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxNRBBias.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxPhaseLin.editingFinished.connect(self.spinBoxChanged) - self.ui.spinBoxPadFactor.editingFinished.connect(self.spinBoxChanged) - - self.ui.checkBoxNRBNorm.clicked.connect(self.changeCheckBoxNRBNorm) - self.ui.checkBoxLockBias.clicked.connect(self.changeCheckBoxLockBias) - - self.ui.spinBoxNRBBias.setEnabled(not self.lock_cars_nrb_bias)
- - -
[docs] def fcn(self, data_in): - """ - If return list, [0] goes to original, [1] goes to affected - """ - - assert isinstance(data_in, list), 'KK plot effect fcn requires the \ - data input be a list with length 2: NRB, CARS' - - assert len(data_in), 'KK plot effect fcn requires the \ - data input be a list with length 2: NRB, CARS' - - nrb = data_in[0] - cars = data_in[1] - - data_out = _np.zeros(cars.shape, dtype=_np.complex) - - cars_amp_offset = self.parameters['cars_amp_offset'] - nrb_amp_offset = self.parameters['nrb_amp_offset'] - phase_offset = self.parameters['phase_offset'] - norm_to_nrb = self.parameters['norm_to_nrb'] - pad_factor = self.parameters['pad_factor'] - - _kk = _KramersKronig(cars_amp_offset=cars_amp_offset, - nrb_amp_offset=nrb_amp_offset, - phase_offset=phase_offset, - norm_to_nrb=norm_to_nrb, - pad_factor=pad_factor) - - data_out = _kk.calculate(cars, nrb) - - return data_out.imag
- -
[docs] def spinBoxChanged(self): - """ - Controller for all spinBoxes - """ - - sdr = self.sender() - - if sdr == self.ui.spinBoxCARSBias: - self.parameters['cars_amp_offset'] = self.ui.spinBoxCARSBias.value() - if self.lock_cars_nrb_bias: - self.parameters['nrb_amp_offset'] = \ - self.ui.spinBoxCARSBias.value() - self.ui.spinBoxNRBBias.setValue(self.parameters['nrb_amp_offset']) - - elif sdr == self.ui.spinBoxNRBBias: - self.parameters['nrb_amp_offset'] = self.ui.spinBoxNRBBias.value() - - elif sdr == self.ui.spinBoxPhaseLin: - self.parameters['phase_offset'] = self.ui.spinBoxPhaseLin.value() - - elif sdr == self.ui.spinBoxPadFactor: - self.parameters['pad_factor'] = self.ui.spinBoxPadFactor.value() - - self.changed.emit()
- -
[docs] def changeCheckBoxLockBias(self): - if self.ui.checkBoxLockBias.isChecked(): - self.ui.spinBoxNRBBias.setEnabled(False) - self.lock_cars_nrb_bias = True - else: - self.ui.spinBoxNRBBias.setEnabled(True) - self.lock_cars_nrb_bias = False - self.changed.emit()
- -
[docs] def changeCheckBoxNRBNorm(self): - if self.ui.checkBoxNRBNorm.isChecked(): - self.parameters['norm_to_nrb'] = True - else: - self.parameters['norm_to_nrb'] = False - self.changed.emit()
- -
[docs] def changeSpinBoxPadFactor(self): - self.parameters['pad_factor'] = self.ui.spinBoxPadFactor.value() - self.changed.emit()
- - -if __name__ == '__main__': - import sys as _sys - from PyQt5.QtWidgets import (QApplication as _QApplication) - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - win = widgetKK() - win.show() - - app.exec_() - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_SG.html b/docs/build/html/_modules/crikit/ui/widget_SG.html deleted file mode 100644 index be31d86..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_SG.html +++ /dev/null @@ -1,361 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_SG — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.ui.widget_SG

-"""
-Widget for PlotEffect that adjusts the parameters appropriate for
-Savitky-Golay filtering
-
-Created on Thu Dec 22 11:18:36 2016
-
-@author: chc
-"""
-
-from scipy.signal import savgol_filter as _sg
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                 as _AbstractPlotEffectPlugin)
-
-from crikit.ui.qt_PlotEffect_SG import Ui_Form as _Ui_Form
-
-
[docs]class widgetSG(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that adjusts the parameters appropriate for - Savitky-Golay filtering - - - Parameters - ---------- - window_length : int - Window length - - polyorder : int - Polynomial order - - parent : QObject - Parent - - Methods - --------- - fcn : Performs the Savitky-Golay - - Signals: - changed : a value in the UI has changed - - """ - - # Parameter dict that will be returned from PlotEffect - # Will be updated later in program to contain all parameters - # to pass to underlying algorithm - parameters = {'name' : 'SG', - 'long_name' : 'Savitky-Golay filtering'} - - # Labeling options for original data plot - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Original' - } - - # Labeling options for affected data plot - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Difference (au)', - 'title' : 'Difference' - } - - - def __init__(self, window_length=601, polyorder=2, parent = None): - super(widgetSG, self).__init__(parent) - self.ui = _Ui_Form() ### EDIT ### - self.ui.setupUi(self) ### EDIT ### - - # Update parameter dict - self.parameters['window_length'] = window_length - self.parameters['polyorder'] = polyorder - - # Window size must be > polyorder - if self.parameters['window_length'] <= self.parameters['polyorder']: - self.parameters['window_length'] = self.parameters['polyorder'] + 1 - - # Window size must be odd - if self.parameters['window_length'] % 2 == 1: - pass - else: - self.parameters['window_length'] += 1 - - self.ui.spinBoxWinSize.setValue(self.parameters['window_length']) - self.ui.spinBoxOrder.setValue(self.parameters['polyorder']) - - # SIGNALS & SLOTS - self.ui.spinBoxWinSize.editingFinished.connect(self.changeWinSize) - self.ui.spinBoxOrder.editingFinished.connect(self.changeOrder) - -
[docs] def fcn(self, data_in): - """ - If return list, [0] goes to original, [1] goes to affected - """ - - baseline = _sg(data_in, window_length=self.parameters['window_length'], - polyorder=self.parameters['polyorder'], axis=-1) - data_out = data_in - baseline - - return [baseline, data_out]
- -
[docs] def changeWinSize(self): - temp_win_size = self.ui.spinBoxWinSize.value() - if temp_win_size % 2 == 1: - self.parameters['window_length'] = temp_win_size - else: - self.ui.spinBoxWinSize.setValue(temp_win_size + 1) - self.parameters['window_length'] = temp_win_size + 1 - self.changed.emit()
- -
[docs] def changeOrder(self): - self.parameters['polyorder'] = self.ui.spinBoxOrder.value() - self.changed.emit()
- -if __name__ == '__main__': - import sys as _sys - from PyQt5.QtWidgets import (QApplication as _QApplication) - - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - win = widgetSG() - - win.show() - - app.exec_() - print(win.parameters) - _sys.exit() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_images.html b/docs/build/html/_modules/crikit/ui/widget_images.html deleted file mode 100644 index 3dc5304..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_images.html +++ /dev/null @@ -1,912 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_images — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_images
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_images

-"""
-Visualization Widgets (crikit.ui.widget_images)
-=======================================================
-
-widgetColorMath : Mathematical operations on raw data leading to color \
-    images
-
-widgetBWImg : Grayscale imagery
-
-widgetSglColor : Single-color imagery
-
-widgetCompositeColor : Composite-color imagery
-
-_mplWin : Matplotlib window container
-
-"""
-
-import sys as _sys
-import numpy as _np
-
-# Generic imports for QT-based programs
-from PyQt5.QtWidgets import (QApplication as _QApplication,
-                             QWidget as _QWidget,
-                             QSizePolicy as _QSizePolicy,
-                             QColorDialog as _QColorDialog,
-                             QHBoxLayout as _QHBoxLayout)
-
-import PyQt5.QtCore as _QtCore
-
-# Import from Designer-based GUI
-from crikit.ui.qt_CompositeColor import Ui_Form as Ui_CompositeColor_Form
-from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas
-from crikit.ui.qt_GrayScaleImgInfoBar import Ui_formWidgetGrayScaleImgInfoBar as Ui_GrayImgInfoBar
-from crikit.ui.qt_ColorModeSetting import Ui_Form as Ui_ColorModeSetting
-from crikit.ui.qt_BlankLayout import Ui_Form as Ui_Blank
-from crikit.ui.qt_PopSpectrumGS import Ui_Form as Ui_PopSpectrumGS
-from crikit.ui.qt_ImageGainMath import Ui_Form as Ui_ImageGainMath
-
-# Generic imports for MPL-incorporation
-import matplotlib as _mpl
-from matplotlib.pyplot import colormaps as _plt_colormaps
-import sciplot as _sciplot
-#import matplotlib.pyplot as _plt
-
-_mpl.use('Qt5Agg')
-_mpl.rcParams['font.family'] = 'sans-serif'
-_mpl.rcParams['font.size'] = 10
-
-from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as _NavigationToolbar)
-
-from crikit.ui.classes_ui import BW, SingleColor, CompositeColor
-
-
-
[docs]class widgetImageGainMath(_QWidget): - """ - Panel that controle image gain and applies math - """ - OPERATION_STRINGS = ['','+','-','*','/','Peak b/w troughs','SUM'] - OPERATION_FREQ_COUNT = [1, 2, 2, 2,2, 3, 2] - COND_TYPE_STRINGS = ['>','<','=','<=','>='] - - def __init__(self, parent=None, **kwargs): - super().__init__(parent) - self.ui = Ui_ImageGainMath() - self.ui.setupUi(self) - - self.ui.comboBoxCondOps.addItem('OFF') - - for item in widgetImageGainMath.OPERATION_STRINGS: - self.ui.comboBoxOperations.addItem(item) - self.ui.comboBoxCondOps.addItem(item) - - for item in widgetImageGainMath.COND_TYPE_STRINGS: - self.ui.comboBoxCondInEquality.addItem(item) - - self.ui.comboBoxOperations.currentIndexChanged.connect(self.operationchange) - self.ui.comboBoxCondOps.currentIndexChanged.connect(self.condOpsChange) - -
[docs] def clear(self): - """ - Resets the ui to it's initial state - """ - self.ui.checkBoxDisable.setChecked(False) - - self.ui.spinBoxGain.setValue(1.0) - self.ui.tabWidgetMath.setCurrentIndex(0) - - self.ui.pushButtonOpFreq1.setText('Freq 1') - self.ui.pushButtonOpFreq2.setText('Freq 2') - self.ui.pushButtonOpFreq3.setText('Freq 3') - self.ui.comboBoxOperations.setCurrentIndex(0) - - self.ui.pushButtonCondFreq1.setText('Freq 1') - self.ui.pushButtonCondFreq2.setText('Freq 2') - self.ui.pushButtonCondFreq3.setText('Freq 3') - self.ui.comboBoxCondOps.setCurrentIndex(0) - self.ui.comboBoxCondInEquality.setCurrentIndex(0) - self.ui.spinBoxInEquality.setValue(0.0)
- -
[docs] def condOpsChange(self): - index = self.ui.comboBoxCondOps.currentIndex() - - if index == 0: - num_freq = 0 - else: - num_freq = widgetImageGainMath.OPERATION_FREQ_COUNT[index-1] - - self.ui.pushButtonCondFreq1.setEnabled(False) - self.ui.pushButtonCondFreq2.setEnabled(False) - self.ui.pushButtonCondFreq3.setEnabled(False) - self.ui.comboBoxCondInEquality.setEnabled(False) - self.ui.spinBoxInEquality.setEnabled(False) - - if num_freq >= 1: - self.ui.pushButtonCondFreq1.setEnabled(True) - self.ui.comboBoxCondInEquality.setEnabled(True) - self.ui.spinBoxInEquality.setEnabled(True) - if num_freq >= 2: - self.ui.pushButtonCondFreq2.setEnabled(True) - if num_freq >= 3: - self.ui.pushButtonCondFreq3.setEnabled(True)
- -
[docs] def operationchange(self): - index = self.ui.comboBoxOperations.currentIndex() - - num_freq = widgetImageGainMath.OPERATION_FREQ_COUNT[index] - - self.ui.pushButtonOpFreq1.setEnabled(False) - self.ui.pushButtonOpFreq2.setEnabled(False) - self.ui.pushButtonOpFreq3.setEnabled(False) - - if num_freq >= 1: - self.ui.pushButtonOpFreq1.setEnabled(True) - if num_freq >= 2: - self.ui.pushButtonOpFreq2.setEnabled(True) - if num_freq >= 3: - self.ui.pushButtonOpFreq3.setEnabled(True)
- -
[docs]class widgetPopSpectrumGS(_QWidget): - """ - Panel that let's user pop the current image, an average spectrum, - or a grayscale image to SciPlot - """ - def __init__(self, parent=None, **kwargs): - super().__init__(parent) - self.ui = Ui_PopSpectrumGS() - self.ui.setupUi(self)
- -
[docs]class widgetGrayScaleInfoBar(_QWidget): - """ - Grayscale image info bar - """ - def __init__(self, parent = None, **kwargs): - super().__init__(parent) - self.ui = Ui_GrayImgInfoBar() - self.ui.setupUi(self)
- -
[docs]class widgetColorMode(_QWidget): - """ - Color mode selector - """ - def __init__(self, parent=None, **kwargs): - super().__init__(parent) - self.ui = Ui_ColorModeSetting() - self.ui.setupUi(self) - - # Get all MPL named colors - color_list = ['red', 'green', 'blue', 'magenta', 'cyan', 'yellow', - 'black', 'white', 'CUSTOM'] - color_list.extend(sorted(set(_mpl.colors.cnames.keys()) - set(color_list))) - self.ui.comboBoxBGColor.addItems(color_list) - self.ui.comboBoxFGColor.addItems(color_list) - self.ui.comboBoxBGColor.setCurrentIndex(color_list.index('black')) - # Get all mpl colormaps and set combo box - list_of_colormaps = sorted(_plt_colormaps()) - self.ui.comboBoxColormap.addItems(list_of_colormaps) - - # Set default colormap to 'gray' - idx = self.ui.comboBoxColormap.findText('gray') - self.ui.comboBoxColormap.setCurrentIndex(idx)
- -
[docs]class widgetBWImg(_QWidget): - """ - Grayscale image widget - """ - def __init__(self, parent = None, **kwargs): - super().__init__(parent) - self.win = Ui_Blank() - self.win.setupUi(self) - self.win.gridLayout.setEnabled(False) - - self._img_defaults = {'showcbar': True, 'axison': True} - - self.gsinfo = widgetGrayScaleInfoBar(parent=self) - - self.colormode = widgetColorMode(parent=self) - self.colormode.ui.comboBoxColorMode.setCurrentIndex(1) - self.colormode.ui.comboBoxColormap.setVisible(True) - self.colormode.ui.labelColormap.setVisible(True) - self.colormode.ui.comboBoxFGColor.setVisible(False) - self.colormode.ui.comboBoxBGColor.setVisible(False) - self.colormode.ui.comboBoxColorMode.setVisible(False) - self.colormode.ui.labelBGColor.setVisible(False) - self.colormode.ui.labelFGColor.setVisible(False) - self.colormode.ui.labelColorMode.setVisible(False) - - self.popimage = widgetPopSpectrumGS(parent=self) - self.popimage.ui.pushButtonGSPop.setVisible(False) - - self.ui = self.gsinfo.ui # Alias - - self.win.horizLayout = _QHBoxLayout() - self.win.horizLayout.setContentsMargins(2,2,2,2) - - self.win.verticalLayout.insertLayout(0, self.win.horizLayout) - - self.win.horizLayout.insertWidget(0, self.gsinfo, _QtCore.Qt.AlignHCenter) - self.win.horizLayout.insertWidget(0, self.colormode, _QtCore.Qt.AlignBottom) - - # Initialize underlying data - self.initData() - self.external_plots = [] - - # Stand-in image data - self.data.grayscaleimage = _np.dot(_np.ones([100,1]),_np.linspace(1,100,100)[None,:]) - self.data.set_x(_np.linspace(1,400,self.data.xlen)) - self.data.set_y(_np.linspace(1,400,self.data.ylen)) - - # Calculate extent of image - winextent = (self.data.x.min(), self.data.x.max(), self.data.y.min(), self.data.y.max()) - - # MPL canvas - self.mpl = _MplCanvas(**kwargs) - self.mpl.cbar = None # Monkey patch on a cbar object - - # Create stand-image plot - self.createImg(img=self.data.image, xunits=self.data.xunits, - yunits=self.data.yunits, - extent=winextent, - cmap=self.colormode.ui.comboBoxColormap.currentText()) - self.mpl.fig.tight_layout() - - # Insert canvas widget into this widget - self.win.verticalLayout.insertWidget(0,self.mpl,_QtCore.Qt.AlignCenter) - self.win.verticalLayout.insertWidget(0,self.popimage,_QtCore.Qt.AlignCenter) - self.win.verticalLayout.insertWidget(0,self.mpl.toolbar, _QtCore.Qt.AlignHCenter) - - # # SIGNAL & SLOTS - self.ui.checkBoxFixed.stateChanged.connect(self.checkBoxFixed) - self.ui.checkBoxRemOutliers.stateChanged.connect(self.checkBoxRemOutliers) - self.ui.spinBoxStdDevs.editingFinished.connect(self.checkBoxRemOutliers) - - # New - self.ui.comboBoxAboveMax.currentIndexChanged.connect(self.comboBoxCompress) - self.ui.comboBoxBelowMin.currentIndexChanged.connect(self.comboBoxCompress) - self.ui.spinBoxMax.editingFinished.connect(self.spinBoxMinMaxSet) - self.ui.spinBoxMin.editingFinished.connect(self.spinBoxMinMaxSet) - self.colormode.ui.comboBoxColormap.currentIndexChanged.connect(self.checkBoxFixed) - self.popimage.ui.pushButtonPop.pressed.connect(lambda: self.createImg_Ext(img=self.data.image, - cmap=self.colormode.ui.comboBoxColormap.currentText(), - showcbar=True, - extent=self.data.winextent, - xunits=self.data.xunits, - yunits=self.data.yunits, - parent=parent)) -
[docs] def initData(self): - """ - (Re)-initialize self.data - """ - self.data = BW()
- -
[docs] def createImg_Ext(self, img, xunits = None, yunits = None, - extent = None, showcbar = True, axison = True, - cmap = _mpl.cm.gray, parent=None): - """ - Create new figure window and show image of img - """ - - self.external_plots.append(_sciplot.main(parent=parent)) - self.external_plots[-1].imshow(img, x_label=xunits, y_label=yunits, - cmap=cmap, cbar=showcbar, extent=extent)
- -
[docs] def createImg(self, img, xunits = None, yunits = None, - extent = None, cmap = _mpl.cm.gray): - self.mpl.ax.clear() - self.mpl.img = self.mpl.ax.imshow(img, interpolation = 'none', - extent = extent, cmap = cmap, - origin='lower') - if xunits is not None: - self.mpl.ax.xaxis.set_label_text(xunits) - if yunits is not None: - self.mpl.ax.yaxis.set_label_text(yunits) - - if self._img_defaults['axison'] == False: - self.mpl.ax.set_axis_off() - - # print(self.mpl.cbar) - if self.mpl.cbar is not None: - self.mpl.cbar.remove() - self.mpl.cbar = None - if self._img_defaults['showcbar'] == True: - self.mpl.cbar = self.mpl.fig.colorbar(self.mpl.img) - - if self.ui.checkBoxFixed.isChecked() == False: - self.ui.spinBoxMax.setValue(self.data.maxer) - self.ui.spinBoxMin.setValue(self.data.minner)
- -
[docs] def spinBoxMinMaxSet(self): - try: - self.data.setmin = self.ui.spinBoxMin.value() - self.data.setmax = self.ui.spinBoxMax.value() - self.ui.checkBoxFixed.setChecked(True) - - # Spin-Box call from Outlier-related widgets? - sent_by = self.sender() - if ((sent_by == self.ui.checkBoxRemOutliers) | - (sent_by == self.ui.spinBoxStdDevs)): - pass - elif ((sent_by == self.ui.spinBoxMax) | - (sent_by == self.ui.spinBoxMin)): - self.ui.checkBoxRemOutliers.setChecked(False) - else: - pass - - self.createImg(img=self.data.image, xunits=self.data.xunits, - yunits=self.data.yunits, - extent=self.data.winextent, - cmap=self.colormode.ui.comboBoxColormap.currentText()) - self.mpl.draw() - - except: - print('Error in spinBoxMinMaxSet')
- -
[docs] def checkBoxRemOutliers(self): - """ - """ - if self.ui.checkBoxRemOutliers.isChecked() == False: - pass - else: - new_max = self.data.mean + self.ui.spinBoxStdDevs.value()* \ - self.data.std - new_min = self.data.mean - self.ui.spinBoxStdDevs.value()* \ - self.data.std - self.ui.spinBoxMax.setValue(new_max) - self.ui.spinBoxMin.setValue(new_min) - self.spinBoxMinMaxSet() - - self.createImg(img=self.data.image, xunits=self.data.xunits, - yunits=self.data.yunits, - extent=self.data.winextent, - cmap=self.colormode.ui.comboBoxColormap.currentText()) - self.mpl.draw()
- -
[docs] def checkBoxFixed(self): - """ - See if the min and max are identified as being fixed by - checkbox - """ - - # See if there is a min and max in the textBrowsers - - if self.ui.checkBoxFixed.isChecked() == True: # Checked - try: - self.data.setmin = self.ui.spinBoxMin.value() - self.data.setmax = self.ui.spinBoxMax.value() - if self.ui.comboBoxAboveMax.currentIndex() == 0: - self.data.compress_high = False - else: - self.data.compress_high = True - if self.ui.comboBoxBelowMin.currentIndex() == 0: - self.data.compress_low = False - else: - self.data.compress_low = True - except: - pass - else: - self.data.setmin = None - self.data.setmax = None - self.data.compress_low = None - self.data.compress_high = None - self.ui.checkBoxRemOutliers.setChecked(False) - - self.createImg(img=self.data.image, xunits=self.data.xunits, - yunits=self.data.yunits, - extent=self.data.winextent, - cmap=self.colormode.ui.comboBoxColormap.currentText()) - self.mpl.draw()
- -
[docs] def comboBoxCompress(self): - """ - See if compression is activated via the comboBoxAboveMax - """ - if self.ui.comboBoxAboveMax.currentIndex() == 0: - self.data.compress_high = False - else: - self.data.compress_high = True - - if self.ui.comboBoxBelowMin.currentIndex() == 0: - self.data.compress_low = False - else: - self.data.compress_low = True - - self.createImg(img=self.data.image, xunits=self.data.xunits, - yunits=self.data.yunits, - extent=self.data.winextent, - cmap=self.colormode.ui.comboBoxColormap.currentText()) - self.mpl.draw()
- -
[docs]class widgetSglColor(widgetBWImg): - """ - Single-color widget - """ - def __init__(self, parent=None, **kwargs): - super().__init__(parent) - self._img_defaults = {'showcbar': False, 'axison': True} - self.initData() - self.data.grayscaleimage = _np.dot(_np.ones([100,1]),_np.linspace(1,100,100)[None,:]) - self.data.set_x(_np.linspace(1,400,self.data.xlen)) - self.data.set_y(_np.linspace(1,400,self.data.ylen)) - self.changeColor() - self.colormode.setMaximumHeight(130) - - self.math = widgetImageGainMath(parent=self) - self.win.verticalLayout.insertWidget(3, self.math) - - # Disconnect colormap-related (from BW parent) - self.colormode.ui.comboBoxColormap.currentIndexChanged.disconnect() - - self.colormode.ui.comboBoxColorMode.setCurrentIndex(0) - self.colormode.ui.comboBoxColormap.setVisible(False) - self.colormode.ui.labelColormap.setVisible(False) - self.colormode.ui.comboBoxFGColor.setVisible(True) - self.colormode.ui.comboBoxBGColor.setVisible(True) - self.colormode.ui.comboBoxColorMode.setVisible(False) - self.colormode.ui.labelBGColor.setVisible(True) - self.colormode.ui.labelFGColor.setVisible(True) - self.colormode.ui.labelColorMode.setVisible(True) - - self.colormode.ui.comboBoxFGColor.currentIndexChanged.connect(self.changeColor) - self.colormode.ui.comboBoxBGColor.currentIndexChanged.connect(self.changeColor) - self.math.ui.spinBoxGain.valueChanged.connect(self.applyGain) - self.math.ui.pushButtonGain1.pressed.connect(self.gain1) - self.math.ui.checkBoxDisable.stateChanged.connect(self.disabled) - - self.popimage.ui.pushButtonGSPop.setVisible(True) - try: - self.popimage.ui.pushButtonPop.pressed.disconnect() - except: - pass - self.popimage.ui.pushButtonPop.pressed.connect(lambda: self.createImg_Ext(img = self.data.image, - showcbar=False, - extent=self.data.winextent, - xunits=self.data.xunits, - yunits=self.data.yunits, - parent=parent)) - - try: - self.popimage.ui.pushButtonGSPop.pressed.disconnect() - except TypeError: - pass # Just means pushButtonGSPop wasn't connected to anything - self.popimage.ui.pushButtonGSPop.pressed.connect(lambda: self.createImg_Ext(img = self.data.imageGS, - showcbar=True, - extent=self.data.winextent, - xunits=self.data.xunits, - yunits=self.data.yunits, - parent=parent)) - -
[docs] def initData(self): - """ - (Re)-initialize self.data - """ - self.data = SingleColor()
- - -
[docs] def changeColor(self): - # try: - - if self.sender() == self.colormode.ui.comboBoxFGColor: - color_str = self.colormode.ui.comboBoxFGColor.currentText() - if color_str == 'CUSTOM': - color = _QColorDialog.getColor().getRgb() - color = [round(color[0]/255,2), round(color[1]/255,2), round(color[2]/255,2)] - - self.data.colormap = color - - else: - self.data.colormap = _mpl.colors.colorConverter.to_rgb(_mpl.colors.cnames[color_str]) - - elif self.sender() == self.colormode.ui.comboBoxBGColor: - bgcolor_str = self.colormode.ui.comboBoxBGColor.currentText() - if bgcolor_str == 'CUSTOM': - bgcolor = _QColorDialog.getColor().getRgb() - bgcolor = [round(bgcolor[0]/255,2), round(bgcolor[1]/255,2), round(bgcolor[2]/255,2)] - - self.data.bgcolor = bgcolor - - else: - self.data.bgcolor = _mpl.colors.colorConverter.to_rgb(_mpl.colors.cnames[bgcolor_str]) - - self.createImg(img = self.data.image, xunits = self.data.xunits, - yunits = self.data.yunits, - extent = self.data.winextent) - self.mpl.draw()
- -
[docs] def applyGain(self): - self.data.setgain = self.math.ui.spinBoxGain.value() - self.changeColor() - if self.data.setgain == 0.0: - self.math.ui.checkBoxDisable.setChecked(True) - else: - self.math.ui.checkBoxDisable.setChecked(False)
- -
[docs] def gain1(self): - self.math.ui.spinBoxGain.setValue(1.0)
- -
[docs] def disabled(self): - if self.math.ui.checkBoxDisable.isChecked(): - self.math.ui.spinBoxGain.setValue(0.0) - else: - self.math.ui.spinBoxGain.setValue(1.0)
- -
[docs]class widgetCompositeColor(_QWidget): - def __init__(self, sgl_color_widget_list = None, parent = None, **kwargs): - super(widgetCompositeColor, self).__init__(parent) - ## Double check the spellings - self._img_defaults = {'showcbar':False, 'axison':True} - self.ui = Ui_CompositeColor_Form() - self.ui.setupUi(self) - - # Initialize underlying data - self.initData(sgl_color_widget_list) - self.external_plots = [] - - # Create stand-in image data - self.data.grayscaleimage = _np.dot(_np.ones([100,1]),_np.linspace(1,100,100)[None,:]) - self.data.set_x(_np.linspace(1,400,self.data.xlen)) - self.data.set_y(_np.linspace(1,400,self.data.ylen)) - - winextent = (self.data.x.min(), self.data.x.max(), self.data.y.min(), self.data.y.max()) - - # Instantiate mpl widget - self.mpl = _MplCanvas(**kwargs) - self.mpl.cbar = None # Monkey patch on a cbar object - - # Background color-related - # Get all MPL named colors - color_list = ['black', 'white', 'CUSTOM', 'red', 'green', 'blue', - 'magenta', 'cyan', 'yellow'] - color_list.extend(sorted(set(_mpl.colors.cnames.keys()) - set(color_list))) - self.ui.comboBoxBGColor.addItems(color_list) - self.ui.comboBoxBGColor.setCurrentIndex(color_list.index('black')) - - # Emission/Absorption mode settings - self.ui.comboBoxColorMode.setCurrentIndex(0) # Emission mode is default - - # Create stand-in image data - self.createImg(img = self.data.image, xunits = self.data.xunits, - yunits = self.data.yunits, - extent = winextent) - self.mpl.fig.tight_layout() - - # Insert mpl widget into this widget - self.ui.verticalLayout.insertWidget(0,self.mpl,_QtCore.Qt.AlignHCenter) - self.ui.verticalLayout.insertWidget(0,self.mpl.toolbar, _QtCore.Qt.AlignHCenter) - - self.popimage = widgetPopSpectrumGS(self) - self.ui.verticalLayout.insertWidget(1, self.popimage, _QtCore.Qt.AlignLeft) - self.popimage.ui.pushButtonPop.pressed.connect(lambda: self.createImg_Ext(img = self.data.image, - showcbar=False, - extent=self.data.winextent, - xunits=self.data.xunits, - yunits=self.data.yunits, - parent=parent)) - self.popimage.ui.pushButtonGSPop.setEnabled(False) - self.popimage.ui.pushButtonSpectrum.setEnabled(False) - self.ui.comboBoxBGColor.setEnabled(False) - self.ui.comboBoxBGColor.setVisible(False) # Broken -- don't know if it will ever work - self.ui.labelBGColor.setVisible(False) # Broken - self.ui.comboBoxColorMode.currentIndexChanged.connect(self.changeMode) - -
[docs] def initData(self, sgl_color_widget_list): - """ - (Re)-initialize self.data - """ - - if sgl_color_widget_list is None: - self.data = CompositeColor() - else: - temp = [] - for count in sgl_color_widget_list: - temp.append(count.data) - - self.data = CompositeColor(temp)
- -
[docs] def createImg(self, img, xunits = None, yunits = None, - extent = None, - cmap = _mpl.cm.gray): - self.mpl.ax.clear() - self.mpl.img = self.mpl.ax.imshow(img, interpolation = 'none', - extent = extent, cmap = cmap, origin='lower') - if xunits is not None: - self.mpl.ax.xaxis.set_label_text(xunits) - if yunits is not None: - self.mpl.ax.yaxis.set_label_text(yunits) - - if self._img_defaults['axison'] == False: - self.mpl.ax.set_axis_off() - - if self.mpl.cbar is not None: - self.mpl.cbar.remove() - if self._img_defaults['showcbar'] == True: - self.mpl.cbar = self.mpl.fig.colorbar(self.mpl.img)
- -
[docs] def createImg_Ext(self, img, xunits = None, yunits = None, - extent = None, showcbar = True, axison = True, - cmap = _mpl.cm.gray, parent=None): - """ - Create new figure window and show image of img - """ - - self.external_plots.append(_sciplot.main(parent=parent)) - self.external_plots[-1].imshow(img, x_label=xunits, y_label=yunits, - cmap=cmap, cbar=showcbar, extent=extent)
- - # BROKEN -- May never work - # def changeBGColor(self): - # """ - # Does not work as expected - # """ - # color_str = self.ui.comboBoxBGColor.currentText() - # self.data.bgcolor = _mpl.colors.to_rgb(_mpl.colors.cnames[color_str]) - - # self.createImg(img = self.data.image, xunits = self.data.xunits, - # yunits = self.data.yunits, - # extent = self.data.winextent) - # self.mpl.fig.tight_layout() - # self.mpl.draw() - -
[docs] def changeMode(self): - self.data.mode = self.ui.comboBoxColorMode.currentIndex() - # self.data.mode = _np.abs(self.data.mode - 1).astype(int) - self.mpl.ax.clear() - self.createImg(img = self.data.image, xunits = self.data.xunits, - yunits = self.data.yunits, - extent = self.data.winextent) - self.mpl.fig.tight_layout() - self.mpl.draw()
- - -if __name__ == '__main__': - - app = _QApplication(_sys.argv) - app.setStyle('Cleanlooks') - - winBWImg = widgetBWImg() - winBWImg.setWindowTitle('BW Image') - winBWImg.show() - - winSglColor = widgetSglColor() - winSglColor.setWindowTitle('Single Color') - winSglColor.colormode.ui.comboBoxBGColor.setCurrentIndex(7) - winSglColor.show() - - winSglColor2 = widgetSglColor() - winSglColor2.colormode.ui.comboBoxFGColor.setCurrentIndex(1) - winSglColor2.colormode.ui.comboBoxBGColor.setCurrentIndex(7) - winSglColor2.setWindowTitle('Single Color') - winSglColor2.show() - - - winColorMath = widgetImageGainMath() - winColorMath.setWindowTitle('Color Math') - winColorMath.show() - - winCompositeColor = widgetCompositeColor(sgl_color_widget_list=[winSglColor, winSglColor2]) - winCompositeColor.setWindowTitle('Composite Color') - winCompositeColor.show() - - _sys.exit(app.exec_()) -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_mergeNRBs.html b/docs/build/html/_modules/crikit/ui/widget_mergeNRBs.html deleted file mode 100644 index cdbde3f..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_mergeNRBs.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_mergeNRBs — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_mergeNRBs
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_mergeNRBs

-"""
-Widget for PlotEffect that adjusts the parameters appropriate for
-merging 2 NRBs
-
-Created on Thu Dec 22 22:20:06 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-from crikit.ui.dialog_AbstractPlotEffect import (AbstractPlotEffectPlugin
-                                                     as
-                                                     _AbstractPlotEffectPlugin)
-
-
-from crikit.ui.widget_KK import (widgetKK as _widgetKK)
-from crikit.ui.qt_PlotEffect_MergeNRBs import Ui_Form as _Ui_Form
-from crikit.utils.general import find_nearest as _find_nearest
-from crikit.cri.merge_nrbs import MergeNRBs as _MergeNRBs
-
-
[docs]class widgetMergeNRBs(_AbstractPlotEffectPlugin): - """ - Widget for PlotEffect that adjusts the parameters appropriate for - merging 2 NRBs - """ - # Parameter dict that will be returned from PlotEffect - # Will be updated later in program to contain all parameters - # to pass to underlying algorithm - parameters = {'name' : 'mergeNRBs', - 'long_name' : 'Merge 2 NRBs'} - - # Labeling options for original data plot - labels_orig = { - 'x_label' : 'Wavenumber (cm$^{-1}$)', - 'y_label' : 'Input Int (au)', - 'title' : 'Original' - } - - # Labeling options for affected data plot - labels_affected = { - 'x_label' : labels_orig['x_label'], - 'y_label' : 'Raman-Like Int (au)', - 'title' : 'KK-Raman' - } - - def __init__(self, wn_vec, nrb_left, nrb_right, scale_left=False, - wn_switchpt=2800.0, parent = None): - - super(widgetMergeNRBs, self).__init__(parent) - - self.ui = _Ui_Form() - self.ui.setupUi(self) - - self.wn = wn_vec - self.nrb_left = nrb_left - self.nrb_right = nrb_right - - # Update parameter dict - self.parameters['scale_left'] = scale_left - self.parameters['wn_switchpt'] = wn_switchpt - self.parameters['pix_switchpt'] = \ - _find_nearest(self.wn, self.parameters['wn_switchpt'])[1] - - self.kk_widget = _widgetKK() - - self.ui.horizontalLayoutKK.insertWidget(0, self.kk_widget) - - self.ui.spinBoxWN.setMinimum(self.wn.min()) - self.ui.spinBoxWN.setMaximum(self.wn.max()) - self.ui.spinBoxPix.setMinimum(0) - self.ui.spinBoxPix.setMaximum(self.wn.size-1) - - # Set range - self.ui.spinBoxLowRange.setValue(self.wn.min()) - self.ui.spinBoxHighRange.setValue(self.wn.max()) - self.rng = None - self.rangeChanged() - - if self.parameters['scale_left']: - self.ui.comboBoxScaleLeftRight.setCurrentIndex(0) - elif self.parameters['scale_left'] == False: - self.ui.comboBoxScaleLeftRight.setCurrentIndex(1) - elif self.parameters['scale_left'] is None: - self.ui.comboBoxScaleLeftRight.setCurrentIndex(2) - - self.ui.spinBoxWN.setValue(self.parameters['wn_switchpt']) - self.ui.spinBoxPix.setValue(self.parameters['pix_switchpt']) - - # SIGNALS & SLOTS - self.kk_widget.changed.connect(self.kkChanged) - - self.ui.comboBoxScaleLeftRight.currentIndexChanged.connect(self.scaleChanged) - self.ui.spinBoxWN.editingFinished.connect(self.wnChanged) - self.ui.spinBoxPix.editingFinished.connect(self.pixChanged) - - self.ui.spinBoxLowRange.editingFinished.connect(self.rangeChanged) - self.ui.spinBoxHighRange.editingFinished.connect(self.rangeChanged) - -
[docs] def rangeChanged(self): - low = self.ui.spinBoxLowRange.value() - high = self.ui.spinBoxHighRange.value() - self.rng = [low, high] - self.rng.sort() - self.changed.emit()
- - @property - def fullRange(self): - low = self.rng[0] - high = self.rng[1] - - if (_np.isclose(self.wn.min(), low, atol=.1) & - _np.isclose(self.wn.max(), high, atol=.1)): - return True - else: - return False - -
[docs] def kkChanged(self): - self.changed.emit()
- -
[docs] def scaleChanged(self): - idx = self.ui.comboBoxScaleLeftRight.currentIndex() - - if idx == 0: - self.parameters['scale_left'] = True - elif idx == 1: - self.parameters['scale_left'] = False - else: - self.parameters['scale_left'] = None - self.changed.emit()
- -
[docs] def wnChanged(self): -# print('WN Changed') - self.parameters['wn_switchpt'], self.parameters['pix_switchpt'] = \ - _find_nearest(self.wn, self.ui.spinBoxWN.value()) - - self.ui.spinBoxWN.setValue(self.parameters['wn_switchpt']) - self.ui.spinBoxPix.setValue(self.parameters['pix_switchpt']) - self.changed.emit()
- -
[docs] def pixChanged(self): - self.parameters['pix_switchpt'] = self.ui.spinBoxPix.value() - self.parameters['wn_switchpt'] = self.wn[self.parameters['pix_switchpt']] - - self.ui.spinBoxWN.setValue(self.parameters['wn_switchpt']) - - self.changed.emit()
- -
[docs] def fcn(self, data_in): - """ - If return list, [0] goes to original, [1] goes to affected - """ - inst_nrb_merge = _MergeNRBs(nrb_left=self.nrb_left, - nrb_right=self.nrb_right, - pix=self.parameters['pix_switchpt'], - left_side_scale=self.parameters['scale_left']) - - if self.fullRange: - pix = _np.arange(self.wn.size, dtype=_np.integer) - - else: - list_rng_pix = _find_nearest(self.wn, self.rng)[1] - pix = _np.arange(list_rng_pix[0],list_rng_pix[1]+1, - dtype=_np.integer) - - nrb_merged = inst_nrb_merge.calculate() - kkd = _np.zeros(data_in.shape) - - # Note: kk_widget.fcn return imag part - kkd[..., pix] = self.kk_widget.fcn([nrb_merged[pix], data_in[..., pix]]) - - return [_np.vstack((self.nrb_left, self.nrb_right, nrb_merged)), - kkd]
- -if __name__ == '__main__': - import sys as _sys - from PyQt5.QtWidgets import QApplication as _QApplication - app = _QApplication(_sys.argv) - - WN = _np.linspace(-1500,3600,1600) - - NRB_LEFT = 20e3*_np.exp(-(WN)**2/(1000**2)) + 500 - NRB_RIGHT = 6e3*_np.exp(-(WN-2500)**2/(400**2)) + 500 - - NRB_LEFT[WN<500] *= 0 - NRB_LEFT[WN<500] += 1e-6 - NRB_RIGHT[WN<500] *= 0 - NRB_RIGHT[WN<500] += 1e-6 - - win = widgetMergeNRBs(WN, NRB_LEFT, NRB_RIGHT) - win.show() - - app.exec_() - _sys.exit() - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/ui/widget_scientificspin.html b/docs/build/html/_modules/crikit/ui/widget_scientificspin.html deleted file mode 100644 index 1f67518..0000000 --- a/docs/build/html/_modules/crikit/ui/widget_scientificspin.html +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - - - - - - crikit.ui.widget_scientificspin — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.ui.widget_scientificspin
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.ui.widget_scientificspin

-"""
-From https://gist.github.com/jdreaver -- scientificspin.py
-
-Created on Wed Dec  7 10:39:26 2016
-
-@author: chc
-"""
-
-import re
-
-from PyQt5 import QtWidgets, QtGui
-
-# Regular expression to find floats. Match groups are the whole string, the
-# whole coefficient, the decimal part of the coefficient, and the exponent
-# part.
-_float_re = re.compile(r'(([+-]?\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)')
-
-
[docs]def valid_float_string(string): - match = _float_re.search(string) - return match.groups()[0] == string if match else False
- -
[docs]class FloatValidator(QtGui.QValidator): - -
[docs] def validate(self, string, position): - if valid_float_string(string): - state = QtGui.QValidator.Acceptable - elif string == "" or string[position-1] in 'e.-+': - state = QtGui.QValidator.Intermediate - else: - state = QtGui.QValidator.Invalid - return (state, string, position)
- -
[docs] def fixup(self, text): - match = _float_re.search(text) - return match.groups()[0] if match else ""
- -
[docs]class ScientificDoubleSpinBox(QtWidgets.QDoubleSpinBox): - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.setMinimum(-1e20) - self.setMaximum(1e20) - self.validator = FloatValidator() - self.setDecimals(100) - -
[docs] def validate(self, text, position): - return self.validator.validate(text, position)
- -
[docs] def fixup(self, text): - return self.validator.fixup(text)
- -
[docs] def valueFromText(self, text): - return float(text)
- -
[docs] def textFromValue(self, value): - return format_float(value)
- -
[docs] def stepBy(self, steps): - text = self.cleanText() - groups = _float_re.search(text).groups() - decimal = float(groups[1]) - decimal += steps - new_string = "{:g}".format(decimal) + (groups[3] if groups[3] else "") - self.lineEdit().setText(new_string)
- -
[docs]def format_float(value): - """Modified form of the 'g' format specifier.""" - string = "{:g}".format(value).replace("e+", "e") - string = re.sub("e(-?)0*(\d+)", r"e\1\2", string) - return string
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/utils/breadcrumb.html b/docs/build/html/_modules/crikit/utils/breadcrumb.html deleted file mode 100644 index 237ed9b..0000000 --- a/docs/build/html/_modules/crikit/utils/breadcrumb.html +++ /dev/null @@ -1,527 +0,0 @@ - - - - - - - - - - - crikit.utils.breadcrumb — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.utils.breadcrumb
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.utils.breadcrumb

-"""
-Breadcrumb Module
-=================
-
-    BCPre : Container describing pre-processing steps
-
-Class Methods
---------------
-    HDFtoClass(filename [str], datasetname [str]) : Load dataset in HDF
-        file into the HSI Class
-
-"""
-
-import time as _time
-import copy as _copy
-import pickle as _pickle
-
-
[docs]class BCPre: - """ - Container that describes processing steps (ie it contains "breadcrumbs") - - Attributes - ---------- - process_list : list - A list-of-lists. Each contained list follows the format \ - ['Process Name', 'Var1 Name', Val1, 'Var2 Name', Val2, ...]. The \ - variable names and values may be input values to the pre-processing \ - step. Only the Process Name is mnadatory: the rest are optional. - - backed_flag : list - Flag identifying which steps were backed-up to disk (e.g., for undo) - - id_list : list (read-only) - Unique identifier for each step. Can be used to name back-up/undo files - - cut_list : list (read-only) - Identifier of id's cut with pop_to_last method - - num_steps : int - Number of processing steps - - attr_dict : dict - Dictionary-version of process_list that can be written to HDF5 dataset - metadata (properties) - - Methods - ------- - add_step : Add a new processing step - - backed_up : Mark most recent process step as backed up in backed_flag list - - pop_to_last : Remove entries until nearest backup point (excluding current \ - step). - - """ - - HDF_PREFIX = 'Processing.Steps' - - def __init__(self): - self.process_list = [] - self._id_list = [] - self.backed_flag = [] - self._cut_list = [] - - # PROPERTIES - @property - def id_list(self): - # Use shallow-copy to prevent ability to append - # to _id_list via id_list - return self._id_list.copy() - - @property - def cut_list(self): - # Use shallow-copy to prevent ability to append - # to _cut_list via cut_list - return self._cut_list.copy() - - @cut_list.deleter - def cut_list(self): - self._cut_list = [] - - @property - def num_steps(self): - return len(self.process_list) - - @property - def attr_dict(self): - temp = {} - for num, item in enumerate(self.process_list): - temp_key_process_prefix = self.HDF_PREFIX + '.' + str(num+1) + '.' + str(item[0]) - temp_val = 'NA' - temp[temp_key_process_prefix] = temp_val - if len(item) > 1: - #print('ITEM: {}'.format(item)) - for num_var, var in enumerate(item[1::2]): - #print('KEY: {}, VAL: {}'.format(var, item[2*num_var+2])) - temp_key = temp_key_process_prefix + '.' + str(var) - temp_val = item[2*num_var+2] - temp[temp_key] = temp_val - temp[self.HDF_PREFIX] = self.num_steps - return temp - - @property - def dset_name_suffix(self): - temp = '' - #print('QQQ: {}'.format(self.process_list)) - try: - for num, step in enumerate(self.process_list): - #print('Step: {}'.format(step[0])) - #print(num) - if num == 0: - pass - else: - #print(step[0]) - temp = temp + '_' + step[0] - return temp - except: - return None - - # METHODS -
[docs] @staticmethod - def backup_pickle(data, fname, addl_attr = None): - """ - Dump current state of data (class of type crikit.data.spectrum or - subclass)to pickle file (filename= fname). - - Can append additional attributes (addl_attr) to \ - attribute dictionary (self.attr) - """ - if fname.find('.pickle') == -1: - fname += '.pickle' - - if addl_attr is not None: - data.attr.update(addl_attr) - - with open(fname, 'xb') as f: - # Pickle with highest protocol - # Surpasses the default protocol 3 4Gb limit - _pickle.dump(data, f, protocol=-1)
- -
[docs] @staticmethod - def load_pickle(fname): - """ - Static method. - - Return a loaded pickled version of this class (filename= fname). - - """ - if fname.find('.pickle') == -1: - fname += '.pickle' - - with open(fname, 'rb') as f: - return _pickle.load(f)
- -
[docs] def add_step(self, process_desc): - """ - Adds a steps to the list - - Parameters - ------ - process_desc : list - List containing elements of new process with format: \ - ['Process Name', 'Var1 Name', Val1, 'Var2 Name', Val2, ...]. The \ - variable names and values may be input values to the \ - pre-processing step. Only the Process Name is mnadatory: the rest \ - are optional. - - Returns - ------- - None : None - - """ - assert isinstance(process_desc,list), 'The input need be a list' - assert len(process_desc)%2 != 0, 'The input needs to be an odd length (title, var name 1, var value 1, etc)' - - # Ensures unique IDs based on time. Note some systems only report in - # seconds, not sub-seconds - _time.sleep(1) - - self.process_list.append(process_desc) - self._id_list.append(str(_time.time())) - self.backed_flag.append(False)
- -
[docs] def backed_up(self): - """ - Marks most recent process step as backed up in backed_flag list - - Parameters - ------ - None : None - - Returns - ------- - None : None - - """ - self.backed_flag[-1] = True
- -
[docs] def pop_to_last(self, all=False): - """ - Remove entries until nearest backup point (excluding current step). - That is, if current step IS a backup point, moves to previous one. If \ - current step is NOT a backup point, moves to nearest point. - - If all = True, will cut everything - """ - temp = _copy.deepcopy(self.backed_flag) - backup_locs = [] - for num, val in enumerate(temp): - if val is True: - backup_locs.append(num) - - current_loc = len(temp) - 1 - - if all is False: - if temp[-1] == True: # Current is backed-up, go to previous - num_to_pop = backup_locs[-1] - backup_locs[-2] - else: # Current is not backed-up, return to nearest - num_to_pop = current_loc - backup_locs[-1] - else: - num_to_pop = len(temp) - - for count in range(num_to_pop): - self.process_list.pop() - is_backed_up = self.backed_flag.pop() - if is_backed_up: - self._cut_list.append(self._id_list.pop()) - else: - self._id_list.pop()
- - -if __name__ == '__main__': - import sys as _sys - test = BCPre() - try: - test.add_step('Test1') - except: - print('Expected Error\n') - try: - test.add_step(['Test',1]) - except: - print('Expected Error\n') - - test.add_step(['Raw']) - test.add_step(['SubDark','RangeStart',-1500,'RangeEnd',-400]) - test.add_step(['NormKK','Amp',100.0,'Phase',10.0]) - #test.add_step(['DeTrend','Lambda',1000.0,'p',0.001,'Method','ALS','Type','Phase']) - #test.add_step(['DeTrend','Order',2,'win',601,'Method','sg','Type','Scale']) - - #print('Attempting to append \'1\' to the end of id_list (it should not work)') - #test.id_list.append(1) - #print(test.id_list) - - print('\nProcess list: {}'.format(test.process_list)) - print('\nID list: {}'.format(test.id_list)) - print('\nNumber of process steps: {}'.format(test.num_steps)) - print('\n\nReturned attribute dict: {}'.format(test.attr_dict)) - print('\n\nGenerated dataset name: {}'.format(test.dset_name_suffix)) - _sys.exit() - - #[['Raw'], ['SubDark'], ['SubResidual', 'RangeStart', -1500, 'RangeEnd', -400]] - - -# print('\n\n\nWritten to backup file: {}'.format(test.backed_flag)) -# print('\n...Apply backed_up...') -# test.backed_up() -# print('\nWritten to backup file: {}'.format(test.backed_flag)) -# -# print('\nAdjust backup') -# test.backed_flag[0] = True -# print('Written to backup file: {}'.format(test.backed_flag)) -# -# print('\n Test Pop-to-last') -# print('Process List: {}'.format(test.process_list)) -# print('ID List: {}'.format(test.id_list)) -# print('Written to backup file: {}\n'.format(test.backed_flag)) -# -# test.pop_to_last() -# print('Process List: {}'.format(test.process_list)) -# print('ID List: {}'.format(test.id_list)) -# print('Written to backup file: {}'.format(test.backed_flag)) -# print('Cut List:{}'.format(test.cut_list)) -# del test.cut_list -# print('Cut List:{}'.format(test.cut_list)) -# -# print('\nCut all') -# test.pop_to_last(all=True) -# print('Process List: {}'.format(test.process_list)) -# print('ID List: {}'.format(test.id_list)) -# print('Written to backup file: {}'.format(test.backed_flag)) -# print('Cut List:{}'.format(test.cut_list)) -# del test.cut_list -# print('Cut List:{}'.format(test.cut_list)) -# -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/utils/datacheck.html b/docs/build/html/_modules/crikit/utils/datacheck.html deleted file mode 100644 index a0632c1..0000000 --- a/docs/build/html/_modules/crikit/utils/datacheck.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - crikit.utils.datacheck — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.utils.datacheck
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.utils.datacheck

-"""
-Functions to check and (if needed) convert input variables
-
-Created on Sat Jun 18 00:16:27 2016
-
-@author: chc
-"""
-
-import numpy as _np
-
-
-
[docs]def _rng_is_pix_vec(rng, vec_size=None): - """ - Make sure rng is a vector, unless None (then returns None). - - Parameters - ---------- - - rng : int, list, tuple, or ndarray(1D) - * int: number of pixels in rng - * list, tuple, ndarray with length 2: Start and end of rng - * ndarray (length > 2): actual rng vector - - Returns - ------- - - rng : ndarray (1D) - Array of pixel range - """ - if rng is None: - return None - elif isinstance(rng, (int, float)): - return _np.arange(rng) - elif len(rng) == 2: - rng.sort() - return _np.arange(rng[0], rng[1]) - else: - return rng
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/utils/general.html b/docs/build/html/_modules/crikit/utils/general.html deleted file mode 100644 index e5681c8..0000000 --- a/docs/build/html/_modules/crikit/utils/general.html +++ /dev/null @@ -1,442 +0,0 @@ - - - - - - - - - - - crikit.utils.general — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.utils.general
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.utils.general

-"""
-General utilities
-
-    expand_1d_to_ndim_data : Match 1D data array dimensionality to that of \
-        another array
-
-    expand_1d_to_ndim : Expand 1D data array dimensionality to ndim
-
-    find_nearest : Given a vector and a value, find the index and value
-        of the closest match
-
-Notes
------
-"""
-import numpy as _np
-
-
[docs]def np_fcn_nd_to_1d(fcn, data, axis=-1): - """ - Take in an n-dimensional array and return a 1D version operated on by fcn.\ - Works with many numpy functions that can take an "axis" parameter - """ - if data.ndim > 1: - dims = list(range(data.ndim)) - dims.pop(axis) - vec = fcn(data, axis=tuple(dims)) - else: - vec = data - - return vec
- -
[docs]def mean_nd_to_1d(data, axis=-1): - """ - Take the mean of an nd array, except axis, returning a 1D array - """ - vec = np_fcn_nd_to_1d(_np.mean, data, axis=axis) - - return vec
- -
[docs]def std_nd_to_1d(data, axis=-1): - """ - Take the mean of an nd array, except axis, returning a 1D array - """ - vec = np_fcn_nd_to_1d(_np.std, data, axis=axis) - - return vec
- - -
[docs]def arange_nonzero(start, stop, dtype=_np.float): - """ - Similar to numpy arange but only returns non-zero elements - """ - vec = _np.arange(start, stop+1) - vec = vec[vec != 0] - return vec
- - -
[docs]def expand_1d_to_ndim_data(data, data_to_match): - """ - Make 1D data array equal in dimensions to data_to_match - """ - if data.ndim > 1: - print('data must be 1D') - else: - nd = data_to_match.ndim - return expand_1d_to_ndim(data, nd)
- - -
[docs]def expand_1d_to_ndim(data, ndim): - """ - Make 1D array into ndim dimensions - """ - if data.ndim > 1: - print('data must be 1D') - else: - sh = _np.ones((ndim-1),dtype=int) - sh = _np.append(sh,-1) - return data.reshape(sh)
- -
[docs]def find_nearest(np_vec,to_find = 0): - """ - Given a vector and a value (or list/vector of values), find the index and - value of the closest match - - - Parameters - ---------- - np_vec : numpy.ndarray - Numpy array (list) of values - - to_find : int, float, numpy.ndarray, or list - - Returns - ------- - out : tuple (nearest_value(s), index(es)) - Closest value (nearest_value) and index (index) - - """ - - # Number of values (to_find) to find - len_to_find = 0 - - if isinstance(to_find, int) or isinstance(to_find, float): - len_to_find = 1 - elif isinstance(to_find, list) or isinstance(to_find, tuple): - len_to_find = len(to_find) - elif isinstance(to_find, _np.ndarray): - len_to_find = to_find.size - else: - pass - - if len_to_find == 0: - return (None, None) - elif len_to_find == 1: # Single value - test = _np.abs(_np.array(np_vec)-to_find) - nearest_loc = test.argmin() - nearest_val = np_vec[nearest_loc] - else: # Series of values - nearest_val = [] - nearest_loc = [] - - for val in to_find: - loc = _np.argmin(_np.abs(_np.array(np_vec)-val)) - nearest_loc.append(loc) - nearest_val.append(np_vec[loc]) - - return (nearest_val, nearest_loc)
- - -
[docs]def row_col_from_lin(ct, sh): - """ - Convert a 1D counter into a col and row counter - """ - - assert len(sh) == 2, 'Shape must be 2D' - - tot_rows = sh[0] - tot_cols = sh[1] - - if isinstance(ct, _np.ndarray): - if (ct > tot_rows*tot_cols).any(): - print('Count is out-of-range. Returning None.') - return None - else: - if ct > tot_rows*tot_cols: - print('Count is out-of-range. Returning None.') - return None - - row = _np.mod(ct, tot_rows) - col = ct//tot_rows - - return [row, col]
- - -
[docs]def lin_from_row_col(row, col, sh): - """ - Convert a col and row counter to 1D linear count - """ - - assert len(sh) == 2, 'Shape must be 2D' - - tot_rows = sh[0] - # tot_cols = sh[1] - - ct = col*tot_rows + row - - return ct
- -if __name__ == '__main__': - import timeit as _timeit - - print('Test 1.....') - x = _np.random.rand(10,11) - - for ct in range(x.size): - row, col = lin_count_row_col(ct, x.shape) - print('R: {} C: {}'.format(row,col)) - print('Total number iterated through: {}'.format(ct+1)) - - print('Test 2...') - x = _np.random.rand(100,100,878) - y = _np.zeros(x.shape, dtype=complex) - - tmr = _timeit.default_timer() - for rc, blk in enumerate(x): - for cc, sp in enumerate(blk): - y[rc,cc,:] = _np.fft.fft(sp) - tmr -= _timeit.default_timer() - print('Time with 2 for-loops: {:.3g} sec'.format(-tmr)) - - tmr = _timeit.default_timer() - shp = x.shape - x = x.reshape((-1, shp[-1])) - y = _np.zeros(x.shape, dtype=complex) - for num, sp in enumerate(x): - y[num,:] = _np.fft.fft(sp) - y = y.reshape(shp) - tmr -= _timeit.default_timer() - print('Time with reshaping and 1 for-loops: {:.3g} sec'.format(-tmr)) - x = x.reshape(shp) - - tmr = _timeit.default_timer() - space_shp = _np.array(x.shape)[0:-1] - num_sp = space_shp.prod() - for num in range(num_sp): - rc, cc = lin_count_row_col(num, space_shp) - y[rc, cc, :] = _np.fft.fft(x[rc, cc, :]) - tmr -= _timeit.default_timer() - print('Time with 1 for-loops: {:.3g} sec'.format(-tmr)) - -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/utils/h5.html b/docs/build/html/_modules/crikit/utils/h5.html deleted file mode 100644 index 727c0b9..0000000 --- a/docs/build/html/_modules/crikit/utils/h5.html +++ /dev/null @@ -1,669 +0,0 @@ - - - - - - - - - - - crikit.utils.h5 — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.utils.h5

-"""
-hdf5 utilities (crikit.utils.h5)
-=======================================================
-
-    Utilities for for reading and writing data to HDF5 files
-
-Methods
---------
-    convert_to_np_dtype : convert from HDF5 dataset to numpy ndarray with \
-    numpy-builtin and native datatype
-
-    retrieve_group_dataset_dict : Retrieve dictionary describing groups that \
-    contain data [key] and the datasets [value]. {group : [dataset(s)]}
-
-    retrieve_dataset_attribute_dict : Retrieve dictionary describing \
-    attributes that contain data [key] and the datasets [value]. \
-    {group : [dataset(s)]}
-
-"""
-
-import h5py as _h5py
-_h5py.get_config().complex_names = ('Re','Im')
-
-import numpy as _np
-
-
[docs]def convert_to_np_dtype(dset): - """ - Given an HDF5 dataset, return the values in a numpy-builtin datatype - - Parameters - ---------- - dset : h5py.Dataset - HDF5 (h5py) dataset - - Returns - ------- - out : numpy.ndarray (dtype = numpy built-in) - - Notes - ----- - The software accounts for big-/little-endianness, and the inability of \ - hdf5 to natively store complex numbers. - - """ - assert isinstance(dset, _h5py.Dataset), 'Input is not of type h5py.Dataset' - # Single datatype - if len(dset.dtype) == 0: - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - if issubclass(converted.dtype.type, _np.integer): # Integer to float - converted = converted.astype(_np.float) - return converted - #Compound datatype of length 2-- assumed ('Re','Im') - elif len(dset.dtype) == 2: - print('Warning: h5py.complex_names set incorrectly using \'{}\' and \'{}\' \ -for Re and Im, respectively'.format(dset.dtype.names[0], dset.dtype.names[1])) - _h5py.get_config().complex_names = (dset.dtype.names[0],dset.dtype.names[1]) - dset = dset.file[dset.name] - converted = _np.ndarray(dset.shape, dtype = dset.dtype.newbyteorder('=')) - dset.read_direct(converted) - # Unknown datatype - else: - print('Warning: Unknown datatype. Returning dataset values as is.') - return dset.value - return converted
- - -
[docs]def retrieve_group_dataset_dict(filename): - """ - Given an HDF5 filename, return a dictionary with keys named with full \ - paths to datasets (values) - - Parameters - ---------- - filename : str - filename of HDF5 file - - Returns - ------- - out : dict - {group path : [dataset list]} - - Notes - ----- - - """ - try: - f = _h5py.File(filename,'r') - except OSError as err: - print(err) - else: - list_of_items = ['/'] - f.visit(list_of_items.append) - - groups_all = [] - datasets_all = [] - - for count in list_of_items: - if isinstance(f[count],_h5py.Group) == True: - groups_all.append(count) - if isinstance(f[count],_h5py.Dataset) == True: - datasets_all.append(count) - - groups_with_datasets = [] - - for group_count in groups_all: - for item_count in f[group_count]: - if isinstance(f[group_count][item_count],_h5py.Dataset): - groups_with_datasets.append(group_count) - break - - # Setup dictionary group_with_dataset : datasetnames - group_dataset_dict = [] - for group_count in groups_with_datasets: - dataset_list = [] - for item_count in f[group_count]: - if isinstance(f[group_count][item_count],_h5py.Dataset): - dataset_list.append(item_count) - group_dataset_dict.append([group_count,dataset_list]) - - group_dataset_dict = dict(group_dataset_dict) - - #print('Returning {0} groups covering {1} datasets'.format\ - # (len(groups_with_datasets), len(datasets_all))) - - - - f.close() - return group_dataset_dict
- -
[docs]def retrieve_dataset_attribute_dict(filename,datasetfullname): - """ - Given an HDF5 filename and dataset, return a dictionary with keys named \ - with parameters and values - - Parameters - ---------- - filename : str - filename of HDF5 file - - datasetfullname : str - full pathname to dataset (e.g., /group/subgroup/dataset) - - Returns - ------- - out : dict - {parameter : value} - - Notes - ----- - - """ - try: - f = _h5py.File(filename,'r') - except OSError as err: - print(err) - else: - try: - attrs = f[datasetfullname].attrs - temp = dict(attrs) - except: - print('Error in attributes... Usually an empty one') - temp = {} - for count in attrs: - try: - temp[count] = attrs[count] - except: - pass - return temp - f.close() - return None
- -
[docs]def special_exclude_datasets(filename, str_excl = '_background', new_filename = None): - """ - Removes any datasets with '_background' in the name. Creates a new - h5 file with '_excl*_.h5' appended (unless specified) - - Parameters - ---------- - filename (str) : name of file to analyze/repack/copy - - str_excl (str) : (default: '_background') exclude datasets with this string in the name - - new_filename (str) : (Optional) Output filename - - Returns - ------- - str : filename of new HDF5 file - - Writes a new file filename(-.h5) + '_excl_' + str_exclude + '.h5' - - Notes - ----- - SPECIAL : Only likely useful for the NIST developers - - """ - - if new_filename == None: - new_filename = str.strip(filename,'.h5') + '_excl_' + str_excl.strip('_') + '.h5' - else: - pass - - dataset_dict = retrieve_group_dataset_dict(filename) - - f_input = _h5py.File(filename, 'r') - f_output = _h5py.File(new_filename, 'w-') - - try: - # Interate trhough groups/subgroups - for groups in dataset_dict: - dsets_in_group = dataset_dict[groups] - - # Iterate through each filename in this group - for dset_name in dsets_in_group: - if str.find(dset_name,str_excl) == -1: - temp_name = groups + '/' + dset_name - loc = f_output.require_group(f_input[temp_name].parent.name) - print('Copying: {}'.format(temp_name)) - f_input.copy(temp_name,loc) - del temp_name - except: - print('There was an error') - return None - f_input.close() - f_output.close() - return new_filename
- -
[docs]def special_repack(filename, repack_str = '_Movie_', new_filename = None): - """ - Find datasets (1D) with a given repack_str and concatenates them into - a larger array. Other datasets are copied as is. - - Creates a new h5 file with '_repack_' + repack_str(-'_') + .h5' appended - - Parameters - ---------- - filename (str) : name of file to analyze/repack/copy - - repack_str (str) : string to find in datasets to concatenate - - new_filename (str) : (Optional) Output filename - - Returns - ------- - str : filename of new HDF5 file - - Writes a new file filename + '_repack_' + repack_str(-'_') + .h5' - - Notes - ----- - The output file cannot already exist - - SPECIAL : Only likely useful for the NIST developers - - """ - - if new_filename == None: - new_filename = str.strip(filename,'.h5') + '_repack_' + \ - repack_str.strip('_') + '.h5' - else: - pass - - dataset_dict = retrieve_group_dataset_dict(filename) - - f_input = _h5py.File(filename, 'r') - f_output = _h5py.File(new_filename, 'w-') - - try: - # Iterate through each data-containing group - for groups in dataset_dict: - dsets_in_group = dataset_dict[groups] - # Turn dataset list into one long string and look for - # repack_str if there are none, copy the whole group - if str(dsets_in_group).find(repack_str) == -1: - loc = f_output.require_group(groups) - for dset in dsets_in_group: - name = groups + '/' + dset - f_input.copy(name,loc) - else: - # Create a set from the list to remove identical entries - unique_dset_prefix_list = \ - list(set([str.split(dset_names,repack_str)[0] \ - for dset_names in dsets_in_group])) - - for unique_dset_prefix in unique_dset_prefix_list: - dset_w_prefix = [dset_names for dset_names in \ - dsets_in_group \ - if dset_names.find(unique_dset_prefix) != -1] - - name = groups + '/' + dset_w_prefix[0] - - # Init larger array with expanded size, same dtype - repack_array = _np.ndarray([len(dset_w_prefix), \ - f_input[name].value.shape[0]], dtype = \ - f_input[name].dtype) - - # Fill in columns - for count in enumerate(dset_w_prefix): - name = groups + '/' + count[1] - repack_array[count[0],:] = f_input[name].value - - loc = f_output.require_group(groups) - f_output[str(groups + '/' + unique_dset_prefix)] = repack_array - name = groups + '/' + dset_w_prefix[0] - input_attrs = f_input[str(groups + '/' + \ - dset_w_prefix[0])].attrs - - # Copy attribute from first dataset to the repack_array - for attr in input_attrs: - try: - f_output[str(groups + '/' + \ - unique_dset_prefix)].attrs.create(attr, \ - input_attrs[attr]) - except: - pass - except: - print('There was an error') - - f_input.close() - f_output.close() - - return new_filename
- -
[docs]def special_shrink_datasets(filename, dset_path, dset_name, stepsize, - xstep_attr='RasterScanParams.FastAxisSteps', - xstep_size_attr='RasterScanParams.FastAxisStepSize', - ystep_attr='RasterScanParams.SlowAxisSteps', - ystep_size_attr='RasterScanParams.SlowAxisStepSize'): - """ - Find a particular dataset and shrink it by stepping over pixels - - Parameters - ---------- - filename : str - Name of file to analyze/repack/copy - - dset_path : str - Path to dataset - - dset_attr : str - Dataset name - - stepsize : int - Step size to take (1::stepsize) - - xstep_attr : str - Name of HDF attribute that describes number of steps in the \ - X-direction - - xstep_size_attr : str - Name of HDF attribute that describes step size in the \ - X-direction - - ystep_attr : str - Name of HDF attribute that describes number of steps in the \ - Y-direction - - ystep_size_attr : str - Name of HDF attribute that describes step size in the \ - Y-direction - - Returns - ------- - str : filename of new HDF5 file - - Writes a new file filename + '_repack_' + repack_str(-'_') + .h5' - - Notes - ----- - The output file cannot already exist - - SPECIAL : Only likely useful for the NIST developers - - Example - ------- - _shrink('../mP2_w_small.h5','/BCARSImage/mP2_3_5ms_Pos_2_0/','mP2_3_5ms_Pos_2_0',10) - - """ - - f = _h5py.File(filename,'r') - - try: - dset_fullname = dset_path + dset_name - - dset_name_small = dset_name + '_small' - dset_fullname_small = dset_path + dset_name_small - - temp = _np.zeros(f[dset_fullname].shape, dtype=f[dset_fullname].dtype) - - - f[dset_fullname].read_direct(temp) - f.close() - - f = _h5py.File(filename,'r+') - temp2 = temp[0::stepsize,0::stepsize,:] - - lg_xsteps = temp.shape[1] - lg_ysteps = temp.shape[0] - sm_xsteps = temp2.shape[1] - sm_ysteps = temp2.shape[0] - - - ds = f[dset_path] - ds.create_dataset(dset_name_small, data = temp2) - except: - print('Failed') - else: - input_attrs = f[dset_fullname].attrs - - # Copy attribute from first dataset to the repack_array - for attr in input_attrs: - try: - if attr == xstep_attr: - f[dset_fullname_small].attrs.create(attr, \ - sm_xsteps) - elif attr == xstep_size_attr: - temp = input_attrs[attr] - - f[dset_fullname_small].attrs.create(attr, \ - temp*(lg_xsteps/sm_xsteps)) - - elif attr == ystep_attr: - f[dset_fullname_small].attrs.create(attr, \ - sm_ysteps) - elif attr == ystep_size_attr: - temp = input_attrs[attr] - - f[dset_fullname_small].attrs.create(attr, \ - temp*(lg_ysteps/sm_ysteps)) - else: - f[dset_fullname_small].attrs.create(attr, \ - input_attrs[attr]) - except: - pass - finally: - f.close()
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/utils/mplstyle.html b/docs/build/html/_modules/crikit/utils/mplstyle.html deleted file mode 100644 index ffb1ffd..0000000 --- a/docs/build/html/_modules/crikit/utils/mplstyle.html +++ /dev/null @@ -1,381 +0,0 @@ - - - - - - - - - - - crikit.utils.mplstyle — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Module code »
  • - -
  • crikit.utils.mplstyle
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

Source code for crikit.utils.mplstyle

-"""
-Created on Thu Jun 30 10:23:03 2016
-
-@author: chc
-"""
-
-from cycler import cycler
-import copy as _copy
-import numpy as _np
-
-
[docs]class CrikitMplStyle: - """ - - """ - - _tableau20 = _np.array([[31, 119, 180], - [174, 199, 232], - [255, 127, 14], - [255, 187, 120], - [44, 160, 44], - [152, 223, 138], - [214, 39, 40], - [255, 152, 150], - [148, 103, 189], - [197, 176, 213], - [140, 86, 75], - [196, 156, 148], - [227, 119, 194], - [247, 182, 210], - [127, 127, 127], - [199, 199, 199], - [188, 189, 34], - [219, 219, 141], - [23, 190, 207], - [158, 218, 229]], dtype=_np.float)/255 - - _tableau10 = _tableau20[::2,:] - - _tableau10_med = _np.array([[114, 158, 206], - [255, 158, 74], - [103, 191, 92], - [237, 102, 93], - [173, 139, 201], - [168, 120, 110], - [237, 151, 202], - [162, 162, 162], - [205, 204, 93], - [109, 204, 218]], dtype = _np.float)/255 - - - _base_crikit = {'font.family': ['sans-serif'], - 'font.sans-serif': ['Arial', - 'Bitstream Vera Sans', - 'DejaVu Sans', - 'Lucida Grande', - 'Verdana', - 'Geneva', - 'Lucid', - 'Avant Garde', - 'sans-serif'], - 'axes.prop_cycle': cycler('color', _tableau10), -# 'axes.prop_cycle': plt.style.library['ggplot']['axes.prop_cycle'], - 'image.cmap': 'viridis', - 'image.interpolation': 'none'} - - _paper_halfwidth = {'axes.labelsize': 8.8, - 'axes.titlesize': 9.6, - 'figure.figsize': [3.3, 4.4], - 'grid.linewidth': 0.8, - 'legend.fontsize': 8.0, - 'lines.linewidth': 1.4, - 'lines.markeredgewidth': 0.0, - 'lines.markersize': 5.6, - 'patch.linewidth': 0.24, - 'xtick.labelsize': 8.0, - 'xtick.major.pad': 5.6, - 'xtick.major.width': 0.8, - 'xtick.minor.width': 0.4, - 'ytick.labelsize': 8.0, - 'ytick.major.pad': 5.6, - 'ytick.major.width': 0.8, - 'ytick.minor.width': 0.4} - - _paper_fullwidth = {'axes.labelsize': 8.8, - 'axes.titlesize': 9.6, - 'figure.figsize': [6.4, 4.4], - 'grid.linewidth': 0.8, - 'legend.fontsize': 8.8, - 'lines.linewidth': 1.4, - 'lines.markeredgewidth': 0.0, - 'lines.markersize': 5.6, - 'patch.linewidth': 0.24, - 'xtick.labelsize': 8.0, - 'xtick.major.pad': 5.6, - 'xtick.major.width': 0.8, - 'xtick.minor.width': 0.4, - 'ytick.labelsize': 8.0, - 'ytick.major.pad': 5.6, - 'ytick.major.width': 0.8, - 'ytick.minor.width': 0.4} - - _poster = {'axes.labelsize': 17.6, - 'axes.titlesize': 19.2, - 'figure.figsize': [12.8, 8.8], - 'grid.linewidth': 1.6, - 'legend.fontsize': 16.0, - 'lines.linewidth': 2.8, - 'lines.markeredgewidth': 0.0, - 'lines.markersize': 11.2, - 'patch.linewidth': 0.48, - 'xtick.labelsize': 16.0, - 'xtick.major.pad': 11.2, - 'xtick.major.width': 1.6, - 'xtick.minor.width': 0.8, - 'ytick.labelsize': 16.0, - 'ytick.major.pad': 11.2, - 'ytick.major.width': 1.6, - 'ytick.minor.width': 0.8} - - basic_halfwidth = _copy.deepcopy(_base_crikit) - basic_halfwidth.update(_paper_halfwidth) - - basic_fullwidth = _copy.deepcopy(_base_crikit) - basic_fullwidth.update(_paper_fullwidth) - - basic_poster = _copy.deepcopy(_base_crikit) - basic_poster.update(_poster)
- - -if __name__ == '__main__': - import matplotlib.pyplot as _plt - import numpy as _np - - x = _np.arange(100) - _plt.style.use('classic') - style = CrikitMplStyle.basic_fullwidth - _plt.style.use(style) - - _plt.figure() - - _plt.plot((_np.random.rand(10,1)*x).T, label='test') - _plt.legend() - _plt.show() - - _plt.figure() - _plt.imshow(_np.random.rand(100,100)) - _plt.colorbar() - _plt.show() -
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/crikit/utils/roi.html b/docs/build/html/_modules/crikit/utils/roi.html deleted file mode 100644 index 4da6510..0000000 --- a/docs/build/html/_modules/crikit/utils/roi.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - - - - - - crikit.utils.roi — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
- -

Source code for crikit.utils.roi

-"""
-Created on Wed Jun 15 23:33:41 2016
-
-@author: chc
-"""
-import numpy as _np
-from matplotlib.path import Path as _Path
-
-
-
[docs]def verts_to_path(verts, isclosed=True): - """ - Convert vertices to paths - """ - if not isclosed: - verts += [verts[0]] - else: - pass - codes = [_Path.MOVETO] + [_Path.LINETO] * (len(verts)-2) + \ - [_Path.CLOSEPOLY] - - return _Path(verts, codes)
- - -
[docs]def pts_in_path(path): - """ - Return points (pixels) that fall within path (but not on boundary) - """ - - # Get bounding box of path (simplify geometry) - exts = path.get_extents() - - # Bottom-left, top-right coordinates - bl, tr = exts.get_points() - - # Temporary x- and y-vectors and meshgrids - x = _np.arange(bl[0], tr[0]) - y = _np.arange(bl[1], tr[1]) - X, Y = _np.meshgrid(x, y) - - # Linearize meshgrid - allpts = _np.hstack((X.flatten()[:, None], Y.flatten()[:, None])) - - # Mask of points within path (NOT including boundary) - mask_allpts = path.contains_points(allpts) - - # Get and return x- and y-pixels - x_pts, y_pts = _np.array([X.flatten()[mask_allpts], - Y.flatten()[mask_allpts]]) - return x_pts, y_pts
- - -
[docs]def pts_to_verts(xvec, yvec): - """ - Convert points to vertices, i.e., convert from 2 1D arrays (or list) of \ - x- and y-coordinates to a list-of-lists of [x,y] pairs - """ - verts = [] - for count in range(len(xvec)): - verts.append([xvec[count], yvec[count]]) - return verts
- - -
[docs]def verts_to_points_in_roi(verts): - """ - Vertice list defining ROI in, points within returned. - """ - path = verts_to_path(verts, isclosed=False) - x_pts, y_pts = pts_in_path(path) - return x_pts, y_pts
-
- -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html deleted file mode 100644 index 79d033e..0000000 --- a/docs/build/html/_modules/index.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - - - - - - - Overview: module code — CRIKit2 17.10b1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
-
- - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Overview: module code
  • - - -
  • - - - -
  • - -
- - -
-
-
-
- -

All modules for which code is available

- - -
-
- -
-
- - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_sources/algorithms.rst.txt b/docs/build/html/_sources/algorithms.rst.txt deleted file mode 100644 index 5d79315..0000000 --- a/docs/build/html/_sources/algorithms.rst.txt +++ /dev/null @@ -1,16 +0,0 @@ -.. _algorithms: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -Command Line Tools & Algorthms -=============================== - diff --git a/docs/build/html/_sources/api.rst.txt b/docs/build/html/_sources/api.rst.txt deleted file mode 100644 index d25df71..0000000 --- a/docs/build/html/_sources/api.rst.txt +++ /dev/null @@ -1,161 +0,0 @@ -.. _api: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -API Reference -============= - -This is not an exhaustive list of classes and functions, -but rather those most likely to be of interest to users and developer. -See :ref:`genindex` and :ref:`modindex` for a full list. - -:mod:`crikit.cri`: Coherent Raman Imagery (CRI) classes and functions ---------------------------------------------------------------------- - -.. automodule:: crikit.cri - -Classes -~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - - cri.kk.KramersKronig - cri.error_correction.PhaseErrCorrectALS - cri.error_correction.ScaleErrCorrectSG - -Functions -~~~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - - cri.algorithms.kk.kkrelation - cri.algorithms.kk.hilbertfft - -:mod:`crikit.data`: Data container classes ------------------------------------------- - -.. automodule:: crikit.data - -Classes -~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - data.frequency.Frequency - data.replicate.Replicate - - data.spectrum.Spectrum - data.spectra.Spectra - data.hsi.Hsi - -:mod:`crikit.io`: Input/Output (IO) functions ----------------------------------------------- - -.. automodule:: crikit.io - -Functions -~~~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - io.csv_nist.csv_nist_import_data - io.hdf5.hdf_is_valid_dsets - io.hdf5.hdf_attr_to_dict - io.hdf5.hdf_import_data - io.meta_configs.special_nist_bcars1_sample_scan - io.meta_configs.special_nist_bcars2 - io.meta_process.meta_process - io.meta_process.rosetta_query - -:mod:`crikit.measurement`: Measurement classes ----------------------------------------------- - -.. automodule:: crikit.measurement - -Classes -~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - measurement.fftspatialnoise.FFTSignalMetric - measurement.peakamps.MeasurePeak - measurement.peakamps.MeasurePeakAdd - measurement.peakamps.MeasurePeakBWTroughs - measurement.peakamps.MeasurePeakMinus - measurement.peakamps.MeasurePeakDivide - measurement.peakamps.MeasurePeakMultiply - measurement.peakamps.MeasurePeakSummation - measurement.peakfind.PeakFinder - -:mod:`crikit.preprocess`: Preprocessing classes and functions -------------------------------------------------------------- - -.. automodule:: crikit.preprocess - -Classes -~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - preprocess.algorithms.als.AlsCvxopt - preprocess.algorithms.anscombe.anscombe_inverse_exact_unbiased - preprocess.algorithms.anscombe.gen_anscombe_forward - preprocess.algorithms.anscombe.gen_anscombe_inverse_closed_form - preprocess.algorithms.anscombe.gen_anscombe_inverse_exact_unbiased - preprocess.algorithms.arpls.ArPlsCvxopt - preprocess.crop.ZeroColumn - preprocess.crop.ZeroRow - preprocess.denoise.SVDDecompose - preprocess.denoise.SVDRecompose - preprocess.standardize.Anscombe - preprocess.standardize.AnscombeInverse - preprocess.subtract_baseline.SubtractBaselineALS - preprocess.subtract_dark.SubtractDark - preprocess.subtract_mean.SubtractMeanOverRange - -:mod:`crikit.utils`: Utility functions ---------------------------------------- - -.. automodule:: crikit.utils - -Classes -~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - utils.breadcrumb.BCPre - -Functions -~~~~~~~~~ -.. currentmodule:: crikit - -.. autosummary:: - - utils.general.arange_nonzero - utils.general.expand_1d_to_ndim - utils.general.expand_1d_to_ndim_data - utils.general.find_nearest - utils.general.lin_from_row_col - utils.general.mean_nd_to_1d - utils.general.np_fcn_nd_to_1d - utils.general.row_col_from_lin - utils.general.std_nd_to_1d - diff --git a/docs/build/html/_sources/cri_walkthru.rst.txt b/docs/build/html/_sources/cri_walkthru.rst.txt deleted file mode 100644 index bbeb867..0000000 --- a/docs/build/html/_sources/cri_walkthru.rst.txt +++ /dev/null @@ -1,597 +0,0 @@ -.. _cri_walkthru: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -Walk-Thru: CRI Processing -========================= - -This walk-thru will take you through several steps: - -- `Overview`_ -- `Generating the built-in Raman/BCARS numerical phantom`_ -- `Viewing dark, NRB, and dataset spectra`_ -- `Dark subtraction`_ -- `Residual dark subtraction (Optional)`_ -- `Variance stabilization`_ -- `Denoising via singular value decomposition (SVD)`_ -- `The inverse Anscombe transformation`_ -- `Phase retrieval via Kramers-Kronig relation`_ -- `Phase error correction`_ -- `Scale error correction`_ -- `Calibration`_ -- `Saving`_ -- `Pseudo-color imagery`_ -- `Skipped actions in a normal CRI workflow`_ - - `Loading HDF file Hsi dataset`_ - - `Loading Dark dataset`_ - -`Denoise Dark (Optional)`_ - - `Loading an NRB dataset`_ - - From HDF - - From an ROI within the **Hsi** dataset - -The screenshots within this manual may or may not reflect the exact look of the -version of CRIkit2 UI that you are using. - -Overview --------- - -.. image:: _static/cri_wt/Overview.png - :align: center - -Generating the built-in Raman/BCARS numerical phantom ------------------------------------------------------ -CRIkit2 comes with a built-in numerical phantom, which is dervived from an -actual BCARS image collected from murine pancreas tissue [Camp16]_. This -numerical phantom may be used as a **Raman** or a **BCARS** model. The Raman -model produces an HSI wherein each pixel contains a Raman spectrum. The BCARS -model incorporates a nonresonant background (NRB) and excitation source profile; -thus, generating raw BCARS spectra, similar to those generated here at NIST [Camp14]_. - -1. **Help** >> **BCARS Numerical Phantom** -2. Check Noise and Dark check boxes. - - **Check** Gaussian (AWGN) - - **Std Dev**: 12.44 - - **Check** Poisson - - **Multiplier (alpha)**: 1.4 - - **Check** Dark Constant - - **Level**: 1600.0 -3. Select Subsampling - - Subsampling will reduce the memory and performance burden on your computer. - - This tutorial will demonstrate with 1x (no sub-sampling), but you can feel - free to use up to 4x to make things speedier. -4. Press **Ok** pushbutton. - -.. image:: _static/cri_wt/LoadModel.png - :align: center - -There now is a fully loaded BCARS phantom. Additionally, the **NRB** reference -is loaded (**View** >> **NRB Spect**) and the **Dark** spectrum is loaded -(**View** >> **Dark Spect**). - -.. image:: _static/cri_wt/Overview_post_gen_BCARS.png - :align: center - -Viewing dark, NRB, and dataset spectra --------------------------------------- -To view the loaded **Dark** spectrum(a): - -- **View** >> **Dark Spect** - -To view the loaded **NRB** spectrum(a): - -- **View** >> **NRB Spect** - -There are two primary methods to view spectra from within the dataset: point -spectra and ROI spectra. - -To view the spectrum from a single point within the dataset (2 methods): - -- **View** >> **Pt Spect** -- Click the **Pt Spect** button on the main ribbon - -Either method will change your cursor into a cross. Select a pixel within the -**single-frequency (SF) image** and **left-click**. This will pop-up the plotter window with the -spectrum. - -To view the mean spectrum from within an ROI (2 methods): - -- **View** >> **ROI Spect** -- Click the **ROI Spect** button on the main ribbon - -Again, either method will change your cursor into a cross. The ROI is defined by -a polyhedron within the **single-frequency (SF) image**. Select vertices with -a **left-click** with your mouse. Close the polyhedrom with a single -**right-click**. The location of the right-click does not matter as this only -indicates to connect the last selected vertex and the first. This will pop-up -the plotter window with 2 components: the mean spectrum (dark, solid line) and -a patch (lighter, solid shading) that indicates plus-minus 1 standard deviation. - -.. image:: _static/cri_wt/RoiRawSpectra.png - :align: center - -Dark subtraction ----------------- -The dark signal is the intrinsic signal level generated by the detector, even -when no photons are incident on the detector. Typically, a measurement is made -with the detector (or incident) sources blocked. - -Under normal operation, you would load a dark spectrum(a) from an external -file. During the generation of the BCARS numerical phantom, the dark signal -is co-generated. - -To subtract the dark spectrum(a) from the HSI (2 methods): - -- **Pre-Process** >> **Dark Sub...** -- Click the **Dark Sub** button on the main ribbon - -Two pop-up dialog boxes will appear: - -- Subtract Dark Spectrum from Image?: **Click**: OK -- Subtract Dark Spectrum from NRB Spectrum(a)?: **Click**: OK - -.. image:: _static/cri_wt/Sub_dark_dialogs.png - :align: center - -Variance stabilization ----------------------- -CRIkit2 provides variance stabilitization through the forward Anscombe -transformation that enables signals with mixed additive white Gaussian noise -(AWGN) and shot-noise (Poisson) to be transformed into a signal with -approximately uniform AWGN only [Foi13]_. Conversely, CRIkit2 provides an -exact, unbiased inverse of the generalized Anscombe variance-stabilizing -transform [Foi13]_. - -Many denoising and factorization methods, such as principle component analysis -(PCA), singular value decomposition (SVD), nonnegative matrix factorization -(NMF); explicitly or implicitly assume a normal (i.e., Gaussian) distribution -of noise (and signals). Thus, variance stabilization may aid actions involving -such tasks [Camp16]_. - -In this tutorial, we will use the Anscombe transformation prior to -**SVD denoising**. Additionally, we will apply the **inverse Anscombe** -transform **after** SVD denoising. - -To perform the forward Anscombe transformation (2 methods): - -- **Pre-Process** >> **Standardize** >> **Anscombe** -- Click the **Anscombe** button on the main ribbon - -A pop-up dialog will appear asking for two necessary pieces of information: - -- The standard deviation of the AWGN -- The shot-noise (Poisson) noise multiplier - -Normally, one would need to calculate/measure or estimate these parameters, but -the **numerical phantom, by default, applies**: - -- Gaussian noise standard deviation: 12.44 -- Poisson noise gain: 1.4 - -.. image:: _static/cri_wt/Anscombe.png - :align: center - - -Denoising via singular value decomposition (SVD) ------------------------------------------------- -SVD is a linear algebra method that transforms a matrix into the multiplication -of three matrices: the left-singular vectors matrix, the singular value matrix, -and the right-singular vector matrix. The use of SVD for denoising has been -extensively explored for both traditional computer imagery -[Narendra75]_ [Patterson75]_, and CRI [Camp16]_ [Lee11]_. - -In short, SVD will decompose the CRI image into a series of images and spectra. -Ideally, the spectra/images that contain real (ie non-noise) signal -contributions are totally separate from those containing noise. One can thus -reconstruct a noiseless image from the noise-free images/spectra decompositions. - -CRIkit2 performs the SVD decomposition and raises a new user interface (UI) -that displays the decomposed images and spectra, providing information to the -user to interactively select those with minimal noise. - -.. image:: _static/cri_wt/SVD_Ui.png - :align: center - -Recommendations: - -- Select all singular values with visible spatial **or** spectral components -- Remember to press **Apply** button after selections to-keep of current 6 - displayed. -- Press **Next** pushbutton to view next 6 components. -- Press **Ok** pushbutton to recompose the CRI image with only selected - components. - -In this tutorial, selections [0,1,2,3,4,5,6] are kept (7 total). - -.. image:: _static/cri_wt/Spectrum_Before_After_SVD.png - :align: center - -**Note**: The example spectra are before Anscombe-SVD; and after -Anscombe-SVD-inverse Anscombe. - -The inverse Anscombe transformation ------------------------------------ -CRIkit2 provides an exact, unbiased inverse of the generalized Anscombe -variance-stabilizing transform to convert the variance-stabilized image -back into a mixed-noise version [Foi13]_. - -To perform the inverse Anscombe transformation (2 methods): - -- **Pre-Process** >> **Standardize** >> **Inv Anscombe** -- Click the **Inv Anscombe** button on the main ribbon - -A pop-up dialog will appear asking for two necessary pieces of information: - -- The standard deviation of the AWGN -- The shot-noise (Poisson) noise multiplier - -**Note**: these values will be pre-filled with the values entered from the -forward Anscombe transformation. It would be unusual to not use these values. - -Phase retrieval via Kramers-Kronig relation -------------------------------------------- -In CRI imagery acquired through CARS methods, phase retrieval methods are -used to separate CARS and NRB signal contribution, i.e. to extract the Raman -spectral signatures [Liu09]_ [Camp16]_. - -CRIkit2 provides access to a Kramers-Kronig (KK) relation implemented using a -Fourier transform-based Hilbert transform [Camp16]_. - -This KK implementation requires an approximate NRB, which may be imported -through several means: - -- Selection of a ROI (e.g., selecting an ROI of water) -- Spectra imported from an external file -- Merging two NRB spectra from ROI's or external files. - -During the generation of the BCARS numerical phantom, the NRB signal -is co-generated and loaded. - -To perform the KK (2 methods): - -- **Pre-Process** >> **Coherent Raman Imaging** >> **KK** -- Click the **KK** button on the main ribbon - -.. image:: _static/cri_wt/KKOptions.png - :align: center - -This dialog enables fine-tuning of several parameters: - -- NRB bias (constant to add/subract from NRB spectrum) -- CARS bias (constant to add/subract from all HSI spectra) -- Phase offset (constant phase to add/subtract to all KK'd spectra) -- Pad factor (window-padding multiple of spectral length [Liu09]_) - -The **Interative Setting Selection** provides preview spectra of several spectra. -These spectra are the mean of the 4 quandrants (i.e. fourths) of the total image -and the center fourth. - -.. image:: _static/cri_wt/KKInteractive.png - :align: center - -For this tutorial: - -- CARS/NRB bias: 0 -- Phase Offset: 0 -- Pad Factor: 1 - -When **finished** press **Ok** pushbutton. - -Phase error correction ----------------------- -The KK relation will extract Raman signatures accurately under certain conditions, -one being that the NRB can be separately measured and provided -- **at every -pixel**. This condition, however, can not readily be met; thus, reference NRB -are typically utilized. An ideal reference NRB should not contain any Raman peaks -within the spectral region of interest. Typical examples are glasses, salts, and -water [Camp14]_ [Camp16]_ [Karuna16]_. - -Unfortunately, the use of a reference (i.e., non-exact) NRB results in amplitude -and phase error. Phase error correction **and** scale error correction correct -for these complex errors. Phase error correction is performed by finding the -slowly varying baseline of the spectral phase at each pixel. - -CRIkit2 uses an asymmetric least-squares (ALS) method [Eilers05]_. The -custom implementation 3 main parameters: - -- P (asymmetry parameter) -- Lambda (smoothness parameter) -- Sub-sampling factor (sub-sample the spectra to improve speed) - -**Note**: This is typically the **slowest processing step** in the workflow. A -300 x 300 x 900 pixel image with no sub-sampling of the ALS may require 45 -**minutes** or longer to complete. - -Additionally, this dialog allows for a **fixed P-value** across the spectrum -or a **log-linear P-value** that varies across the spectrum. For this tutorial -we will use the **Fixed-P**. - -To perform phase error correction (2 methods): - -- **Pre-Process** >> **Coherent Raman Imaging** >> **Phase Err...** -- Click the **Phase Err** button on the main ribbon - -Recommendations: - -- The sub-sampling parameter will increase the speed of the detrending - (potentially quadratically), but at the expense of accuracy. -- Though P- and Lambda-values are independent, the most important factor - is the ratio of the two. -- There may be window-edge errors at the extreme points of spectra. The - **Fix End-Points** option may correct these distortions; though, for extremely - minor baseline correction, this may cause more harm than help. -- The exact settings are a function of the particular optical system's - resolution, spectral sampling, and reference material used. - -This tutorial and the numerical phantom, **unlike real experiments**, provides -the exact NRB; thus, phase-error is extremely small (numerical error). - -For this tutorial: - -- **Fixed-P**: 1e-6 -- **Lambda*: 1 -- **Sub-Sampling Factor**: 10 -- **Max Iterations**: 100 -- **Min Difference**: 1e-6 -- **Fix End-Points**: False (Unchecked) - -For typical experiments: - -- **Fixed-P**: 1e-4 to 1e-2 (increment by half order-of-magnitude) -- **Lambda*: 1 -- **Sub-Sampling Factor**: 10 -- **Max Iterations**: 100 -- **Min Difference**: 1e-6 -- **Fix End-Points**: True (Checked) - -When **finished** press **Ok** pushbutton. - -.. image:: _static/cri_wt/ALS.png - :align: center - -Scale error correction ------------------------ -The use of a reference (i.e., non-exact) NRB results in amplitude -and phase error. Phase error correction **and** scale error correction correct -for these complex errors. Scale error correction is performed by finding the -median trend line that bisects the real portion of the complex spectra at each -pixel [Camp16]_. - -CRIkit2 uses a Savitky-Golay filter to find a smooth median line, which requires -2 parameters: - -- Window width (sliding-window width to polynomial fit). Must be odd-valued. -- Order (order of polynomial to fit) - -To perform phase error correction (2 methods): - -- **Pre-Process** >> **Coherent Raman Imaging** >> **Scale Err...** -- Click the **Scale Err** button on the main ribbon - -Recommendations: - -- Set the **order** to 1 or 2 -- Expand the **window width** to a large enough value that the median line - approximately bisects the shown spectra. -- The exact settings are a function of the particular optical system's - resolution, spectral sampling, and reference material used. - -Typical experimental values: - -- **Window width**: 601 -- **Order**: 2 - -When **finished** press **Ok** pushbutton. - -.. image:: _static/cri_wt/SG.png - :align: center - -Calibration ------------ -CRIkit2 provides a UI for single-peak calibration that properly accounts -for the nonlinear relationship between wavenumber and wavelength (i.e. what -spectrometers measure across) in BCARS. - -In typical bio-experiments, we utilize the 1,004 cm-1 peak (phenylalanine) [DeGelder07]_. - -To use a different peak, change the **Correct WN** value to the new peak wavenumber -and fill-in the **Measured WN** with what the average spectra show within the -upper plot. - -To perform calibration (2 methods): - -- **Edit** >> **Calibrate** -- Click the **Calibrate** button on the main ribbon - -Recommendations - -- Click the **Zoom** button on the upper plot and select around the 1,004 cm-1 - region. -- Enter the actual peak location in the **Measured WN** box. -- If the spectra do not reveal a feature of interest, return (click **Cancel**) - to the main UI and use the **ROI Spect** or **Pt Spect** to plot the spectrum - from a pixel(s) of interest. Identify the location of the particular - calibration peak. Re-open the **calibration** tool (ignore the plots) and enter - the **Correct WN** and **Measured WN** values. - -For this tutorial there is no calibration necessary. Click **Cancel** pushbutton. - -.. image:: _static/cri_wt/Calibration.png - :align: center - -Saving -------- - -.. image:: _static/cri_wt/Save.png - :align: center - -Pseudo-color imagery --------------------- -Nuclei: - -- **Color 0** tab -- **Color** drop-down box setting: Yellow -- Math function: "Peak b/w Troughs" -- Peak (Freq 1 button): 786 cm-1 -- Trough 1 (Freq 2 button): 767 cm-1 -- Trough 2 (Freq 3 button): 809 cm-1 -- **Conditional** math function: "SUM" -- Start freq (Freq 1 button): 2700 cm-1 -- Stop freq (Freq 1 button): 3000 cm-1 -- **Conditional** comparitor: ">" -- **Conditional** value: 1.0 -- **Minimum** value setting: 0.002 - -.. image:: _static/cri_wt/SingleColorExample.png - :align: center - -.. image:: _static/cri_wt/Nuclei.png - :align: center - -Phenylalanine: - -- **Color 1** tab -- **Color** drop-down box setting: Magenta -- Math function: "Peak b/w Troughs" -- Peak (Freq 1 button): 1002 cm-1 -- Trough 1 (Freq 2 button): 986 cm-1 -- Trough 2 (Freq 3 button): 1019 cm-1 -- **Conditional** math function: "SUM" -- Start freq (Freq 1 button): 2700 cm-1 -- Stop freq (Freq 1 button): 3000 cm-1 -- **Conditional** comparitor: ">" -- **Conditional** value: 1.0 -- **Minimum** value setting: 0.002 - -.. image:: _static/cri_wt/Phenylalanine.png - :align: center - -Structural Proteins: - -- **Color 2** tab -- **Color** drop-down box setting: Cyan -- Math function: "Peak b/w Troughs" -- Peak (Freq 1 button): 937 cm-1 -- Trough 1 (Freq 2 button): 902 cm-1 -- Trough 2 (Freq 3 button): 980 cm-1 -- **Conditional** math function: "SUM" -- Start freq (Freq 1 button): 2700 cm-1 -- Stop freq (Freq 1 button): 3000 cm-1 -- **Conditional** comparitor: ">" -- **Conditional** value: 1.0 -- **Minimum** value setting: 0.002 - -.. image:: _static/cri_wt/StructuralProtein.png - :align: center - -Elastin: - -- **Color 3** tab -- **Color** drop-down box setting: B&W (Black-and-white) -- Math function: "Peak b/w Troughs" -- Peak (Freq 1 button): 525 cm-1 -- Trough 1 (Freq 2 button): 513 cm-1 -- Trough 2 (Freq 3 button): 540 cm-1 -- **Conditional** math function: " / " -- Start freq (Freq 1 button): 1003 cm-1 -- Stop freq (Freq 1 button): 1029 cm-1 -- **Conditional** comparitor: ">" -- **Conditional** value: 1.4 -- **Minimum** value setting: 0.0006 - -.. image:: _static/cri_wt/Elastin.png - :align: center - -.. image:: _static/cri_wt/CompositeColorExample.png - :align: center - -Skipped actions in a normal CRI workflow ----------------------------------------- - -Loading HDF file Hsi dataset -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. image:: _static/cri_wt/Open.png - :align: center - - - -Loading Dark dataset -~~~~~~~~~~~~~~~~~~~~ - -.. image:: _static/cri_wt/OpenDark.png - :align: center - -Denoise Dark (Optional) -~~~~~~~~~~~~~~~~~~~~~~~ - -.. image:: _static/cri_wt/denoise_dark.jpg - :align: center - -Loading an NRB from HDF file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. image:: _static/cri_wt/OpenNRB.png - :align: center - -Load an NRB from a region-of-interest (ROI) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. image:: _static/cri_wt/load_nrb_roi.jpg - :align: center - -Merge two NRB datasets -~~~~~~~~~~~~~~~~~~~~~~ - -Residual dark subtraction (Optional) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -References ----------- - -.. [Camp14] C. H. Camp Jr, Y. J. Lee, J. M. Heddleston, C. M. Hartshorn, A. R. - Hight Walker, J. N. Rich, J. D. Lathia, and M. T. Cicerone, "High-Speed - Coherent Raman Fingerprint Imaging of Biological Tissues," Nat. Photonics 8, - 627–634 (2014). - -.. [Camp16] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative, - comparable coherent anti-Stokes Raman scattering (CARS) spectroscopy: - correcting errors in phase retrieval," J. Raman Spectrosc. 47, 408–415 (2016). - -.. [DeGelder07] J. De Gelder, K. De Gussem, P. Vandenabeele, and L. Moens, - "Reference database of Raman spectra of biological molecules," J. Raman - Spectrosc. 38, 1133–1147 (2007). - -.. [Eilers05] P. H. C. Eilers and H. F. M. Boelens, "Baseline Correction with - Asymmetric Least Squares Smoothing," (Unpublished, 2005). - https://zanran_storage.s3.amazonaws.com/www.science.uva.nl/ContentPages/443199618.pdf - -.. [Foi13] M. Mäkitalo and A. Foi, "Optimal inversion of the generalized - anscombe transformation for Poisson-Gaussian noise," IEEE Trans. Image - Process. 22, 91–103 (2013). - -.. [Karuna16] A. Karuna, F. Masia, P. Borri, and W. Langbein, "Hyperspectral - volumetric coherent anti-Stokes Raman scattering microscopy: quantitative - volume determination and NaCl as non-resonant standard," J. Raman Spectrosc. - 47, 1167–1173 (2016). - -.. [Lee11] Y. J. Lee, D. Moon, K. B. Migler, and M. T. Cicerone, "Quantitative - image analysis of broadband CARS hyperspectral images of polymer blends," - Anal. Chem. 83, 2733–2739 (2011). - -.. [Liu09] Y. X. Liu, Y. J. Lee, and M. T. Cicerone, "Broadband CARS spectral - phase retrieval using a time-domain Kramers-Kronig transform," Opt. Lett. 34, - 1363–1365 (2009). - -.. [Narendra75] T. S. Huang and P. M. Narendra, "Image restoration by singular - value decomposition.," Appl. Opt. 14, 2213–6 (1975). - -.. [Patterson75] H. C. Andrews and C. L. Patterson, "Outer Product Expansions - and Their Uses in Digital Image Processing," Am. Math. Mon. 82, 1–13 (1975). diff --git a/docs/build/html/_sources/crikit.cri.algorithms.rst.txt b/docs/build/html/_sources/crikit.cri.algorithms.rst.txt deleted file mode 100644 index a1cdb1f..0000000 --- a/docs/build/html/_sources/crikit.cri.algorithms.rst.txt +++ /dev/null @@ -1,22 +0,0 @@ -crikit\.cri\.algorithms package -=============================== - -Submodules ----------- - -crikit\.cri\.algorithms\.kk module ----------------------------------- - -.. automodule:: crikit.cri.algorithms.kk - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.cri.algorithms - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.cri.rst.txt b/docs/build/html/_sources/crikit.cri.rst.txt deleted file mode 100644 index a1cade9..0000000 --- a/docs/build/html/_sources/crikit.cri.rst.txt +++ /dev/null @@ -1,46 +0,0 @@ -crikit\.cri package -=================== - -Subpackages ------------ - -.. toctree:: - - crikit.cri.algorithms - crikit.cri.tests - -Submodules ----------- - -crikit\.cri\.error\_correction module -------------------------------------- - -.. automodule:: crikit.cri.error_correction - :members: - :undoc-members: - :show-inheritance: - -crikit\.cri\.kk module ----------------------- - -.. automodule:: crikit.cri.kk - :members: - :undoc-members: - :show-inheritance: - -crikit\.cri\.merge\_nrbs module -------------------------------- - -.. automodule:: crikit.cri.merge_nrbs - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.cri - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.cri.tests.rst.txt b/docs/build/html/_sources/crikit.cri.tests.rst.txt deleted file mode 100644 index 54b35ac..0000000 --- a/docs/build/html/_sources/crikit.cri.tests.rst.txt +++ /dev/null @@ -1,38 +0,0 @@ -crikit\.cri\.tests package -========================== - -Submodules ----------- - -crikit\.cri\.tests\.test\_hilbert module ----------------------------------------- - -.. automodule:: crikit.cri.tests.test_hilbert - :members: - :undoc-members: - :show-inheritance: - -crikit\.cri\.tests\.test\_kk module ------------------------------------ - -.. automodule:: crikit.cri.tests.test_kk - :members: - :undoc-members: - :show-inheritance: - -crikit\.cri\.tests\.test\_kk\_alg module ----------------------------------------- - -.. automodule:: crikit.cri.tests.test_kk_alg - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.cri.tests - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.data.rst.txt b/docs/build/html/_sources/crikit.data.rst.txt deleted file mode 100644 index 2163611..0000000 --- a/docs/build/html/_sources/crikit.data.rst.txt +++ /dev/null @@ -1,62 +0,0 @@ -crikit\.data package -==================== - -Submodules ----------- - -crikit\.data\.factorized module -------------------------------- - -.. automodule:: crikit.data.factorized - :members: - :undoc-members: - :show-inheritance: - -crikit\.data\.frequency module ------------------------------- - -.. automodule:: crikit.data.frequency - :members: - :undoc-members: - :show-inheritance: - -crikit\.data\.hsi module ------------------------- - -.. automodule:: crikit.data.hsi - :members: - :undoc-members: - :show-inheritance: - -crikit\.data\.replicate module ------------------------------- - -.. automodule:: crikit.data.replicate - :members: - :undoc-members: - :show-inheritance: - -crikit\.data\.spectra module ----------------------------- - -.. automodule:: crikit.data.spectra - :members: - :undoc-members: - :show-inheritance: - -crikit\.data\.spectrum module ------------------------------ - -.. automodule:: crikit.data.spectrum - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.data - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.datasets.rst.txt b/docs/build/html/_sources/crikit.datasets.rst.txt deleted file mode 100644 index ed42e31..0000000 --- a/docs/build/html/_sources/crikit.datasets.rst.txt +++ /dev/null @@ -1,22 +0,0 @@ -crikit\.datasets package -======================== - -Submodules ----------- - -crikit\.datasets\.model module ------------------------------- - -.. automodule:: crikit.datasets.model - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.datasets - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.io.rst.txt b/docs/build/html/_sources/crikit.io.rst.txt deleted file mode 100644 index d2ecf2c..0000000 --- a/docs/build/html/_sources/crikit.io.rst.txt +++ /dev/null @@ -1,54 +0,0 @@ -crikit\.io package -================== - -Submodules ----------- - -crikit\.io\.csv\_nist module ----------------------------- - -.. automodule:: crikit.io.csv_nist - :members: - :undoc-members: - :show-inheritance: - -crikit\.io\.hdf5 module ------------------------ - -.. automodule:: crikit.io.hdf5 - :members: - :undoc-members: - :show-inheritance: - -crikit\.io\.macros module -------------------------- - -.. automodule:: crikit.io.macros - :members: - :undoc-members: - :show-inheritance: - -crikit\.io\.meta\_configs module --------------------------------- - -.. automodule:: crikit.io.meta_configs - :members: - :undoc-members: - :show-inheritance: - -crikit\.io\.meta\_process module --------------------------------- - -.. automodule:: crikit.io.meta_process - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.io - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.measurement.rst.txt b/docs/build/html/_sources/crikit.measurement.rst.txt deleted file mode 100644 index 4fccd03..0000000 --- a/docs/build/html/_sources/crikit.measurement.rst.txt +++ /dev/null @@ -1,45 +0,0 @@ -crikit\.measurement package -=========================== - -Subpackages ------------ - -.. toctree:: - - crikit.measurement.tests - -Submodules ----------- - -crikit\.measurement\.fftspatialnoise module -------------------------------------------- - -.. automodule:: crikit.measurement.fftspatialnoise - :members: - :undoc-members: - :show-inheritance: - -crikit\.measurement\.peakamps module ------------------------------------- - -.. automodule:: crikit.measurement.peakamps - :members: - :undoc-members: - :show-inheritance: - -crikit\.measurement\.peakfind module ------------------------------------- - -.. automodule:: crikit.measurement.peakfind - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.measurement - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.measurement.tests.rst.txt b/docs/build/html/_sources/crikit.measurement.tests.rst.txt deleted file mode 100644 index 9815a7e..0000000 --- a/docs/build/html/_sources/crikit.measurement.tests.rst.txt +++ /dev/null @@ -1,22 +0,0 @@ -crikit\.measurement\.tests package -================================== - -Submodules ----------- - -crikit\.measurement\.tests\.test\_peakfind module -------------------------------------------------- - -.. automodule:: crikit.measurement.tests.test_peakfind - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.measurement.tests - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.preprocess.algorithms.rst.txt b/docs/build/html/_sources/crikit.preprocess.algorithms.rst.txt deleted file mode 100644 index 5521b2d..0000000 --- a/docs/build/html/_sources/crikit.preprocess.algorithms.rst.txt +++ /dev/null @@ -1,46 +0,0 @@ -crikit\.preprocess\.algorithms package -====================================== - -Submodules ----------- - -crikit\.preprocess\.algorithms\.abstract\_als module ----------------------------------------------------- - -.. automodule:: crikit.preprocess.algorithms.abstract_als - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.algorithms\.als module ------------------------------------------- - -.. automodule:: crikit.preprocess.algorithms.als - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.algorithms\.anscombe module ------------------------------------------------ - -.. automodule:: crikit.preprocess.algorithms.anscombe - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.algorithms\.arpls module --------------------------------------------- - -.. automodule:: crikit.preprocess.algorithms.arpls - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.preprocess.algorithms - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.preprocess.rst.txt b/docs/build/html/_sources/crikit.preprocess.rst.txt deleted file mode 100644 index 805e9fe..0000000 --- a/docs/build/html/_sources/crikit.preprocess.rst.txt +++ /dev/null @@ -1,69 +0,0 @@ -crikit\.preprocess package -========================== - -Subpackages ------------ - -.. toctree:: - - crikit.preprocess.algorithms - -Submodules ----------- - -crikit\.preprocess\.crop module -------------------------------- - -.. automodule:: crikit.preprocess.crop - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.denoise module ----------------------------------- - -.. automodule:: crikit.preprocess.denoise - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.standardize module --------------------------------------- - -.. automodule:: crikit.preprocess.standardize - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.subtract\_baseline module ---------------------------------------------- - -.. automodule:: crikit.preprocess.subtract_baseline - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.subtract\_dark module ------------------------------------------ - -.. automodule:: crikit.preprocess.subtract_dark - :members: - :undoc-members: - :show-inheritance: - -crikit\.preprocess\.subtract\_mean module ------------------------------------------ - -.. automodule:: crikit.preprocess.subtract_mean - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.preprocess - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.rst.txt b/docs/build/html/_sources/crikit.rst.txt deleted file mode 100644 index d401f59..0000000 --- a/docs/build/html/_sources/crikit.rst.txt +++ /dev/null @@ -1,37 +0,0 @@ -crikit package -============== - -Subpackages ------------ - -.. toctree:: - - crikit.cri - crikit.data - crikit.datasets - crikit.io - crikit.measurement - crikit.preprocess - crikit.transform - crikit.ui - crikit.utils - -Submodules ----------- - -crikit\.CRIkitUI module ------------------------ - -.. automodule:: crikit.CRIkitUI - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.transform.rst.txt b/docs/build/html/_sources/crikit.transform.rst.txt deleted file mode 100644 index 0b8b464..0000000 --- a/docs/build/html/_sources/crikit.transform.rst.txt +++ /dev/null @@ -1,10 +0,0 @@ -crikit\.transform package -========================= - -Module contents ---------------- - -.. automodule:: crikit.transform - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.ui.rst.txt b/docs/build/html/_sources/crikit.ui.rst.txt deleted file mode 100644 index b06fcb9..0000000 --- a/docs/build/html/_sources/crikit.ui.rst.txt +++ /dev/null @@ -1,205 +0,0 @@ -crikit\.ui package -================== - -Subpackages ------------ - -.. toctree:: - - crikit.ui.utils - -Submodules ----------- - -crikit\.ui\.classes\_ui module ------------------------------- - -.. automodule:: crikit.ui.classes_ui - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_AbstractFactorization module ------------------------------------------------- - -.. automodule:: crikit.ui.dialog_AbstractFactorization - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_AbstractPlotEffect module ---------------------------------------------- - -.. automodule:: crikit.ui.dialog_AbstractPlotEffect - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_SVD module ------------------------------- - -.. automodule:: crikit.ui.dialog_SVD - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_kkOptions module ------------------------------------- - -.. automodule:: crikit.ui.dialog_kkOptions - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_model module --------------------------------- - -.. automodule:: crikit.ui.dialog_model - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_ploteffect module -------------------------------------- - -.. automodule:: crikit.ui.dialog_ploteffect - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_save module -------------------------------- - -.. automodule:: crikit.ui.dialog_save - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_subResidualOptions module ---------------------------------------------- - -.. automodule:: crikit.ui.dialog_subResidualOptions - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.dialog\_varstabAnscombeOptions module -------------------------------------------------- - -.. automodule:: crikit.ui.dialog_varstabAnscombeOptions - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.helper\_plotOptions module --------------------------------------- - -.. automodule:: crikit.ui.helper_plotOptions - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.helper\_roiselect module ------------------------------------- - -.. automodule:: crikit.ui.helper_roiselect - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.subui\_hdf\_load module ------------------------------------ - -.. automodule:: crikit.ui.subui_hdf_load - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_ALS module ------------------------------- - -.. automodule:: crikit.ui.widget_ALS - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_ArPLS module --------------------------------- - -.. automodule:: crikit.ui.widget_ArPLS - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_Calibrate module ------------------------------------- - -.. automodule:: crikit.ui.widget_Calibrate - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_DeTrending module -------------------------------------- - -.. automodule:: crikit.ui.widget_DeTrending - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_Jupyter module ----------------------------------- - -.. automodule:: crikit.ui.widget_Jupyter - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_KK module ------------------------------ - -.. automodule:: crikit.ui.widget_KK - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_SG module ------------------------------ - -.. automodule:: crikit.ui.widget_SG - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_images module ---------------------------------- - -.. automodule:: crikit.ui.widget_images - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_mergeNRBs module ------------------------------------- - -.. automodule:: crikit.ui.widget_mergeNRBs - :members: - :undoc-members: - :show-inheritance: - -crikit\.ui\.widget\_scientificspin module ------------------------------------------ - -.. automodule:: crikit.ui.widget_scientificspin - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.ui - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.ui.utils.rst.txt b/docs/build/html/_sources/crikit.ui.utils.rst.txt deleted file mode 100644 index 1ee92bf..0000000 --- a/docs/build/html/_sources/crikit.ui.utils.rst.txt +++ /dev/null @@ -1,22 +0,0 @@ -crikit\.ui\.utils package -========================= - -Submodules ----------- - -crikit\.ui\.utils\.roi module ------------------------------ - -.. automodule:: crikit.ui.utils.roi - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.ui.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/crikit.utils.rst.txt b/docs/build/html/_sources/crikit.utils.rst.txt deleted file mode 100644 index a87fc54..0000000 --- a/docs/build/html/_sources/crikit.utils.rst.txt +++ /dev/null @@ -1,62 +0,0 @@ -crikit\.utils package -===================== - -Submodules ----------- - -crikit\.utils\.breadcrumb module --------------------------------- - -.. automodule:: crikit.utils.breadcrumb - :members: - :undoc-members: - :show-inheritance: - -crikit\.utils\.datacheck module -------------------------------- - -.. automodule:: crikit.utils.datacheck - :members: - :undoc-members: - :show-inheritance: - -crikit\.utils\.general module ------------------------------ - -.. automodule:: crikit.utils.general - :members: - :undoc-members: - :show-inheritance: - -crikit\.utils\.h5 module ------------------------- - -.. automodule:: crikit.utils.h5 - :members: - :undoc-members: - :show-inheritance: - -crikit\.utils\.mplstyle module ------------------------------- - -.. automodule:: crikit.utils.mplstyle - :members: - :undoc-members: - :show-inheritance: - -crikit\.utils\.roi module -------------------------- - -.. automodule:: crikit.utils.roi - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: crikit.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt deleted file mode 100644 index 5ebb9c2..0000000 --- a/docs/build/html/_sources/index.rst.txt +++ /dev/null @@ -1,56 +0,0 @@ -.. CRIKit2 documentation master file, created by - sphinx-quickstart on Wed Jul 20 22:31:57 2016. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -.. image:: _static/CRIkit2_Logo.png - :align: left - - -| -| -| -| -| -| -| - -Welcome to CRIKit2's documentation! -=================================== - -CRIkit2 is a numerical and graphical package for processing hyperspectral -imagery (HSI). Originally developed for coherent Raman imaginery (CRI), -CRIkit2 is appropriate for all HSI. - -The main components of CRIkit2: - -- **CRIkitUI_process** : the [graphical] user interface (UI) for (pre-)processing - HSI. -- **CRIkitUI_analyze** : *Coming soon*. A UI for analysis and visualization. Out-of-core - computation enabled. Does not alter the original data. -- Numerical packages that can be used from the command line. - -Contents: - -.. toctree:: - :maxdepth: 2 - :caption: User Documentation - - installing - running - cri_walkthru - algorithms - io - nonlicense - -.. toctree:: - :maxdepth: 2 - :caption: Developer Documentation - - api - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` diff --git a/docs/build/html/_sources/installing.rst.txt b/docs/build/html/_sources/installing.rst.txt deleted file mode 100644 index 24719e2..0000000 --- a/docs/build/html/_sources/installing.rst.txt +++ /dev/null @@ -1,104 +0,0 @@ -.. _installing: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -Installation -============ - -Dependencies ---------------------- -Note: the versions are those that have been tested, but older/newer -versions may also work. - -- Python 3.4, 3.5, 3.6 (3.4.4, 3.5.2, 3.6.1) -- `SciPlot-PyQt `__ >= 0.1.3 (>=0.1.4 for MPL2) -- numpy (1.9.3, 1.11.1, 1.11.3+mkl) -- PyQt5 (5.5, 5.6, 5.8.1) -- matplotlib (1.5, 2.0 -- see below for MPL2) -- cvxopt (1.1.7, 1.1.9) -- h5py (2.5, 2.6, 2.7) -- Sphinx (1.4.5, 1.5.2, 1.6.4) -- only for documentation building - -Notes and Known Issues ----------------------- - -Matplotlib 2 -~~~~~~~~~~~~ -You will need to use SciPlot-PyQT v0.1.4 (or higher) -- Matplotlib 2 made numerous changes and deprecations that are being resolved -- See the installation instruction in the `SciPlot-pyQt README.md `__ - -Python 3.4 -~~~~~~~~~~~ -You will need to manually install PyQt5 and Qt5 or get it through a distribution -* PyQt5: https://www.riverbankcomputing.com/software/pyqt/download5 -* Qt: https://www.qt.io/ - -PyQt 5.7 and WinPython 3.5 -~~~~~~~~~~~~~~~~~~~~~~~~~~ -There is a bug in PyQt 5.7.* that will prevent SciPlot's tables from showing the individual plot entries -(see https://www.riverbankcomputing.com/pipermail/pyqt/2017-January/038483.html). Apparently, this will be fixed in 5.7.2. - -- As WinPython 3.5.2.3Qt5 and 3.5.2.2Qt5 use PyQt 5.7.*, it is advised to use WinPython 3.5.2.1Qt5 or 3.4.4.5Qt5 until the matter is sorted out. -- Alternatively, one can uninstall pyqt5.7.* and force an install of <= 5.6.*. - -SciPlot-PyQt -~~~~~~~~~~~~ -Currently, SciPlot >= 0.1.3 is not available through pip. You can however clone the repository from github. -(see https://github.com/CCampJr/SciPlot-PyQt) - -Instructions ------------- - -Git Dynamic copy -~~~~~~~~~~~~~~~~~~~ -:: - - # Make new directory for crikit2 (DIR) - # Clone from github - git clone https://github.com/CoherentRamanNIST/crikit2.git ./DIR - - # Within install directory (DIR) - pip3 install -e . - - # To update installation, from within crikit2 directory - git pull - -Git Static copy -~~~~~~~~~~~~~~~~~~~ -:: - - # Make new directory for crikit2 (DIR) - # Clone from github - git clone https://github.com/CoherentRamanNIST/crikit2.git ./DIR - - # Within install directory (DIR) - pip3 install . - - # You can now delete the source files you downloaded - -(Re)-Building documentation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The documentation was built using Sphinx. A pre-built version of the html -files is included with this module, but you may wish to rebuild on your own -system.:: - - # Build all APIs - # From within the docs/ directory - sphinx-apidoc -o ./source/ ../crikit/ - - # Build API w/o pyuic5-generated files - sphinx-apidoc -f -o .\source\ ..\crikit\ ..\crikit\ui\qt_* ..\crikit\ui\*_rc* ..\crikit\ui\old\** - - make html - # On Windows - make.bat html diff --git a/docs/build/html/_sources/io.rst.txt b/docs/build/html/_sources/io.rst.txt deleted file mode 100644 index f1d2a24..0000000 --- a/docs/build/html/_sources/io.rst.txt +++ /dev/null @@ -1,17 +0,0 @@ -.. _io: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -Input/Output (IO) File Types and Specs -====================================== - -Coming Soon \ No newline at end of file diff --git a/docs/build/html/_sources/modules.rst.txt b/docs/build/html/_sources/modules.rst.txt deleted file mode 100644 index fcf390b..0000000 --- a/docs/build/html/_sources/modules.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -crikit -====== - -.. toctree:: - :maxdepth: 4 - - crikit diff --git a/docs/build/html/_sources/nonlicense.rst.txt b/docs/build/html/_sources/nonlicense.rst.txt deleted file mode 100644 index be3bde8..0000000 --- a/docs/build/html/_sources/nonlicense.rst.txt +++ /dev/null @@ -1,28 +0,0 @@ -.. _nonlicense: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -Nonlicense -=========== -This software was developed at the National Institute of Standards and Technology (NIST) by -employees of the Federal Government in the course of their official duties. Pursuant to -`Title 17 Section 105 of the United States Code `_, -this software is not subject to copyright protection and is in the public domain. -NIST assumes no responsibility whatsoever for use by other parties of its source code, -and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. - -Specific software products identified in this open source project were used in order -to perform technology transfer and collaboration. In no case does such identification imply -recommendation or endorsement by the National Institute of Standards and Technology, nor -does it imply that the products identified are necessarily the best available for the -purpose. - diff --git a/docs/build/html/_sources/running.rst.txt b/docs/build/html/_sources/running.rst.txt deleted file mode 100644 index 25d7d3a..0000000 --- a/docs/build/html/_sources/running.rst.txt +++ /dev/null @@ -1,52 +0,0 @@ -.. _running: - -.. image:: _static/CRIkit2_Logo.png - :align: left - -| -| -| -| -| -| -| - -Running the CRIkit2 Graphical User Interface -============================================ - -As a module ------------ -:: - - python3 -m crikit - - # OR - - python -m crikit - -From within a Python/IPython/Jupyter shell ------------------------------------------- - -.. code:: python - - from crikit.CRIkitUI import crikit_launch - crikit_launch() - - -A longer example: - -.. code:: python - - import numpy as np - - from crikit.CRIkitUI import crikit_launch - - # Random hsi image - data = np.random.randn(10,21,100) - f = np.linspace(500,1000,100) - x = 1e3*np.arange(21) - y = 1e3*np.arange(10) - - crikit_launch(data=data, x=x, y=y, x_units='Feet', y_units='M', - x_label='Test', y_label='Test2', f_units=r'$\mu$m', - f_label='Frequency') \ No newline at end of file diff --git a/docs/build/html/_static/CRIkit2_Logo.png b/docs/build/html/_static/CRIkit2_Logo.png deleted file mode 100644 index b3cde5e..0000000 Binary files a/docs/build/html/_static/CRIkit2_Logo.png and /dev/null differ diff --git a/docs/build/html/_static/ajax-loader.gif b/docs/build/html/_static/ajax-loader.gif deleted file mode 100644 index 61faf8c..0000000 Binary files a/docs/build/html/_static/ajax-loader.gif and /dev/null differ diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css deleted file mode 100644 index 6df76b0..0000000 --- a/docs/build/html/_static/basic.css +++ /dev/null @@ -1,639 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox input[type="text"] { - width: 170px; -} - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li div.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border: 0; - border-collapse: collapse; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -dl { - margin-bottom: 15px; -} - -dd p { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dt:target, .highlighted { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - margin-left: 0.5em; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} - -div.code-block-caption { - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -div.code-block-caption + div > div.highlight > pre { - margin-top: 0; -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - padding: 1em 1em 0; -} - -div.literal-block-wrapper div.highlight { - margin: 0; -} - -code.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -code.descclassname { - background-color: transparent; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: relative; - left: 0px; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/docs/build/html/_static/comment-bright.png b/docs/build/html/_static/comment-bright.png deleted file mode 100644 index 15e27ed..0000000 Binary files a/docs/build/html/_static/comment-bright.png and /dev/null differ diff --git a/docs/build/html/_static/comment-close.png b/docs/build/html/_static/comment-close.png deleted file mode 100644 index 4d91bcf..0000000 Binary files a/docs/build/html/_static/comment-close.png and /dev/null differ diff --git a/docs/build/html/_static/comment.png b/docs/build/html/_static/comment.png deleted file mode 100644 index dfbc0cb..0000000 Binary files a/docs/build/html/_static/comment.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/ALS.png b/docs/build/html/_static/cri_wt/ALS.png deleted file mode 100644 index 4e4a5d1..0000000 Binary files a/docs/build/html/_static/cri_wt/ALS.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Anscombe.png b/docs/build/html/_static/cri_wt/Anscombe.png deleted file mode 100644 index 34c2407..0000000 Binary files a/docs/build/html/_static/cri_wt/Anscombe.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Calibration.png b/docs/build/html/_static/cri_wt/Calibration.png deleted file mode 100644 index cb4fc4d..0000000 Binary files a/docs/build/html/_static/cri_wt/Calibration.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/CompositeColorExample.png b/docs/build/html/_static/cri_wt/CompositeColorExample.png deleted file mode 100644 index 9bb1a93..0000000 Binary files a/docs/build/html/_static/cri_wt/CompositeColorExample.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Elastin.png b/docs/build/html/_static/cri_wt/Elastin.png deleted file mode 100644 index 5a0cd3f..0000000 Binary files a/docs/build/html/_static/cri_wt/Elastin.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/KKInteractive.png b/docs/build/html/_static/cri_wt/KKInteractive.png deleted file mode 100644 index 081ca0e..0000000 Binary files a/docs/build/html/_static/cri_wt/KKInteractive.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/KKOptions.png b/docs/build/html/_static/cri_wt/KKOptions.png deleted file mode 100644 index 9eec813..0000000 Binary files a/docs/build/html/_static/cri_wt/KKOptions.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/LoadModel.png b/docs/build/html/_static/cri_wt/LoadModel.png deleted file mode 100644 index 5f2d790..0000000 Binary files a/docs/build/html/_static/cri_wt/LoadModel.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Nuclei.png b/docs/build/html/_static/cri_wt/Nuclei.png deleted file mode 100644 index 0c6be9d..0000000 Binary files a/docs/build/html/_static/cri_wt/Nuclei.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/Anscombe_action.jpg b/docs/build/html/_static/cri_wt/Old/Anscombe_action.jpg deleted file mode 100644 index bf9d1fc..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/Anscombe_action.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/InverseAnscombe_action.png b/docs/build/html/_static/cri_wt/Old/InverseAnscombe_action.png deleted file mode 100644 index ba41306..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/InverseAnscombe_action.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/denoise_action.jpg b/docs/build/html/_static/cri_wt/Old/denoise_action.jpg deleted file mode 100644 index 959de6e..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/denoise_action.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/denoise_dark.jpg b/docs/build/html/_static/cri_wt/Old/denoise_dark.jpg deleted file mode 100644 index d58559a..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/denoise_dark.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/load1.jpg b/docs/build/html/_static/cri_wt/Old/load1.jpg deleted file mode 100644 index b85b0ae..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/load1.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/load2.png b/docs/build/html/_static/cri_wt/Old/load2.png deleted file mode 100644 index cd4131a..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/load2.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/load3.png b/docs/build/html/_static/cri_wt/Old/load3.png deleted file mode 100644 index a22ebce..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/load3.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/load_dark.png b/docs/build/html/_static/cri_wt/Old/load_dark.png deleted file mode 100644 index f21d222..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/load_dark.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/load_nrb.png b/docs/build/html/_static/cri_wt/Old/load_nrb.png deleted file mode 100644 index 84af646..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/load_nrb.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/load_nrb_roi.jpg b/docs/build/html/_static/cri_wt/Old/load_nrb_roi.jpg deleted file mode 100644 index 59312e8..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/load_nrb_roi.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/overview.jpg b/docs/build/html/_static/cri_wt/Old/overview.jpg deleted file mode 100644 index 99d94bd..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/overview.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/subtract_dark.png b/docs/build/html/_static/cri_wt/Old/subtract_dark.png deleted file mode 100644 index 0dce107..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/subtract_dark.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Old/svd_widget.jpg b/docs/build/html/_static/cri_wt/Old/svd_widget.jpg deleted file mode 100644 index f165e26..0000000 Binary files a/docs/build/html/_static/cri_wt/Old/svd_widget.jpg and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Open.png b/docs/build/html/_static/cri_wt/Open.png deleted file mode 100644 index 0e07a76..0000000 Binary files a/docs/build/html/_static/cri_wt/Open.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/OpenDark.png b/docs/build/html/_static/cri_wt/OpenDark.png deleted file mode 100644 index a71710f..0000000 Binary files a/docs/build/html/_static/cri_wt/OpenDark.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/OpenNRB.png b/docs/build/html/_static/cri_wt/OpenNRB.png deleted file mode 100644 index a61157a..0000000 Binary files a/docs/build/html/_static/cri_wt/OpenNRB.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Overview.png b/docs/build/html/_static/cri_wt/Overview.png deleted file mode 100644 index 2c3fdee..0000000 Binary files a/docs/build/html/_static/cri_wt/Overview.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Overview_post_gen_BCARS.png b/docs/build/html/_static/cri_wt/Overview_post_gen_BCARS.png deleted file mode 100644 index c50d18a..0000000 Binary files a/docs/build/html/_static/cri_wt/Overview_post_gen_BCARS.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Phenylalanine.png b/docs/build/html/_static/cri_wt/Phenylalanine.png deleted file mode 100644 index 79275f2..0000000 Binary files a/docs/build/html/_static/cri_wt/Phenylalanine.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/RoiRawSpectra.png b/docs/build/html/_static/cri_wt/RoiRawSpectra.png deleted file mode 100644 index 4257c7d..0000000 Binary files a/docs/build/html/_static/cri_wt/RoiRawSpectra.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/SG.png b/docs/build/html/_static/cri_wt/SG.png deleted file mode 100644 index 3dd2bdc..0000000 Binary files a/docs/build/html/_static/cri_wt/SG.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/SVD_Ui.png b/docs/build/html/_static/cri_wt/SVD_Ui.png deleted file mode 100644 index 2902f79..0000000 Binary files a/docs/build/html/_static/cri_wt/SVD_Ui.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/SVG/ALS_dialog.svg b/docs/build/html/_static/cri_wt/SVG/ALS_dialog.svg deleted file mode 100644 index 1029a41..0000000 --- a/docs/build/html/_static/cri_wt/SVG/ALS_dialog.svg +++ /dev/null @@ -1,2022 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - Input spectra - Preview ofcorrectedspectra - - diff --git a/docs/build/html/_static/cri_wt/SVG/Anscombe_dialog.svg b/docs/build/html/_static/cri_wt/SVG/Anscombe_dialog.svg deleted file mode 100644 index 1f9bce1..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Anscombe_dialog.svg +++ /dev/null @@ -1,461 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/Calibration_dialog.svg b/docs/build/html/_static/cri_wt/SVG/Calibration_dialog.svg deleted file mode 100644 index 7ead245..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Calibration_dialog.svg +++ /dev/null @@ -1,2476 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - Zoom - Measured PeakWavenumber - - Ideal (Calibrated)Peak Wavenumber - - diff --git a/docs/build/html/_static/cri_wt/SVG/CompositeColorExample.svg b/docs/build/html/_static/cri_wt/SVG/CompositeColorExample.svg deleted file mode 100644 index 67317d3..0000000 --- a/docs/build/html/_static/cri_wt/SVG/CompositeColorExample.svg +++ /dev/null @@ -1,9605 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - Composite Image Tabs - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/KKInteractive_dialog.svg b/docs/build/html/_static/cri_wt/SVG/KKInteractive_dialog.svg deleted file mode 100644 index 15ed08a..0000000 --- a/docs/build/html/_static/cri_wt/SVG/KKInteractive_dialog.svg +++ /dev/null @@ -1,1844 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - Input spectra - Preview of KK - - diff --git a/docs/build/html/_static/cri_wt/SVG/KKOptions_dialog.svg b/docs/build/html/_static/cri_wt/SVG/KKOptions_dialog.svg deleted file mode 100644 index 7071abd..0000000 --- a/docs/build/html/_static/cri_wt/SVG/KKOptions_dialog.svg +++ /dev/null @@ -1,608 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/LoadModel.svg b/docs/build/html/_static/cri_wt/SVG/LoadModel.svg deleted file mode 100644 index f609232..0000000 --- a/docs/build/html/_static/cri_wt/SVG/LoadModel.svg +++ /dev/null @@ -1,972 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/Open_DarkFilter_dialog.svg b/docs/build/html/_static/cri_wt/SVG/Open_DarkFilter_dialog.svg deleted file mode 100644 index b4d6ad6..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Open_DarkFilter_dialog.svg +++ /dev/null @@ -1,1246 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - Data Groups - - Datasets in group - - Filter by text - - diff --git a/docs/build/html/_static/cri_wt/SVG/Open_NRBFilter_dialog.svg b/docs/build/html/_static/cri_wt/SVG/Open_NRBFilter_dialog.svg deleted file mode 100644 index 38cf843..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Open_NRBFilter_dialog.svg +++ /dev/null @@ -1,1274 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - Data Groups - - Datasets in group - - Filter by text - - diff --git a/docs/build/html/_static/cri_wt/SVG/Open_dialog.svg b/docs/build/html/_static/cri_wt/SVG/Open_dialog.svg deleted file mode 100644 index 926ab63..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Open_dialog.svg +++ /dev/null @@ -1,1366 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - Data Groups - - Datasets in group - - diff --git a/docs/build/html/_static/cri_wt/SVG/Overview.svg b/docs/build/html/_static/cri_wt/SVG/Overview.svg deleted file mode 100644 index acf0821..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Overview.svg +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - Main Ribbon - - FrequencySelector - - Single-Frequency (SF) Image - - diff --git a/docs/build/html/_static/cri_wt/SVG/Overview_PostGenerateBCARS.svg b/docs/build/html/_static/cri_wt/SVG/Overview_PostGenerateBCARS.svg deleted file mode 100644 index 6b9a54d..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Overview_PostGenerateBCARS.svg +++ /dev/null @@ -1,6202 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/RoiRawSpectra.svg b/docs/build/html/_static/cri_wt/SVG/RoiRawSpectra.svg deleted file mode 100644 index bfa2214..0000000 --- a/docs/build/html/_static/cri_wt/SVG/RoiRawSpectra.svg +++ /dev/null @@ -1,8631 +0,0 @@ - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/SG_dialog.svg b/docs/build/html/_static/cri_wt/SVG/SG_dialog.svg deleted file mode 100644 index 8b47a89..0000000 --- a/docs/build/html/_static/cri_wt/SVG/SG_dialog.svg +++ /dev/null @@ -1,2024 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - Input spectra - Preview ofcorrectedspectra - - diff --git a/docs/build/html/_static/cri_wt/SVG/SVD_UI.svg b/docs/build/html/_static/cri_wt/SVG/SVD_UI.svg deleted file mode 100644 index 4289fab..0000000 --- a/docs/build/html/_static/cri_wt/SVG/SVD_UI.svg +++ /dev/null @@ -1,7069 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - Spectral - Spatial - Check tokeep - - Apply current selections - - Finished. Use selections. - - See next 6 - - diff --git a/docs/build/html/_static/cri_wt/SVG/Save_dialog.svg b/docs/build/html/_static/cri_wt/SVG/Save_dialog.svg deleted file mode 100644 index affc6fc..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Save_dialog.svg +++ /dev/null @@ -1,715 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/SVG/SingleColorDNAExample.svg b/docs/build/html/_static/cri_wt/SVG/SingleColorDNAExample.svg deleted file mode 100644 index ef92162..0000000 --- a/docs/build/html/_static/cri_wt/SVG/SingleColorDNAExample.svg +++ /dev/null @@ -1,424 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - FrequencySelector - Peak AssignmentButtons - - Math FunctionSelector - - - - - PerformMath - - Set MinimumValue - - Set ChannelColor - - Set Conditions - - Color ChannelTabs - Comparitor - - Value - - - diff --git a/docs/build/html/_static/cri_wt/SVG/Sub_dark_dialogs.svg b/docs/build/html/_static/cri_wt/SVG/Sub_dark_dialogs.svg deleted file mode 100644 index 04e39d1..0000000 --- a/docs/build/html/_static/cri_wt/SVG/Sub_dark_dialogs.svg +++ /dev/null @@ -1,821 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/docs/build/html/_static/cri_wt/Save.png b/docs/build/html/_static/cri_wt/Save.png deleted file mode 100644 index ddaa265..0000000 Binary files a/docs/build/html/_static/cri_wt/Save.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/SingleColorExample.png b/docs/build/html/_static/cri_wt/SingleColorExample.png deleted file mode 100644 index c26904a..0000000 Binary files a/docs/build/html/_static/cri_wt/SingleColorExample.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Spectrum_Before_After_SVD.png b/docs/build/html/_static/cri_wt/Spectrum_Before_After_SVD.png deleted file mode 100644 index f260446..0000000 Binary files a/docs/build/html/_static/cri_wt/Spectrum_Before_After_SVD.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/StructuralProtein.png b/docs/build/html/_static/cri_wt/StructuralProtein.png deleted file mode 100644 index 7c2629c..0000000 Binary files a/docs/build/html/_static/cri_wt/StructuralProtein.png and /dev/null differ diff --git a/docs/build/html/_static/cri_wt/Sub_dark_dialogs.png b/docs/build/html/_static/cri_wt/Sub_dark_dialogs.png deleted file mode 100644 index a920fac..0000000 Binary files a/docs/build/html/_static/cri_wt/Sub_dark_dialogs.png and /dev/null differ diff --git a/docs/build/html/_static/css/badge_only.css b/docs/build/html/_static/css/badge_only.css deleted file mode 100644 index 6362912..0000000 --- a/docs/build/html/_static/css/badge_only.css +++ /dev/null @@ -1,2 +0,0 @@ -.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} -/*# sourceMappingURL=badge_only.css.map */ diff --git a/docs/build/html/_static/css/theme.css b/docs/build/html/_static/css/theme.css deleted file mode 100644 index c1631d8..0000000 --- a/docs/build/html/_static/css/theme.css +++ /dev/null @@ -1,5 +0,0 @@ -*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,.rst-content .toctree-wrapper p.caption,h3{orphans:3;widows:3}h2,.rst-content .toctree-wrapper p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! - * Font Awesome 4.6.3 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.6.3");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff2?v=4.6.3") format("woff2"),url("../fonts/fontawesome-webfont.woff?v=4.6.3") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.6.3") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.wy-menu-vertical li span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.rst-content .fa-pull-left.admonition-title,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content dl dt .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.rst-content code.download span.fa-pull-left:first-child,.fa-pull-left.icon{margin-right:.3em}.fa.fa-pull-right,.wy-menu-vertical li span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.rst-content .fa-pull-right.admonition-title,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content dl dt .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.rst-content code.download span.fa-pull-right:first-child,.fa-pull-right.icon{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:""}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-signing:before,.fa-sign-language:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:0.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all 0.3s ease-in;-moz-transition:all 0.3s ease-in;transition:all 0.3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 .3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:.34375em .625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{width:36px;height:12px;margin:12px 0;position:relative;border-radius:4px;background:#ccc;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:before{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:after{content:"false";position:absolute;left:48px;display:block;font-size:12px;color:#ccc}.wy-switch.active{background:#1e8449}.wy-switch.active:before{left:24px;background:#27AE60}.wy-switch.active:after{content:"true"}.wy-switch.disabled,.wy-switch.active.disabled{cursor:not-allowed}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content .toctree-wrapper p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content .toctree-wrapper p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9B59B6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],pre.literal-block div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}@media print{.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#EAF2F5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs li code,.wy-breadcrumbs li .rst-content tt,.rst-content .wy-breadcrumbs li tt{padding:5px;border:none;background:none}.wy-breadcrumbs li code.literal,.wy-breadcrumbs li .rst-content tt.literal,.rst-content .wy-breadcrumbs li tt.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin-bottom:0;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#555;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:0.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:0.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:0.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:.4045em 5.663em;border-top:none;border-bottom:none}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:0.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#b3b3b3}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980B9;text-align:center;padding:.809em;display:block;color:#fcfcfc;margin-bottom:.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:0.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:normal;color:rgba(255,255,255,0.3)}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}footer span.commit code,footer span.commit .rst-content tt,.rst-content footer span.commit tt{padding:0px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:1em;background:none;border:none;color:#999}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:before,.rst-breadcrumbs-buttons:after{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-side-scroll{width:auto}.wy-side-nav-search{width:auto}.wy-menu.wy-menu-vertical{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content img{max-width:100%;height:auto !important}.rst-content .highlight>pre{line-height:normal}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after{visibility:visible;content:"";font-family:FontAwesome;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content .toctree-wrapper p.caption:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink,.rst-content p.caption:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.docutils.citation tt,.rst-content table.docutils.citation code,.rst-content table.docutils.footnote tt,.rst-content table.docutils.footnote code{color:#555}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list td>strong{display:inline-block;margin-top:3px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt,.rst-content tt,.rst-content code{color:#000;padding:2px 5px}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal{color:#E74C3C}.rst-content tt.xref,a .rst-content tt,.rst-content tt.xref,.rst-content code.xref,a .rst-content tt,a .rst-content code{font-weight:bold;color:#404040}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:#555}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-weight:normal;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child,.rst-content code.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),local("Inconsolata-Regular"),url(../fonts/Inconsolata-Regular.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(../fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(../fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(../fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(../fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(../fonts/RobotoSlab-Bold.ttf) format("truetype")} -/*# sourceMappingURL=theme.css.map */ diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js deleted file mode 100644 index 5654977..0000000 --- a/docs/build/html/_static/doctools.js +++ /dev/null @@ -1,287 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for all documentation. - * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - */ -jQuery.urldecode = function(x) { - return decodeURIComponent(x).replace(/\+/g, ' '); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s == 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node) { - if (node.nodeType == 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { - var span = document.createElement("span"); - span.className = className; - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this); - }); - } - } - return this.each(function() { - highlight(this); - }); -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} - -/** - * Small JavaScript module for the documentation. - */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - - }, - - /** - * i18n support - */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, - LOCALE : 'unknown', - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated == 'undefined') - return string; - return (typeof translated == 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated == 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; - }, - - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); - }, - - /** - * workaround a firefox stupidity - * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash) - window.setTimeout(function() { - document.location.href += ''; - }, 10); - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - if (!body.length) { - body = $('body'); - } - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('#searchbox')); - } - }, - - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) == 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('#searchbox .highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - }, - - /** - * make the url absolute - */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, - - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this == '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); - }, - - initOnKeyListeners: function() { - $(document).keyup(function(event) { - var activeElementType = document.activeElement.tagName; - // don't navigate when in search box or textarea - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { - switch (event.keyCode) { - case 37: // left - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; - } - case 39: // right - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; - } - } - } - }); - } -}; - -// quick alias for translations -_ = Documentation.gettext; - -$(document).ready(function() { - Documentation.init(); -}); \ No newline at end of file diff --git a/docs/build/html/_static/down-pressed.png b/docs/build/html/_static/down-pressed.png deleted file mode 100644 index 5756c8c..0000000 Binary files a/docs/build/html/_static/down-pressed.png and /dev/null differ diff --git a/docs/build/html/_static/down.png b/docs/build/html/_static/down.png deleted file mode 100644 index 1b3bdad..0000000 Binary files a/docs/build/html/_static/down.png and /dev/null differ diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png deleted file mode 100644 index a858a41..0000000 Binary files a/docs/build/html/_static/file.png and /dev/null differ diff --git a/docs/build/html/_static/fonts/fontawesome-webfont.eot b/docs/build/html/_static/fonts/fontawesome-webfont.eot deleted file mode 100644 index c7b00d2..0000000 Binary files a/docs/build/html/_static/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/fontawesome-webfont.svg b/docs/build/html/_static/fonts/fontawesome-webfont.svg deleted file mode 100644 index 8b66187..0000000 --- a/docs/build/html/_static/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,685 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/_static/fonts/fontawesome-webfont.woff b/docs/build/html/_static/fonts/fontawesome-webfont.woff deleted file mode 100644 index 6e7483c..0000000 Binary files a/docs/build/html/_static/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/docs/build/html/_static/jquery-3.1.0.js b/docs/build/html/_static/jquery-3.1.0.js deleted file mode 100644 index f2fc274..0000000 --- a/docs/build/html/_static/jquery-3.1.0.js +++ /dev/null @@ -1,10074 +0,0 @@ -/*eslint-disable no-unused-vars*/ -/*! - * jQuery JavaScript Library v3.1.0 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2016-07-07T21:44Z - */ -( function( global, factory ) { - - "use strict"; - - if ( typeof module === "object" && typeof module.exports === "object" ) { - - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; - -var arr = []; - -var document = window.document; - -var getProto = Object.getPrototypeOf; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var fnToString = hasOwn.toString; - -var ObjectFunctionString = fnToString.call( Object ); - -var support = {}; - - - - function DOMEval( code, doc ) { - doc = doc || document; - - var script = doc.createElement( "script" ); - - script.text = code; - doc.head.appendChild( script ).parentNode.removeChild( script ); - } -/* global Symbol */ -// Defining this global in .eslintrc would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.1.0", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = jQuery.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isFunction: function( obj ) { - return jQuery.type( obj ) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - - // As of jQuery 3.0, isNumeric is limited to - // strings and numbers (primitives or objects) - // that can be coerced to finite numbers (gh-2662) - var type = jQuery.type( obj ); - return ( type === "number" || type === "string" ) && - - // parseFloat NaNs numeric-cast false positives ("") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - !isNaN( obj - parseFloat( obj ) ); - }, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); - }, - - // Convert dashed to camelCase; used by the css and data modules - // Support: IE <=9 - 11, Edge 12 - 13 - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.0 - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-01-04 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - disabledAncestor = addCombinator( - function( elem ) { - return elem.disabled === true; - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement("fieldset"); - - try { - return !!fn( el ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - // Known :disabled false positives: - // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) - // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Check form elements and option elements for explicit disabling - return "label" in elem && elem.disabled === disabled || - "form" in elem && elem.disabled === disabled || - - // Check non-disabled form elements for fieldset[disabled] ancestors - "form" in elem && elem.disabled === false && ( - // Support: IE6-11+ - // Ancestry is covered for us - elem.isDisabled === disabled || - - // Otherwise, assume any non-