regex for numeric value for data from text files; closes #127
This commit is contained in:
		| @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets | ||||
| class Ui_ascii_reader(object): | ||||
|     def setupUi(self, ascii_reader): | ||||
|         ascii_reader.setObjectName("ascii_reader") | ||||
|         ascii_reader.resize(627, 1245) | ||||
|         ascii_reader.resize(665, 904) | ||||
|         self.verticalLayout = QtWidgets.QVBoxLayout(ascii_reader) | ||||
|         self.verticalLayout.setObjectName("verticalLayout") | ||||
|         self.tabWidget = QtWidgets.QTabWidget(ascii_reader) | ||||
| @@ -156,39 +156,51 @@ class Ui_ascii_reader(object): | ||||
|         spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) | ||||
|         self.gridLayout_2.addItem(spacerItem1, 4, 1, 1, 1) | ||||
|         self.horizontalLayout_4.addLayout(self.gridLayout_2) | ||||
|         self.verticalLayout_4 = QtWidgets.QVBoxLayout() | ||||
|         self.verticalLayout_4.setObjectName("verticalLayout_4") | ||||
|         self.horizontalLayout_4.addLayout(self.verticalLayout_4) | ||||
|         self.verticalLayout_3.addWidget(self.groupBox) | ||||
|         self.dsdfsf = QtWidgets.QLabel(self.tabWidgetPage1) | ||||
|         self.dsdfsf.setObjectName("dsdfsf") | ||||
|         self.verticalLayout_3.addWidget(self.dsdfsf) | ||||
|         self.label_8 = QtWidgets.QLabel(self.tabWidgetPage1) | ||||
|         self.label_8.setObjectName("label_8") | ||||
|         self.verticalLayout_3.addWidget(self.label_8) | ||||
|         self.radioButton = QtWidgets.QRadioButton(self.tabWidgetPage1) | ||||
|         self.radioButton.setObjectName("radioButton") | ||||
|         self.gridLayout = QtWidgets.QGridLayout() | ||||
|         self.gridLayout.setObjectName("gridLayout") | ||||
|         self.re_match_index = QtWidgets.QSpinBox(self.tabWidgetPage1) | ||||
|         self.re_match_index.setMinimum(1) | ||||
|         self.re_match_index.setObjectName("re_match_index") | ||||
|         self.gridLayout.addWidget(self.re_match_index, 1, 3, 1, 1) | ||||
|         self.label_9 = QtWidgets.QLabel(self.tabWidgetPage1) | ||||
|         self.label_9.setObjectName("label_9") | ||||
|         self.gridLayout.addWidget(self.label_9, 1, 2, 1, 1) | ||||
|         self.regex_input = QtWidgets.QLineEdit(self.tabWidgetPage1) | ||||
|         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.regex_input.sizePolicy().hasHeightForWidth()) | ||||
|         self.regex_input.setSizePolicy(sizePolicy) | ||||
|         self.regex_input.setObjectName("regex_input") | ||||
|         self.gridLayout.addWidget(self.regex_input, 1, 1, 1, 1) | ||||
|         self.re_button = QtWidgets.QRadioButton(self.tabWidgetPage1) | ||||
|         self.re_button.setChecked(True) | ||||
|         self.re_button.setObjectName("re_button") | ||||
|         self.buttonGroup_2 = QtWidgets.QButtonGroup(ascii_reader) | ||||
|         self.buttonGroup_2.setObjectName("buttonGroup_2") | ||||
|         self.buttonGroup_2.addButton(self.radioButton) | ||||
|         self.verticalLayout_3.addWidget(self.radioButton) | ||||
|         self.lineEdit = QtWidgets.QLineEdit(self.tabWidgetPage1) | ||||
|         self.lineEdit.setObjectName("lineEdit") | ||||
|         self.verticalLayout_3.addWidget(self.lineEdit) | ||||
|         self.radioButton_2 = QtWidgets.QRadioButton(self.tabWidgetPage1) | ||||
|         self.radioButton_2.setObjectName("radioButton_2") | ||||
|         self.buttonGroup_2.addButton(self.radioButton_2) | ||||
|         self.verticalLayout_3.addWidget(self.radioButton_2) | ||||
|         self.lineEdit_2 = QtWidgets.QLineEdit(self.tabWidgetPage1) | ||||
|         self.lineEdit_2.setObjectName("lineEdit_2") | ||||
|         self.verticalLayout_3.addWidget(self.lineEdit_2) | ||||
|         self.radioButton_3 = QtWidgets.QRadioButton(self.tabWidgetPage1) | ||||
|         self.radioButton_3.setObjectName("radioButton_3") | ||||
|         self.buttonGroup_2.addButton(self.radioButton_3) | ||||
|         self.verticalLayout_3.addWidget(self.radioButton_3) | ||||
|         self.spinBox = QtWidgets.QSpinBox(self.tabWidgetPage1) | ||||
|         self.spinBox.setObjectName("spinBox") | ||||
|         self.verticalLayout_3.addWidget(self.spinBox) | ||||
|         self.buttonGroup_2.addButton(self.re_button) | ||||
|         self.gridLayout.addWidget(self.re_button, 1, 0, 1, 1) | ||||
|         self.custom_input = QtWidgets.QLineEdit(self.tabWidgetPage1) | ||||
|         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.custom_input.sizePolicy().hasHeightForWidth()) | ||||
|         self.custom_input.setSizePolicy(sizePolicy) | ||||
|         self.custom_input.setObjectName("custom_input") | ||||
|         self.gridLayout.addWidget(self.custom_input, 2, 1, 1, 1) | ||||
|         self.custom_button = QtWidgets.QRadioButton(self.tabWidgetPage1) | ||||
|         self.custom_button.setObjectName("custom_button") | ||||
|         self.buttonGroup_2.addButton(self.custom_button) | ||||
|         self.gridLayout.addWidget(self.custom_button, 2, 0, 1, 1) | ||||
|         self.label_8 = QtWidgets.QLabel(self.tabWidgetPage1) | ||||
|         self.label_8.setWordWrap(True) | ||||
|         self.label_8.setObjectName("label_8") | ||||
|         self.gridLayout.addWidget(self.label_8, 0, 0, 1, 4) | ||||
|         self.verticalLayout_3.addLayout(self.gridLayout) | ||||
|         self.groupBox_2 = QtWidgets.QGroupBox(self.tabWidgetPage1) | ||||
|         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
| @@ -330,10 +342,11 @@ class Ui_ascii_reader(object): | ||||
|         self.label_5.setText(_translate("ascii_reader", "<html><head/><body><p>Δy</p></body></html>")) | ||||
|         self.x_label.setText(_translate("ascii_reader", "x")) | ||||
|         self.dsdfsf.setText(_translate("ascii_reader", "Numerical value")) | ||||
|         self.label_9.setText(_translate("ascii_reader", "Match index")) | ||||
|         self.regex_input.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Token:<br/>[abc]: Matches any of a, b, or c<br/>[a-z]: Matches any digit in the range a-z<br/>\\d: Matches any digit in the range 0-9 (equal to [0-9}</p><p>Quantifiers:<br/>a*: 0 or more of a<br/>a*: 1 or more of a<br/>a?: 0 or 1 of a</p></body></html>")) | ||||
|         self.re_button.setText(_translate("ascii_reader", "Regex")) | ||||
|         self.custom_button.setText(_translate("ascii_reader", "Custom value")) | ||||
|         self.label_8.setText(_translate("ascii_reader", "Filename")) | ||||
|         self.radioButton.setText(_translate("ascii_reader", "Regex")) | ||||
|         self.radioButton_2.setText(_translate("ascii_reader", "Custom value")) | ||||
|         self.radioButton_3.setText(_translate("ascii_reader", "Position in filename")) | ||||
|         self.groupBox_2.setTitle(_translate("ascii_reader", "Preview")) | ||||
|         self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabWidgetPage1), _translate("ascii_reader", "Data")) | ||||
|         self.label_2.setText(_translate("ascii_reader", "Number of delays")) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from pathlib import Path | ||||
| import re | ||||
|  | ||||
| from nmreval.io.asciireader import AsciiReader | ||||
| from nmreval.utils import NUMBER_RE | ||||
| @@ -18,6 +18,9 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|         self.setupUi(self) | ||||
|  | ||||
|         self.reader = None | ||||
|         self._matches = [] | ||||
|         self.regex_input.setText(NUMBER_RE.pattern) | ||||
|         self.custom_input.setValidator(QtGui.QDoubleValidator()) | ||||
|  | ||||
|         self.comment_textfield = QtWidgets.QPlainTextEdit(self.header_widget) | ||||
|         self.comment_textfield.setReadOnly(True) | ||||
| @@ -46,6 +49,8 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|     def __call__(self, fname, *args, **kwargs): | ||||
|         self.reader = AsciiReader(fname) | ||||
|  | ||||
|         self.check_filename(self.regex_input.text()) | ||||
|  | ||||
|         if self.skip: | ||||
|             self.accept() | ||||
|             return | ||||
| @@ -62,8 +67,6 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|         self.skippy_checkbox.setCheckState(QtCore.Qt.Unchecked) | ||||
|         self.skippy_checkbox.blockSignals(False) | ||||
|  | ||||
|         self.check_filename(fname) | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def set_gui(self): | ||||
| @@ -145,7 +148,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|                 staggered_range = 0 | ||||
|         except ValueError: | ||||
|             _ = QtWidgets.QMessageBox.information(self, 'No delays', | ||||
|                                                     'Delays cannot be calculated: Not enough or wrong arguments.') | ||||
|                                                   'Delays cannot be calculated: Not enough or wrong arguments.') | ||||
|             return | ||||
|  | ||||
|         self.reader.calc_delays(start, stop, num_delays, log=self.log_checkBox.isChecked(), | ||||
| @@ -204,9 +207,14 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|             col_header = [col_header[i] for i in range(len(col_header)) if i in y] | ||||
|  | ||||
|         try: | ||||
|             ret_dic = self.reader.export(x=x, y=y, yerr=y_err, | ||||
|                                          mode=self.buttonGroup.checkedButton().text(), | ||||
|                                          col_names=col_header) | ||||
|             ret_dic = self.reader.export( | ||||
|                 x=x, | ||||
|                 y=y, | ||||
|                 yerr=y_err, | ||||
|                 mode=self.buttonGroup.checkedButton().text(), | ||||
|                 col_names=col_header, | ||||
|                 num_value=self.get_numerical_value(), | ||||
|             ) | ||||
|             self.data_read.emit(ret_dic) | ||||
|  | ||||
|         except ImportError as e: | ||||
| @@ -223,7 +231,45 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|     def skip_next_dial(self, _: int): | ||||
|         self.skip = self.skippy_checkbox.isChecked() | ||||
|  | ||||
|     def check_filename(self, filename: str | Path): | ||||
|         self.label_8.setText(str(filename.stem)) | ||||
|         for i in NUMBER_RE.finditer(str(filename.stem)): | ||||
|             print(i) | ||||
|     @QtCore.pyqtSlot(str, name='on_regex_input_textChanged') | ||||
|     def check_filename(self, pattern: str = NUMBER_RE.pattern): | ||||
|         if self.reader is None: | ||||
|             return | ||||
|  | ||||
|         try: | ||||
|             pattern = re.compile(pattern) | ||||
|             self.regex_input.setStyleSheet('color: rgb(0, 0, 0)') | ||||
|             self._matches = [m for m in pattern.finditer(str(self.reader.fname.stem))] | ||||
|         except re.error: | ||||
|             self._matches = [] | ||||
|  | ||||
|         if self._matches: | ||||
|             self.re_match_index.blockSignals(True) | ||||
|             self.re_match_index.setMaximum(len(self._matches)) | ||||
|             self.re_match_index.blockSignals(False) | ||||
|         else: | ||||
|             self.regex_input.setStyleSheet('color: rgb(255, 0, 0)') | ||||
|  | ||||
|         self.show_match(self.re_match_index.value()) | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, name='on_re_match_index_valueChanged') | ||||
|     def show_match(self, idx: int = 0): | ||||
|         fname = str(self.reader.fname.stem) | ||||
|  | ||||
|         if self._matches: | ||||
|             m = self._matches[idx-1] | ||||
|             self.label_8.setText(f'{fname[:m.start()]}<b>{fname[m.start():m.end()]}</b>{fname[m.end():]}') | ||||
|         else: | ||||
|             self.label_8.setText(fname) | ||||
|  | ||||
|     def get_numerical_value(self): | ||||
|         val = 0 | ||||
|         if self.re_button.isChecked() and self._matches: | ||||
|             m = self._matches[self.re_match_index.value()-1] | ||||
|             val = float(NUMBER_RE.search(m.group()).group().replace('p', '.')) | ||||
|         elif self.custom_button.isChecked(): | ||||
|             val = float(self.custom_input.text()) | ||||
|  | ||||
|         return val | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -11,8 +11,6 @@ from ..data.bds import BDS | ||||
| from ..data.dsc import DSC | ||||
| from ..utils.utils import staggered_range | ||||
|  | ||||
| NUMBERRE = re.compile(r'[0-9]\.*[0-9]*[Ee]*[+-]*[0-9]*') | ||||
|  | ||||
|  | ||||
| class AsciiReader: | ||||
|     # delimiters = ['\t', ' ', ','] | ||||
| @@ -87,8 +85,15 @@ class AsciiReader: | ||||
|         if stagg: | ||||
|             self.delays = staggered_range(self.delays, stepsize=stag_size) | ||||
|  | ||||
|     def export(self, x: int = None, y: list = None, yerr: list = None, | ||||
|                mode: str = 'points', col_names=None) -> list: | ||||
|     def export( | ||||
|             self: 'AsciiReader', | ||||
|             x: int = None, | ||||
|             y: list = None, | ||||
|             yerr: list = None, | ||||
|             mode: str = 'points', | ||||
|             col_names=None, | ||||
|             num_value: float = None, | ||||
|     ) -> list: | ||||
|  | ||||
|         mode = mode.lower() | ||||
|         if mode not in ['points', 'fid', 'spectrum', 'dsc', 'bds']: | ||||
| @@ -138,12 +143,18 @@ class AsciiReader: | ||||
|         if self.delays: | ||||
|             delay_names = self.delays | ||||
|         else: | ||||
|             delay_names = [filename] | ||||
|             delay_names = [num_value] | ||||
|  | ||||
|         imported_sets = [] | ||||
|  | ||||
|         for i, value in enumerate(delay_names): | ||||
|             kwargs = {'value': value, 'filename': self.fname, 'name': filename, 'group': filename, 'y_err': None} | ||||
|             kwargs = { | ||||
|                 'value': value, | ||||
|                 'filename': self.fname, | ||||
|                 'name': filename, | ||||
|                 'group': filename, | ||||
|                 'y_err': None | ||||
|             } | ||||
|  | ||||
|             num_y = len(y) | ||||
|             single_len = 1 | ||||
|   | ||||
| @@ -4,3 +4,4 @@ from .constants import * | ||||
|  | ||||
|  | ||||
| NUMBER_RE = re.compile(r'[-+]?\d*[+p.]?\d+([eE][-+]?\d+)?', re.MULTILINE) | ||||
| UNSIGNED_NUMBER_RE = re.compile(r'[-+]?\d*[+p.]?\d+([eE][-+]?\d+)?', re.MULTILINE) | ||||
|   | ||||
| @@ -6,8 +6,8 @@ | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>627</width> | ||||
|     <height>1245</height> | ||||
|     <width>665</width> | ||||
|     <height>904</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
| @@ -301,9 +301,6 @@ | ||||
|             </item> | ||||
|            </layout> | ||||
|           </item> | ||||
|           <item> | ||||
|            <layout class="QVBoxLayout" name="verticalLayout_4"/> | ||||
|           </item> | ||||
|          </layout> | ||||
|         </widget> | ||||
|        </item> | ||||
| @@ -315,50 +312,78 @@ | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QLabel" name="label_8"> | ||||
|          <property name="text"> | ||||
|           <string>Filename</string> | ||||
|          </property> | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QRadioButton" name="radioButton"> | ||||
|          <property name="text"> | ||||
|           <string>Regex</string> | ||||
|          </property> | ||||
|          <attribute name="buttonGroup"> | ||||
|           <string notr="true">buttonGroup_2</string> | ||||
|          </attribute> | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QLineEdit" name="lineEdit"/> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QRadioButton" name="radioButton_2"> | ||||
|          <property name="text"> | ||||
|           <string>Custom value</string> | ||||
|          </property> | ||||
|          <attribute name="buttonGroup"> | ||||
|           <string notr="true">buttonGroup_2</string> | ||||
|          </attribute> | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QLineEdit" name="lineEdit_2"/> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QRadioButton" name="radioButton_3"> | ||||
|          <property name="text"> | ||||
|           <string>Position in filename</string> | ||||
|          </property> | ||||
|          <attribute name="buttonGroup"> | ||||
|           <string notr="true">buttonGroup_2</string> | ||||
|          </attribute> | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QSpinBox" name="spinBox"/> | ||||
|         <layout class="QGridLayout" name="gridLayout"> | ||||
|          <item row="1" column="3"> | ||||
|           <widget class="QSpinBox" name="re_match_index"> | ||||
|            <property name="minimum"> | ||||
|             <number>1</number> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="1" column="2"> | ||||
|           <widget class="QLabel" name="label_9"> | ||||
|            <property name="text"> | ||||
|             <string>Match index</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="1" column="1"> | ||||
|           <widget class="QLineEdit" name="regex_input"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||||
|              <horstretch>0</horstretch> | ||||
|              <verstretch>0</verstretch> | ||||
|             </sizepolicy> | ||||
|            </property> | ||||
|            <property name="toolTip"> | ||||
|             <string><html><head/><body><p>Token:<br/>[abc]: Matches any of a, b, or c<br/>[a-z]: Matches any digit in the range a-z<br/>\d: Matches any digit in the range 0-9 (equal to [0-9}</p><p>Quantifiers:<br/>a*: 0 or more of a<br/>a*: 1 or more of a<br/>a?: 0 or 1 of a</p></body></html></string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="1" column="0"> | ||||
|           <widget class="QRadioButton" name="re_button"> | ||||
|            <property name="text"> | ||||
|             <string>Regex</string> | ||||
|            </property> | ||||
|            <property name="checked"> | ||||
|             <bool>true</bool> | ||||
|            </property> | ||||
|            <attribute name="buttonGroup"> | ||||
|             <string notr="true">buttonGroup_2</string> | ||||
|            </attribute> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="2" column="1"> | ||||
|           <widget class="QLineEdit" name="custom_input"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||||
|              <horstretch>0</horstretch> | ||||
|              <verstretch>0</verstretch> | ||||
|             </sizepolicy> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="2" column="0"> | ||||
|           <widget class="QRadioButton" name="custom_button"> | ||||
|            <property name="text"> | ||||
|             <string>Custom value</string> | ||||
|            </property> | ||||
|            <attribute name="buttonGroup"> | ||||
|             <string notr="true">buttonGroup_2</string> | ||||
|            </attribute> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="0" column="0" colspan="4"> | ||||
|           <widget class="QLabel" name="label_8"> | ||||
|            <property name="text"> | ||||
|             <string>Filename</string> | ||||
|            </property> | ||||
|            <property name="wordWrap"> | ||||
|             <bool>true</bool> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QGroupBox" name="groupBox_2"> | ||||
| @@ -614,8 +639,8 @@ | ||||
|    <slot>close()</slot> | ||||
|    <hints> | ||||
|     <hint type="sourcelabel"> | ||||
|      <x>366</x> | ||||
|      <y>485</y> | ||||
|      <x>375</x> | ||||
|      <y>894</y> | ||||
|     </hint> | ||||
|     <hint type="destinationlabel"> | ||||
|      <x>366</x> | ||||
| @@ -625,7 +650,7 @@ | ||||
|   </connection> | ||||
|  </connections> | ||||
|  <buttongroups> | ||||
|   <buttongroup name="buttonGroup"/> | ||||
|   <buttongroup name="buttonGroup_2"/> | ||||
|   <buttongroup name="buttonGroup"/> | ||||
|  </buttongroups> | ||||
| </ui> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user