def import_las(files_list, wells_dir): """ Looks if well with appropriate name (name from las file) is in maincotext then parses this las file into this well else if there is no appropriate well then creates new well and parse las file into this well :param wells_dir: target dir to import in :type files_list: list of files paths """ log.debug("i'm in import_las()") broken_files = str() for file_name in files_list: try: las = lasio.read(file_name) if las["DEPT"] is None: log.debug('las["DEPT"]={0}'.format(las["DEPT"])) raise ValueError('las file has no DEPT curve') # log.debug(las.well['WELL'].value) if all(str(las.well['WELL'].value) != well.name for well in main_context.wells_list): well = Well(str(las.well['WELL'].value)) well.las = las main_context.wells_list.append(well) wells_dir.add_well(well) else: well_dict = {well.name: well for well in main_context.wells_list} well = well_dict.get(str(las.well['WELL'].value)) assert well, well_dict well.las = las except Exception: broken_files += file_name + '\n' return broken_files
def read_head(self, lines): """ submethod for reading las file head information """ try: self.name = re.search(r'# WELL NAME:\s*(?P<well_name>\S+)', lines[1]).group('well_name') self.head_x = float( re.search( r'# WELL HEAD X-COORDINATE:\s*(?P<head_x>[-+]?\d+\.\d+)', lines[2]).group('head_x')) self.head_y = float( re.search( r'# WELL HEAD Y-COORDINATE:\s*(?P<head_y>[-+]?\d+\.\d+)', lines[3]).group('head_y')) self.offset = float( re.search( r'# WELL OFFSET \(from MSL\):\s*(?P<offset>[-+]?\d+\.\d+)', lines[4]).group('offset')) log.debug( 'name={0}\t head_x={1}\t head_y={2}\t offset={3}'. format(self.name, self.head_x, self.head_y, self.offset)) except AttributeError as ex: log.warning(str(ex)) return False return True
def import_dev(files_list, wells_dir): """ Looks if well with appropriate name (name from dev file) is in maincotext then parses this dev file into this well else if there is no appropriate well then creates new well and parse dev file into this well :param wells_dir: target dir to import to :param files_list: list of files paths """ log.debug("i'm in import_dev()") broken_files = str() for file_name in files_list: well = Well() if not well.read_dev(file_name): broken_files += file_name + '\n' continue well_names = [well_in_list.name for well_in_list in main_context.wells_list] if well.name not in well_names: main_context.wells_list.append(well) wells_dir.add_well(well) else: exist_well = main_context.wells_list[well_names.index(well.name)] exist_well.read_dev(file_name) return broken_files
def on_actionImport_triggered(self, qt_invoker): """ executes from context menu :param qt_invoker: item where was context menu invoked """ files_list, files_type = QFileDialog.getOpenFileNames( self, "Select one or more files to open", Config.default_dir_path, "dev files *.dev(*.dev);; las files *.las(*.las);; WellTops file *.txt(*.txt)" ) log.debug("files_type = {0} \tfiles_list = {1}".format( files_type, files_list)) func = { "dev files *.dev(*.dev)": imports.import_dev, " las files *.las(*.las)": imports.import_las, " WellTops file *.txt(*.txt)": imports.import_well_tops }.get(files_type) if not func: return broken_files = str() if not isinstance(qt_invoker, QTreeWidgetItem): broken_files = func(files_list, main_context.root_dir) else: broken_files = func(files_list, qt_invoker.source) if broken_files and len(broken_files) > 0: QMessageBox.warning(self, "Warning", "Following files are broken:\n" + broken_files) self.reset_content()
def import_well_tops(files_list, wells_dir): """ If there is well with appropriate name (name from tops file) then add this top to this well else ignore this top :type files_list: list of files paths """ log.debug("i'm in import_well_tops()") broken_files = str() for file_name in files_list: try: f = open(file_name) lines = f.readlines() well_names = [well_in_list.name for well_in_list in main_context.wells_list] if not re.match(r'[-+]?\d+\.\d+', lines[0].split()[2]): lines.remove(lines[0]) try: for line in lines: m = re.match('\s*(?P<well_name>\S+)\s+(?P<surface_id>\S+)\s+(?P<md>[-+]?\d+\.\d+)\s*', line) if not m: log.warning('not match: %s' % line) broken_files += file_name + '\n' continue well_name, surface_id, md = m.groups() top = Top(well_name=well_name, surface_id=surface_id, md=float(md)) if top.well_name in well_names: well = main_context.wells_list[well_names.index(top.well_name)] if well.add_top(top): top.add_well(well) main_context.tops_list.append(top) top.calculate_addition_fields() except ValueError as ex: log.error(line + ' ' + str(ex)) broken_files += file_name + '\n' except Exception: broken_files += file_name + '\n' return broken_files
def read_dev(self, dev_file): """ reads las file using the following parser :param dev_file: path to target file """ try: f = open(dev_file, 'r') lines = f.readlines() # check for file length validity if len(lines) < 17: log.warning('Too short file: "%s"' % dev_file) return False def read_head(self, lines): """ submethod for reading las file head information """ try: self.name = re.search(r'# WELL NAME:\s*(?P<well_name>\S+)', lines[1]).group('well_name') self.head_x = float( re.search( r'# WELL HEAD X-COORDINATE:\s*(?P<head_x>[-+]?\d+\.\d+)', lines[2]).group('head_x')) self.head_y = float( re.search( r'# WELL HEAD Y-COORDINATE:\s*(?P<head_y>[-+]?\d+\.\d+)', lines[3]).group('head_y')) self.offset = float( re.search( r'# WELL OFFSET \(from MSL\):\s*(?P<offset>[-+]?\d+\.\d+)', lines[4]).group('offset')) log.debug( 'name={0}\t head_x={1}\t head_y={2}\t offset={3}'. format(self.name, self.head_x, self.head_y, self.offset)) except AttributeError as ex: log.warning(str(ex)) return False return True # reads the head information if not read_head(self, lines): return False, '*.dev file header format not valid' # reads the list of available columns columns = re.findall(r'\s*(\b\w+)\s*', lines[13]) columns = [column.lower() for column in columns] for column in columns: getattr(self, column).clear() log.debug('columns=' + str(columns)) # reads coordinates information by each column for line in lines[15:]: values = re.findall(r'\s*([-+]?\d+\.\d+)\s*', line) for i in range(len(columns)): getattr(self, columns[i]).append(float(values[i])) self.check_coordinate_columns_validity( ) # verify validity of the columns coordinates except Exception as ex: log.error(str(ex)) return False return True
def on_actionSpreadsheet_triggered(self, qt_invoker): """ executes from context menu :param qt_invoker: item where was context menu invoked """ log.debug('action spreadsheet') if qt_invoker.UserType == 'well' and qt_invoker.text(1) != 'needs dev': text = \ 'well_name = {0}\n' \ 'head_x = {1}\n' \ 'head_y = {2}\n' \ 'offset = {3}\n' \ '#======================================================================================================================================\n' \ ' MD X Y Z TVD DX DY AZIM INCL DLS\n' \ '#======================================================================================================================================\n' \ ''.format(qt_invoker.source.name, qt_invoker.source.head_x, qt_invoker.source.head_y, qt_invoker.source.offset) for i in range(len(qt_invoker.source.md)): text += ' {0:0<12} {1:0<12} {2:0<12} {3:0<12} {4:0<12} {5:0<12} {6:0<12} {7:0<12} {8:0<12} {9:0<12}\n'.format( qt_invoker.source.md[i], qt_invoker.source.x[i], qt_invoker.source.y[i], qt_invoker.source.z[i], qt_invoker.source.tvd[i], qt_invoker.source.dx[i], qt_invoker.source.dy[i], qt_invoker.source.azim[i], qt_invoker.source.incl[i], qt_invoker.source.dls[i]) layout = QtWidgets.QVBoxLayout(self) qt_text_edit = QtWidgets.QTextEdit(self) qt_text_edit.setReadOnly(True) qt_text_edit.setCurrentFont(QtGui.QFont("Liberation Mono", 10)) layout.addWidget(qt_text_edit) qt_text_edit.setText(text) qt_dialog = QtWidgets.QDialog(self) qt_dialog.setWindowTitle('Spreadsheet') qt_dialog.setLayout(layout) qt_dialog.setMinimumWidth(1100) qt_dialog.setMinimumHeight(600) qt_dialog.show() if qt_invoker.UserType == 'tops_dir': well = qt_invoker.parent().source if len(well.tops_list) < 1: return text = 'Well Surface_id MD\n' for top in well.tops_list: text += '{0:<10} {1:<15} {2:<f}\n'.format( top.well_name, top.surface_id, top.md) layout = QtWidgets.QVBoxLayout(self) qt_text_edit = QtWidgets.QTextEdit(self) qt_text_edit.setReadOnly(True) qt_text_edit.setCurrentFont(QtGui.QFont("Liberation Mono", 10)) layout.addWidget(qt_text_edit) qt_text_edit.setText(text) qt_dialog = QtWidgets.QDialog(self) qt_dialog.setWindowTitle('Spreadsheet') qt_dialog.setLayout(layout) qt_dialog.setMinimumWidth(330) qt_dialog.setMinimumHeight(180) qt_dialog.show() if qt_invoker.UserType == 'curves_dir': well = qt_invoker.parent().source if not well.las: return text = StringIO() well.las.write(text, version=2.0, fmt="%10.5f") layout = QtWidgets.QVBoxLayout(self) qt_text_edit = QtWidgets.QTextEdit(self) qt_text_edit.setReadOnly(True) qt_text_edit.setCurrentFont(QtGui.QFont("Liberation Mono", 10)) layout.addWidget(qt_text_edit) qt_text_edit.setText(text.getvalue()) qt_dialog = QtWidgets.QDialog(self) qt_dialog.setWindowTitle('Spreadsheet') qt_dialog.setLayout(layout) qt_dialog.setMinimumWidth(1000) qt_dialog.setMinimumHeight(500) qt_dialog.show()
def check_changed(self, item, column): """ executes when some item in tree widget changed their state :param column: column where item state was changed :param item: item which state was changed """ self.blockSignals(True) # not mark signal if item.checkState(0) == item.previous_state: return item.previous_state = item.checkState(0) log.debug('type="{0}" name="{1} signal={2}"'.format( item.UserType, item.text(0), item.previous_state)) if item.UserType == 'wells_dir': def mark_sub_items(item): children = [item.child(i) for i in range(item.childCount())] for child in children: if child.UserType == 'well': child.setCheckState(0, item.checkState(0)) child.previous_state = item.checkState(0) continue if child.UserType == 'wells_dir': child.setCheckState(0, item.checkState(0)) child.previous_state = item.checkState(0) mark_sub_items(child) mark_sub_items(item) elif item.UserType == 'curve_aliases_dir': state = item.checkState(0) item = item.parent() def mark_sub_items(item): children = [item.child(i) for i in range(item.childCount())] for child in children: if child.UserType in ['curve_alias', 'curve']: child.setCheckState(0, state) child.previous_state = state continue if child.UserType in ['curve_aliases_dir', 'curves_dir']: child.setCheckState(0, state) child.previous_state = state mark_sub_items(child) continue if child.UserType in ['wells_dir', 'well']: mark_sub_items(child) mark_sub_items(item) elif item.UserType == 'top_aliases_dir': state = item.checkState(0) item = item.parent() def mark_sub_items(item): children = [item.child(i) for i in range(item.childCount())] for child in children: if child.UserType in ['top_alias', 'top']: child.setCheckState(0, state) child.previous_state = state continue if child.UserType in ['top_aliases_dir', 'tops_dir']: child.setCheckState(0, state) child.previous_state = state mark_sub_items(child) continue if child.UserType in ['wells_dir', 'well']: mark_sub_items(child) mark_sub_items(item) elif item.UserType == 'curve_alias': state = item.checkState(0) name = item.text(0) item = item.parent().parent() def mark_sub_items(item): children = [item.child(i) for i in range(item.childCount())] for child in children: if child.UserType in ['curve', 'curve_alias' ] and child.text(0) == name: child.setCheckState(0, state) child.previous_state = state continue if child.UserType in [ 'wells_dir', 'well', 'curve_aliases_dir', 'curves_dir' ]: mark_sub_items(child) mark_sub_items(item) elif item.UserType == 'top_alias': state = item.checkState(0) name = item.text(0) item = item.parent().parent() def mark_sub_items(item): children = [item.child(i) for i in range(item.childCount())] for child in children: if child.UserType in ['top', 'top_alias' ] and child.text(0) == name: child.setCheckState(0, state) child.previous_state = state continue if child.UserType in [ 'wells_dir', 'well', 'top_aliases_dir', 'tops_dir' ]: mark_sub_items(child) mark_sub_items(item) elif item.UserType in ['curves_dir', 'tops_dir']: children = [item.child(i) for i in range(item.childCount())] for child in children: child.setCheckState(0, item.checkState(0)) child.previous_state = item.checkState(0) self.window().tab_2d_map.refresh() self.window().tab_sections.reset() self.blockSignals(False)
def refresh(self): """ executes every time when there was checked new well or new top """ self.ax.clear() self.ax.set_ylabel("y-axis (m)", color="white") self.ax.set_xlabel("x-axis (m)", color="white") self.ax.set_axis_bgcolor("black") self.ax.tick_params(color='white', labelcolor='white') for spine in self.ax.spines.values(): spine.set_color('white') self.ax.tick_params(axis='both', which='major', labelsize=8) self.ax.grid(color="gray") y_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False) self.ax.yaxis.set_major_formatter(y_formatter) # ----получаем два списка x и y координат скважин---- checked_wells = [ well for well in main_context.wells_list if (well.qt_item.checkState(0) and len(well.md) > 0) ] wells_x_list = [well.x[-1] for well in checked_wells] wells_y_list = [well.y[-1] for well in checked_wells] wells_names = [well.name for well in checked_wells] log.debug("(fileName, x, y) = {0}".format( list(zip(wells_names, wells_x_list, wells_y_list)))) self.ax.scatter(wells_x_list, wells_y_list, marker=".", c="#666600", edgecolors="#666600") for x, y, name in zip(wells_x_list, wells_y_list, wells_names): self.ax.annotate('{}'.format(name), xy=(x, y), color='yellow', fontsize=10) # ----получаем два списка x и y координат well_tops---- checked_tops = [ top for top in main_context.tops_list if top.qt_item.checkState(0) ] tops_x_list = [top.x for top in checked_tops] tops_y_list = [top.y for top in checked_tops] tops_names = [ top.well_name + ' ' + top.surface_id for top in checked_tops ] self.ax.scatter(tops_x_list, tops_y_list, marker=".", c="#89060D", edgecolors="#89060D") for x, y, name in zip(tops_x_list, tops_y_list, tops_names): self.ax.annotate('{}'.format(name), xy=(x, y), color='red', fontsize=10) # ---------------- масштабируем -------------------------- x_list = wells_x_list + tops_x_list y_list = wells_y_list + tops_y_list x_min = min(x_list, default=0) x_max = max(x_list, default=1) delta_x = x_max - x_min y_min = min(y_list, default=0) y_max = max(y_list, default=1) delta_y = y_max - y_min delta_max = max([delta_x, delta_y]) self.ax.set_xlim( [x_min - delta_max / 10, x_min + delta_max + delta_max / 10]) self.ax.set_ylim( [y_min - delta_max / 10, y_min + delta_max + delta_max / 10]) start, end = self.ax.get_xlim() self.ax.xaxis.set_ticks(np.linspace(start, end, 13)) start, end = self.ax.get_ylim() self.ax.yaxis.set_ticks(np.linspace(start, end, 13)) self.draw()