コード例 #1
0
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        for name, payload in self.data.items():
            print name
            payload['coords'] = self.linspace
            payload['data'] = np.zeros_like(self.linspace)
            if payload['colour_is_file']:
                payload['colour'] = np.zeros_like(self.linspace)
            else:
                payload['colour'] = payload['all_colour']

            for i in self.linspace:
                i = int(i)
                x, y = transect.interpolate(i).xy
                xi = np.abs(payload['all_coords'][0][0, :] - x).argmin()
                yi = np.abs(payload['all_coords'][1][:, 0] - y).argmin()

                payload['data'][i] = payload['all_data'][yi, xi]
                if payload['colour_is_file']:
                    try:
                        payload['colour'][i] = payload['all_colour'][yi, xi]
                    except IndexError:
                        payload['colour'][i] = 0

            self.data[name] = payload
コード例 #2
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect):
        """
        Gather the data near the transect. Depth convert if necessary.

        Returns nothing. Side effect: sets attributes.

        Args:
            transect (LineString): A shapely LineString object.
        """
        Notice.info("Updating " + self.__class__.__name__)

        b = self.settings.get('fine_buffer') or self.settings['buffer']
        prepared = prep(transect.buffer(b))

        for horizon, points in self.lookup.items():
            l = len(points)
            points = filter(prepared.contains, points)
            print horizon, len(points), "of", l, "points"
            data, coords = [], []
            for p in points:
                coords.append(transect.project(p))
                if self.domain.lower() in ['depth', 'd', 'z']:
                    "Depth converting horizon"
                    zpt = self.velocity.time2depthpt(p.z/1000, coords[-1])
                    data.append(zpt)
                else:
                    data.append(p.z)

            self.data[horizon] = np.array(data)
            self.coords[horizon] = np.array(coords)
コード例 #3
0
def insert(root=None):
    logging.debug("called : %s", __name__)
    logging.debug("argument root : %s", root)

    if root is None:
        logging.debug("empty root is received")
        root = os.path.abspath(os.path.dirname(__file__)) + "/gen/json"
    if not os.path.isdir(root):
        logging.debug("making directory : %s", root)
        os.makedirs(root)

    notices = extract.get_notice_list(False)
    if notices is None:
        logging.error("error getting notice list")
        return None
    count = 0
    for notice in notices:
        timestamp = str(notice['timestamp'])
        path = root + '/' + timestamp + '.json'
        if os.path.isfile(path):
            continue
        else:
            count += 1
            print "Saved notice dated '{}' titled '{}'.".format(
                notice['time'], notice['title'])
            logging.info("Saved notice dated %s titled %s", notice['time'],
                         notice['title'])

            n = Notice(timestamp)
            n.save_json(notice)

    logging.info("%d notices inserted", count)
    return count
コード例 #4
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        for name, payload in self.data.items():
            print name
            payload['coords'] = self.linspace
            payload['data'] = np.zeros_like(self.linspace)
            if payload['colour_is_file']:
                payload['colour'] = np.zeros_like(self.linspace)
            else:
                payload['colour'] = payload['all_colour']

            for i in self.linspace:
                i = int(i)
                x, y = transect.interpolate(i).xy
                xi = np.abs(payload['all_coords'][0][0, :] - x).argmin()
                yi = np.abs(payload['all_coords'][1][:, 0] - y).argmin()

                payload['data'][i] = payload['all_data'][yi, xi]
                if payload['colour_is_file']:
                    try:
                        payload['colour'][i] = payload['all_colour'][yi, xi]
                    except IndexError:
                        payload['colour'][i] = 0

            self.data[name] = payload
コード例 #5
0
def insert(root = None):
	logging.debug("called : %s", __name__)
	logging.debug("argument root : %s", root)

	if root is None:
		logging.debug("empty root is received")
		root = os.path.abspath(os.path.dirname(__file__)) + "/gen/json"
	if not os.path.isdir(root):
		logging.debug("making directory : %s", root)
		os.makedirs(root)

	notices = extract.get_notice_list(False)
	if notices is None:
		logging.error("error getting notice list")
		return None
	count = 0
	for notice in notices:
		timestamp = str(notice['timestamp'])
		path = root + '/' + timestamp + '.json'
		if os.path.isfile(path):
			continue;
		else:
			count += 1
			print "Saved notice dated '{}' titled '{}'.".format(notice['time'], notice['title'])
			logging.info("Saved notice dated %s titled %s",
					notice['time'], notice['title'])

			n = Notice(timestamp)
			n.save_json(notice)

	logging.info("%d notices inserted", count)
	return count
コード例 #6
0
    def update(self, transect):
        """
        Gather the data near the transect. Depth convert if necessary.

        Returns nothing. Side effect: sets attributes.

        Args:
            transect (LineString): A shapely LineString object.
        """
        Notice.info("Updating " + self.__class__.__name__)

        b = self.settings.get('fine_buffer') or self.settings['buffer']
        prepared = prep(transect.buffer(b))

        for horizon, points in self.lookup.items():
            l = len(points)
            points = filter(prepared.contains, points)
            print horizon, len(points), "of", l, "points"
            data, coords = [], []
            for p in points:
                coords.append(transect.project(p))
                if self.domain.lower() in ['depth', 'd', 'z']:
                    "Depth converting horizon"
                    zpt = self.velocity.time2depthpt(p.z / 1000, coords[-1])
                    data.append(zpt)
                else:
                    data.append(p.z)

            self.data[horizon] = np.array(data)
            self.coords[horizon] = np.array(coords)
コード例 #7
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        pad = self.settings['map_padding']
        aspect = 12/3.  # I was expecting it to be 8:3.

        # Calculate the map bounds and centre.
        bounds = transect.bounds
        llx, lly, urx, ury = bounds
        w, h = urx - llx, ury - lly

        x_adj, y_adj = 0, 0
        if h > (w/aspect):
            x_adj = ((aspect*h) - w) / 2.  # Aspect is hard-coded in uberplot
        else:
            y_adj = ((w/aspect) - h) / 2.

        utm_nad83 = pp.Proj("+init=EPSG:26920")
        ll_nad83 = pp.Proj("+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs")
        utm2lola = partial(pp.transform, utm_nad83, ll_nad83)

        ll = transform(utm2lola, Point(llx-pad-x_adj, lly-pad-y_adj))
        ur = transform(utm2lola, Point(urx+pad+x_adj, ury+pad+y_adj))
        self.ll, self.ur = ll, ur
        self.mid = Point(ll.x + 0.5*(ur.x-ll.x), ll.y + 0.5*(ur.y - ll.y))

        # Go over the layers and collect data.
        for layer, details in self.layers.items():
            path = details['file']
            print layer, path

            # Set up convenient params dictionary for plotting function.
            params = {k: v for k, v in details.items() if k != 'file'}
            self.layers[layer]['params'] = params

            # Get a list of shapes from the file.
            shapes = []
            fname, ext = os.path.splitext(os.path.basename(path))
            if ext.strip('.').lower() in self.settings['raster_extensions']:
                # TODO: Deal with rasters.
                pass
            elif ext.strip('.').lower() == 'shp':
                with fiona.open(path) as c:
                    for s in c:
                        shapes.append(shape(s['geometry']))
                        # name = s.get('name') or s.get('id') or None
                        # data = {name: shape(s['geometry'])}
                        # setattr(self, 'data', data)
                setattr(self, layer, shapes)
            else:
                pass
コード例 #8
0
def send_name(filename):
	'''Send the notification for the notice of given json filename'''
	logging.debug("called : %s", __name__)
	logging.debug("argument filename : %s", filename)

	if filename is None:
		logging.error("empty filename received")
		return

	n = Notice(filename)
	notice = n.get_json()

	# If the notice is not updated, update it.
	logging.debug("checking if notice is updated")
	if not notice['updated']:
		update.update_json(filename)
		notice = n.get_json()

	# If the notice is not sent, send it.
	logging.debug("checking if notice is sent")
	if not notice['sent']:
		if send_json(notice):
			# If notice is sent, save it locally. So that it is not
			# sent again.
			logging.debug("notice is sent - saving it locally")
			notice['sent'] = True
			n.save_json(notice)
			return True
		else:
			logging.error("failed sending notice")
			return False
	else:
		logging.debug("notice is already sent")
		return False
コード例 #9
0
    def update(self, notice: Notice):
        assert notice.is_empty() == False

        # 存在则更新,不存在则新建
        self.collection.update_one({'nid': notice.nid},
                                   {'$set': notice.to_dict()},
                                   upsert=True)
コード例 #10
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        self.reset_data()

        points = [Point(xy) for xy in transect.coords]
        for polygon, properties in self.lookup.items():
            for p in filter(polygon.contains, points):
                self.data.append(properties)
                self.coords.append(transect.project(p))

        # Sort the data to be in order
        idx = sorted(range(len(self.coords)),
                     key=lambda k: self.coords[k])

        self.data = [self.data[i] for i in idx]
        self.coords = np.array([self.coords[i] for i in idx])
コード例 #11
0
 def initialize_notice(self):
     log_file = self.conf.get("log", None)
     if log_file is not None:
         log_notice = OutputToFile(log_file)
         self.notice = Notice(log_notice, log_notice)
     else:
         self.notice = Notice()
コード例 #12
0
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        self.reset_data()

        points = [Point(xy) for xy in transect.coords]
        for polygon, properties in self.lookup.items():
            for p in filter(polygon.contains, points):
                self.data.append(properties)
                self.coords.append(transect.project(p))

        # Sort the data to be in order
        idx = sorted(range(len(self.coords)), key=lambda k: self.coords[k])

        self.data = [self.data[i] for i in idx]
        self.coords = np.array([self.coords[i] for i in idx])
コード例 #13
0
    def load_work_state(self, event=None):

        message = 'Any unsaved work that you have open will be lost. Continue?'
        load_work = tkMessageBox.askyesno('Load work state?', message)

        if load_work:
            work_state_file = tkFileDialog.askopenfilename()
            if work_state_file:
                self.work_state_filename = work_state_file
                work_state = cPickle.load(open(self.work_state_filename, 'r'))
                self.root_notice_file = work_state['root_notice']
                self.notices_files = work_state['open_notices']
                self.terms = work_state['definitions']
                self.always_fix = work_state['always_fix']
                self.never_fix = work_state['never_fix']

                self.root_notice = Notice(self.root_notice_file)
                self.current_notice = self.root_notice.document_number
                self.add_element_to_tree(self.root_notice.tree, None)
                self.trees[self.root_notice.document_number] = self.root_notice
                self.populate_definitions()
                self.notices.append(self.root_notice.document_number)

                notices = [
                    Notice(notice_file) for notice_file in self.notices_files
                ]
                notices.sort(key=lambda n: n.effective_date)

                for notice in notices:
                    self.notices.append(notice.document_number)
                    self.trees[notice.document_number] = notice

                self.update_notices_list()
                self.populate_definitions()
コード例 #14
0
def get_text_path(path):
	"""
	Given path to json file, return a formatted body string with all the details
	"""
	logging.debug("called : %s", __name__)
	logging.debug("argument path : ", path)
	n = Notice(path)
	notice = n.get_json()
	return get_text_dict(notice)
コード例 #15
0
def get_text_path(path):
    """
	Given path to json file, return a formatted body string with all the details
	"""
    logging.debug("called : %s", __name__)
    logging.debug("argument path : ", path)
    n = Notice(path)
    notice = n.get_json()
    return get_text_dict(notice)
コード例 #16
0
 def get_notice(self, content, notice_type):
     class_name = notice_type.capitalize()
     notices = content.find(id=notice_type)
     if notices and len(notices):
         notices = notices.find(class_="list-block").children
         for notice in notices:
             if notice != '\n':
                 description, link, date = self.parse_content(notice)
                 new_notice = Notice(notice_type, description, link, date)
                 new_notice.save_notice()
コード例 #17
0
    def open_root_notice(self):

        load_root = False

        if self.root_notice is not None:
            message = "You already have a root notice loaded. If you load " + \
            "another root notice, your current set of notices will be replaced. " + \
            "Are you sure you want to do this?"
            result = tkMessageBox.askokcancel('Replace root?', message)
            if result:
                load_root = True
        else:
            load_root = True

        if load_root:
            self.notices = []
            self.root_notice = None
            self.current_notice = None
            self.trees = {}
            for child in self.element_tree.get_children():
                self.element_tree.delete(child)

            notice_file = tkFileDialog.askopenfilename()
            if notice_file:
                notice = Notice(notice_file)
                self.current_notice = notice.document_number
                self.notices.append(notice.document_number)
                self.root_notice = notice
                self.root_notice_file = notice_file
                self.add_element_to_tree(notice.tree, None)
                self.update_notices_list()
                self.trees[notice.document_number] = self.root_notice
                self.populate_definitions()

                cfr_section = notice.tree.find('{eregs}preamble').find(
                    './/{eregs}section').text
                all_notice_files = find_all(cfr_section, is_notice=True)

                message = "There are {} additional notices associated with this root version. ".format(len(all_notice_files)) + \
                    "Would you like to load all of them? This can take some time if the notices " + \
                    "are very large."
                result = tkMessageBox.askokcancel('Load all notices?', message)
                if result:
                    self.notices_files = all_notice_files
                    all_notices = [
                        Notice(notice_file) for notice_file in all_notice_files
                    ]
                    all_notices.sort(key=lambda n: n.effective_date)
                    for notice in all_notices:
                        self.notices.append(notice.document_number)
                        self.trees[notice.document_number] = notice

                    self.update_notices_list()
                    self.populate_definitions()
コード例 #18
0
 def get(self, uid=None):
     """
     获取通知,传入 uid: str 来指定获取用于指定用户的通知,缺省 uid=None 获取所有通知
     """
     notices = []
     for r in self.collection.find() or []:
         n = Notice().from_dict(r)
         if n.is_expired():
             self.drop_expired(n)
         if uid == None or n.is_for_user(uid):
             notices.append(n.dumps())
     return notices
コード例 #19
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        # Preprocess
        prepared = prep(transect.buffer(self.settings['buffer']))

        # Get the intersecting points
        points = filter(prepared.contains, self.lookup.keys())

        self.reset_data()
        self.names = []

        for point in points:
            name = self.lookup[point]
            self.names.append(name)
            print name,

            pattern = "^" + name + "_out.las"
            for fname in utils.walk(self.well_dir, pattern):
                # This is a loop but there should only be one matching file.
                well = Well(fname, null_subs=np.nan)
                print well.curves.names
                self.data.append(well)
                self.log_lookup[name] = self.data[-1]

            if not self.log_lookup.get(name):
                print
                self.data.append(None)

            sl_name = getattr(self, 'striplog', None)
            sl = None
            if sl_name and (name == self.feature_well):
                lexicon = Lexicon.default()
                pattern = "^" + name + ".*striplog.las"
                for fname in utils.walk(self.well_dir, pattern):
                    # Load the striplog.
                    sl = Well(fname, lexicon=lexicon, null_subs=np.nan)

                    # Add it to the well
                    self.log_lookup[name].add_striplog(sl.striplog[sl_name],
                                                       sl_name)

            self.coords.append(transect.project(point))
コード例 #20
0
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        # Preprocess
        prepared = prep(transect.buffer(self.settings['buffer']))

        # Get the intersecting points
        points = filter(prepared.contains, self.lookup.keys())

        self.reset_data()
        self.names = []

        for point in points:
            name = self.lookup[point]
            self.names.append(name)
            print name,

            pattern = "^" + name + "_out.las"
            for fname in utils.walk(self.well_dir, pattern):
                # This is a loop but there should only be one matching file.
                well = Well(fname, null_subs=np.nan)
                print well.curves.names
                self.data.append(well)
                self.log_lookup[name] = self.data[-1]

            if not self.log_lookup.get(name):
                print
                self.data.append(None)

            sl_name = getattr(self, 'striplog', None)
            sl = None
            if sl_name and (name == self.feature_well):
                lexicon = Lexicon.default()
                pattern = "^" + name + ".*striplog.las"
                for fname in utils.walk(self.well_dir, pattern):
                    # Load the striplog.
                    sl = Well(fname, lexicon=lexicon, null_subs=np.nan)

                    # Add it to the well
                    self.log_lookup[name].add_striplog(sl.striplog[sl_name],
                                                       sl_name)

            self.coords.append(transect.project(point))
コード例 #21
0
def sent_false():
	logging.debug('called : sent_false')
	root = os.path.abspath(os.path.dirname(__file__))
	path = root + '/gen/json/'
	listfile = os.listdir(path)
	if 'old' in listfile:
		listfile.remove('old')
	for fl in listfile:
		n = Notice(fl)
		notice = n.get_json()
		if not notice['sent']:
			notice['sent'] = True
			n.save_json(notice)
コード例 #22
0
    def drop_expired(self, notice=None):
        """
        调用 `nu.drop_expired()` 将清除数据库中所有过期的通知

        调用 `nu.drop_expired(notice)` 将删除数据库中 nid = notice.nid 的一条通知,(这是用来支持 `nu.drop_expired()` 的工作的,也可以用来删除通知,但不推荐使用)
        """
        if isinstance(notice, Notice):
            self.collection.delete_one({"nid": notice.nid})
        else:
            for r in self.collection.find() or []:
                n = Notice().from_dict(r)
                if n.is_expired():
                    self.drop_expired(n)
コード例 #23
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def __init__(self, vel_dir, params):

        # Initialize the base class
        super(SimpleVelocityContainer, self).__init__(params)

        self.vel_dir = vel_dir  # used by __str__
        self.profiles = {}
        count = 0
        for profile in fnmatch.filter(os.listdir(vel_dir), '*.txt'):
            count += 1
            with open(os.path.join(vel_dir, profile), 'r') as f:

                # Read the location out of the file
                header = False
                loc = None
                while not header:
                    l = f.readline().lstrip()
                    if l.startswith('#'):
                        header = True
                    elif l.startswith('coordinates'):

                        x, y = l.split(',')[1:]
                        x = float(x)
                        y = float(y)

                        loc = Point((x, y))
                        header = True

                if not loc:
                    # There were no coordinates.
                    loc = Point((0, 0))

                # Build up the time depth profile
                self.profiles[loc] = []
                for line in f.readlines():

                    # Ignore comments
                    if line.strip().startswith('#'):
                        continue

                    if len(line.strip().split(',')) == 2:
                        time, depth = line.strip().split(',')
                    elif len(line.strip().split()) == 2:
                        time, depth = line.strip().split()
                    else:
                        Notice.warning("Could not read velocity file.")
                        continue

                    self.profiles[loc].append([float(time), float(depth)])
        self.count = count
コード例 #24
0
    def __init__(self, vel_dir, params):

        # Initialize the base class
        super(SimpleVelocityContainer, self).__init__(params)

        self.vel_dir = vel_dir  # used by __str__
        self.profiles = {}
        count = 0
        for profile in fnmatch.filter(os.listdir(vel_dir), '*.txt'):
            count += 1
            with open(os.path.join(vel_dir, profile), 'r') as f:

                # Read the location out of the file
                header = False
                loc = None
                while not header:
                    l = f.readline().lstrip()
                    if l.startswith('#'):
                        header = True
                    elif l.startswith('coordinates'):

                        x, y = l.split(',')[1:]
                        x = float(x)
                        y = float(y)

                        loc = Point((x, y))
                        header = True

                if not loc:
                    # There were no coordinates.
                    loc = Point((0, 0))

                # Build up the time depth profile
                self.profiles[loc] = []
                for line in f.readlines():

                    # Ignore comments
                    if line.strip().startswith('#'):
                        continue

                    if len(line.strip().split(',')) == 2:
                        time, depth = line.strip().split(',')
                    elif len(line.strip().split()) == 2:
                        time, depth = line.strip().split()
                    else:
                        Notice.warning("Could not read velocity file.")
                        continue

                    self.profiles[loc].append([float(time), float(depth)])
        self.count = count
コード例 #25
0
def send_name(filename):
    '''Send the notification for the notice of given json filename'''
    logging.debug("called : %s", __name__)
    logging.debug("argument filename : %s", filename)

    if filename is None:
        logging.error("empty filename received")
        return

    n = Notice(filename)
    notice = n.get_json()

    # If the notice is not updated, update it.
    logging.debug("checking if notice is updated")
    if not notice['updated']:
        update.update_json(filename)
        notice = n.get_json()

    # If the notice is not sent, send it.
    logging.debug("checking if notice is sent")
    if not notice['sent']:
        if send_json(notice):
            # If notice is sent, save it locally. So that it is not
            # sent again.
            logging.debug("notice is sent - saving it locally")
            notice['sent'] = True
            n.save_json(notice)
            return True
        else:
            logging.error("failed sending notice")
            return False
    else:
        logging.debug("notice is already sent")
        return False
コード例 #26
0
def update_json(name):
    logging.debug("called : %s", __name__)
    logging.debug("argument name : %s", name)

    path = jsondir + name
    if not os.path.isfile(path):
        logging.error("json file '%s' is not present.", path)
        return

    n = Notice(name)
    notice = n.get_json()

    # If the json is erroneous, i.e, has empty fields like topic etc, start
    # fresh by removing the json file. This way the json will be reloaded at
    # next cron update.
    if erroneous_json(notice):
        logging.error("Encountered errnoneous json %s. Deleting.", str(path))
        os.remove(path)
        return False

    # If notice is updated, do not update it once more.
    if notice['updated']:
        logging.info("notice %s is already updated", name)
        return False

    details = get_details_url(notice['url'], notice['num_attachments'] == 1)

    logging.debug(
        "Notice has been updated with information from the notice	page")
    notice['updated'] = True
    notice['text'] = details['text']
    if notice['num_attachments'] == 1:
        notice['attachments'] = details['attachments']
        notice['num_attachments'] = len(details['attachments'])

    logging.debug('Saving the updated notice')
    n.save_json(notice)

    return True
コード例 #27
0
def update_json(name):
    logging.debug("called : %s", __name__)
    logging.debug("argument name : %s", name)

    path = jsondir + name
    if not os.path.isfile(path):
        logging.error("json file '%s' is not present.", path)
        return

    n = Notice(name)
    notice = n.get_json()

    # If the json is erroneous, i.e, has empty fields like topic etc, start
    # fresh by removing the json file. This way the json will be reloaded at
    # next cron update.
    if erroneous_json(notice):
        logging.error("Encountered errnoneous json %s. Deleting.", str(path))
        os.remove(path)
        return False

        # If notice is updated, do not update it once more.
    if notice["updated"]:
        logging.info("notice %s is already updated", name)
        return False

    details = get_details_url(notice["url"], notice["num_attachments"] == 1)

    logging.debug("Notice has been updated with information from the notice	page")
    notice["updated"] = True
    notice["text"] = details["text"]
    if notice["num_attachments"] == 1:
        notice["attachments"] = details["attachments"]
        notice["num_attachments"] = len(details["attachments"])

    logging.debug("Saving the updated notice")
    n.save_json(notice)

    return True
コード例 #28
0
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        # space = np.linspace(0, transect.length, self.nsamples)
        for i, n in enumerate(self.linspace):

            # interpolate along the transect
            x, y = transect.interpolate(n).xy

            # Get the closest elevation points
            xi = np.abs(self.all_coords[0][0, :] - x).argmin()
            yi = np.abs(self.all_coords[1][:, 0] - y).argmin()

            self.data[i] = self.all_data[yi, xi]
コード例 #29
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        # space = np.linspace(0, transect.length, self.nsamples)
        for i, n in enumerate(self.linspace):

            # interpolate along the transect
            x, y = transect.interpolate(n).xy

            # Get the closest elevation points
            xi = np.abs(self.all_coords[0][0, :] - x).argmin()
            yi = np.abs(self.all_coords[1][:, 0] - y).argmin()

            self.data[i] = self.all_data[yi, xi]
コード例 #30
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def plot(self):
        """
        Generates plot for the transect.
        """

        # Set the extent to the length? Or keep them all the same?
        self.extents[0] = 0
        self.extents[1] = self.data.length

        Notice.hr_header("Updating")
        # update the containers
        self.velocity.update(self.data)
        self.log.update(self.data)
        self.seismic.update(self.data)
        self.horizons.update(self.data)
        self.elevation.update(self.data)
        self.bedrock.update(self.data)
        self.potfield.update(self.data)
        self.locmap.update(self.data)

        Notice.hr_header("Plotting")
        plot(self)
        plt.show()
コード例 #31
0
    def plot(self):
        """
        Generates plot for the transect.
        """

        # Set the extent to the length? Or keep them all the same?
        self.extents[0] = 0
        self.extents[1] = self.data.length

        Notice.hr_header("Updating")
        # update the containers
        self.velocity.update(self.data)
        self.log.update(self.data)
        self.seismic.update(self.data)
        self.horizons.update(self.data)
        self.elevation.update(self.data)
        self.bedrock.update(self.data)
        self.potfield.update(self.data)
        self.locmap.update(self.data)

        Notice.hr_header("Plotting")
        plot(self)
        plt.show()
コード例 #32
0
    def open_additional_notice(self):

        notice_file = tkFileDialog.askopenfilename()

        if notice_file:
            replace_notice = True
            notice = Notice(notice_file)
            if notice.document_number in self.notices:
                message = 'You already have this notice loaded. If you reload it, ' + \
                    'your unsaved work will be replaced. Are you sure you want to do this?'
                replace_notice = tkMessageBox.askokcancel(
                    'Replace notice?', message)

            if replace_notice:
                self.notices.append(notice.document_number)
                self.notices_files.append(notice_file)
                self.trees[notice.document_number] = notice
                self.update_notices_list()
                self.populate_definitions()
コード例 #33
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def __init__(self, **kwargs):

        Notice.title()
        Notice.hr_header("Initializing")

        params = kwargs.get('params')
        layers = kwargs.get('layers')
        potfields = kwargs.get('potfields')
        data = kwargs.get('data')
        velocity = kwargs.get('velocity')

        super(TransectContainer, self).__init__(params)

        print "Starting {}, id {}, file {}".format(self.title,
                                                   self.id,
                                                   self.config_file)

        # Set up 'data' — the transect line — from shapefile.
        self.data = None
        with fiona.open(data['transect_file']) as c:
            for line in c:
                if line['properties']['id'] == self.id:
                    self.data = shape(line['geometry'])
        if not self.data:
            Notice.fail("No transect with ID "+self.id)

        # self.data.length holds the length of the transect in metres
        # But often we want ints, and sometimes the number of samples.
        # This will give us a nice linspace. Put them in params.
        params['length'] = self.length = int(np.floor(self.data.length))
        params['nsamples'] = self.nsamples = self.length + 1
        params['linspace'] = self.linspace = np.linspace(0, self.length,
                                                         self.nsamples)

        self.time = time.strftime("%Y/%m/%d %H:%M", time.localtime())
        self.tops_file = data['tops_file']
        self.log = LogContainer(data['well_dir'], params)
        self.velocity = self.__velocity_factory(velocity, params)
        self.seismic = SeismicContainer(data['seismic_dir'],
                                        self.velocity,
                                        params)
        self.horizons = HorizonContainer(data['horizon_dir'],
                                         self.velocity,
                                         params)
        self.elevation = ElevationContainer(data['elevation_file'], params)
        self.bedrock = BedrockContainer(data['bedrock_dir'], params)
        self.potfield = PotfieldContainer(potfields, params)
        self.locmap = LocmapContainer(layers, params)
コード例 #34
0
    def __init__(self, **kwargs):

        Notice.title()
        Notice.hr_header("Initializing")

        params = kwargs.get('params')
        layers = kwargs.get('layers')
        potfields = kwargs.get('potfields')
        data = kwargs.get('data')
        velocity = kwargs.get('velocity')

        super(TransectContainer, self).__init__(params)

        print "Starting {}, id {}, file {}".format(self.title, self.id,
                                                   self.config_file)

        # Set up 'data' — the transect line — from shapefile.
        self.data = None
        with fiona.open(data['transect_file']) as c:
            for line in c:
                if line['properties']['id'] == self.id:
                    self.data = shape(line['geometry'])
        if not self.data:
            Notice.fail("No transect with ID " + self.id)

        # self.data.length holds the length of the transect in metres
        # But often we want ints, and sometimes the number of samples.
        # This will give us a nice linspace. Put them in params.
        params['length'] = self.length = int(np.floor(self.data.length))
        params['nsamples'] = self.nsamples = self.length + 1
        params['linspace'] = self.linspace = np.linspace(
            0, self.length, self.nsamples)

        self.time = time.strftime("%Y/%m/%d %H:%M", time.localtime())
        self.tops_file = data['tops_file']
        self.log = LogContainer(data['well_dir'], params)
        self.velocity = self.__velocity_factory(velocity, params)
        self.seismic = SeismicContainer(data['seismic_dir'], self.velocity,
                                        params)
        self.horizons = HorizonContainer(data['horizon_dir'], self.velocity,
                                         params)
        self.elevation = ElevationContainer(data['elevation_file'], params)
        self.bedrock = BedrockContainer(data['bedrock_dir'], params)
        self.potfield = PotfieldContainer(potfields, params)
        self.locmap = LocmapContainer(layers, params)
コード例 #35
0
    def notice_dal(self): return Notice()

    @property
コード例 #36
0
    def update(self, transect):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
        """
        Notice.info("Updating " + self.__class__.__name__)

        pad = self.settings['map_padding']
        aspect = 12 / 3.  # I was expecting it to be 8:3.

        # Calculate the map bounds and centre.
        bounds = transect.bounds
        llx, lly, urx, ury = bounds
        w, h = urx - llx, ury - lly

        x_adj, y_adj = 0, 0
        if h > (w / aspect):
            x_adj = ((aspect * h) - w) / 2.  # Aspect is hard-coded in uberplot
        else:
            y_adj = ((w / aspect) - h) / 2.

        utm_nad83 = pp.Proj("+init=EPSG:26920")
        ll_nad83 = pp.Proj("+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs")
        utm2lola = partial(pp.transform, utm_nad83, ll_nad83)

        ll = transform(utm2lola, Point(llx - pad - x_adj, lly - pad - y_adj))
        ur = transform(utm2lola, Point(urx + pad + x_adj, ury + pad + y_adj))
        self.ll, self.ur = ll, ur
        self.mid = Point(ll.x + 0.5 * (ur.x - ll.x),
                         ll.y + 0.5 * (ur.y - ll.y))

        # Go over the layers and collect data.
        for layer, details in self.layers.items():
            path = details['file']
            print layer, path

            # Set up convenient params dictionary for plotting function.
            params = {k: v for k, v in details.items() if k != 'file'}
            self.layers[layer]['params'] = params

            # Get a list of shapes from the file.
            shapes = []
            fname, ext = os.path.splitext(os.path.basename(path))
            if ext.strip('.').lower() in self.settings['raster_extensions']:
                # TODO: Deal with rasters.
                pass
            elif ext.strip('.').lower() == 'shp':
                with fiona.open(path) as c:
                    for s in c:
                        shapes.append(shape(s['geometry']))
                        # name = s.get('name') or s.get('id') or None
                        # data = {name: shape(s['geometry'])}
                        # setattr(self, 'data', data)
                setattr(self, layer, shapes)
            else:
                pass
コード例 #37
0
ファイル: seisplot.py プロジェクト: Aleks-Canstrat/seisplot
        utils.stain_paper(stupid_image)
    utils.add_rings(stupid_image, cfg['coffee_rings'])
    if cfg['scribble']:
        utils.add_scribble(stupid_image)
    stupid_image.save(stem + ".stupid.png")

    s = "Saved stupid file stupid.png in {:.1f} s"
    t4 = time.time()
    Notice.ok(s.format(t4-t3))

    return


if __name__ == "__main__":

    Notice.title()
    parser = argparse.ArgumentParser(description='Plot a SEGY file.')
    parser.add_argument("-c", "--config",
                        metavar="config file",
                        type=argparse.FileType('r'),
                        default="config.yaml",
                        nargs="?",
                        help="The name of a YAML config file.")
    parser.add_argument('filename',
                        metavar='SEGY file',
                        type=str,
                        nargs='?',
                        help='The path to a SEGY file.')
    parser.add_argument('-o', '--out',
                        metavar='Output file',
                        type=str,
コード例 #38
0
        nargs='?',
        default=0,
        help=
        'The number of dimensions of the input seismic, usually 2 or 3. Overrides config file.'
    )
    parser.add_argument('-d',
                        '--demo',
                        action='store_true',
                        help='Run with the demo file, data/31_81_PR.png.')
    parser.add_argument('-v',
                        '--version',
                        action='store_true',
                        help='Get the version number.')
    args = parser.parse_args()
    if args.version:
        Notice.info(__version__)
        sys.exit()
    Notice.title()
    target = args.filename
    with args.config as f:
        cfg = yaml.safe_load(f)
    Notice.hr_header("Initializing")
    Notice.info("config     {}".format(args.config.name))

    # Fill in 'missing' fields in cfg.
    cfg = {k: cfg.get(k, v) for k, v in utils.DEFAULTS.items()}
    cfg['outfile'] = args.out
    cfg['ndim'] = args.ndim or cfg['ndim']

    if args.demo:
        target = './data/31_81_PR.sgy'
コード例 #39
0
def main(target, cfg):
    """
    Puts everything together.
    """
    t0 = time.time()

    #####################################################################
    #
    # READ SEGY
    #
    #####################################################################
    if cfg['segy_library'].lower() == 'obspy':
        s = Seismic.from_segy_with_obspy(target, params={'ndim': cfg['ndim']})
    else:
        s = Seismic.from_segy(target, params={'ndim': cfg['ndim']})

    # Set the line and/or xline number.
    try:
        n, xl = cfg['number']
    except:
        n, xl = cfg['number'], 0.5

    # Set the direction.
    if (s.ndim) == 2:
        direction = ['inline']
    elif cfg['direction'].lower()[0] == 'i':
        direction = ['inline']
    elif cfg['direction'].lower()[0] in ['x', 'c']:  # Allow 'crossline' too.
        direction = ['xline']
    elif cfg['direction'].lower()[0] == 't':
        direction = ['tslice']
    else:
        direction = ['xline', 'inline']

    # Get the data.
    try:
        ss = [
            Seismic.from_seismic(s, n=n, direction=d)
            for n, d in zip((n, xl), direction)
        ]
    except IndexError:
        # Perhaps misinterpreted 2D as 3D
        s = Seismic.from_segy(target, params={'ndim': 2})
        direction = ['inline']
        ss = [
            Seismic.from_seismic(s, n=n, direction=d)
            for n, d in zip((n, xl), direction)
        ]

    clip_val = np.percentile(s.data, cfg['percentile'])

    if clip_val < 10:
        fstr = '{:.3f}'
    elif clip_val < 100:
        fstr = '{:.2f}'
    elif clip_val < 1000:
        fstr = '{:.1f}'
    else:
        fstr = '{:.0f}'

    # Notify user of parameters.
    Notice.info("n_traces   {}".format(s.ntraces))
    Notice.info("n_samples  {}".format(s.nsamples))
    Notice.info("dt         {}".format(s.dt))
    Notice.info("t_start    {}".format(s.tstart))
    Notice.info("t_end      {}".format(s.tend))
    Notice.info("max_val    " + fstr.format(np.amax(s.data)))
    Notice.info("min_val    " + fstr.format(np.amin(s.data)))
    Notice.info("clip_val   " + fstr.format(clip_val))

    t1 = time.time()
    Notice.ok("Read data in {:.1f} s".format(t1 - t0))

    #####################################################################
    #
    # MAKE PLOT
    #
    #####################################################################
    Notice.hr_header("Plotting")

    # Plot size parameters.
    wsl = 6  # Width of sidelabel, inches
    mih = 11  # Minimum plot height, inches
    fhh = 5  # File header box height, inches
    m = 0.75  # basic unit of margins, inches

    # Margins, CSS like: top, right, bottom, left.
    mt, mr, mb, ml = m, 1.5 * m, m, 1.5 * m
    mm = 2 * m  # padded margin between seismic and label

    # Determine plot dimensions. Kind of laborious and repetitive (see below).
    if cfg['plot_width']:
        seismic_width = cfg['plot_width'] - wsl - mm - ml - mr
        tpi = max([s.ntraces for s in ss]) / seismic_width
    else:
        tpi = cfg['tpi']

    if cfg['plot_height']:
        seismic_height = max(
            mih, cfg['plot_height']) - mb - 0.75 * (len(ss) - 1) - mt
        seismic_height_raw = seismic_height / len(ss)
        ips = seismic_height_raw / (s.tbasis[-1] - s.tbasis[0])
    else:
        ips = cfg['ips']

    # Width is determined by seismic width, plus sidelabel, plus margins.
    # Height is given by ips, but with a minimum of mih inches.
    if 'tslice' in direction:
        seismic_width = [s.ntraces / tpi for s in ss]
        seismic_height_raw = max([s.nxlines for s in ss]) / tpi
    else:
        seismic_width = [s.ntraces / tpi for s in ss]
        seismic_height_raw = ips * (s.tbasis[-1] - s.tbasis[0])

    w = ml + max(seismic_width) + mm + wsl + mr  # inches
    seismic_height = len(ss) * seismic_height_raw
    h_reqd = mb + seismic_height + 0.75 * (len(ss) - 1) + mt  # inches
    h = max(mih, h_reqd)

    # Calculate where to start sidelabel and seismic data.
    # Depends on whether sidelabel is on the left or right.
    if cfg['sidelabel'] == 'right':
        ssl = (ml + max(seismic_width) + mm) / w  # Start of side label (ratio)
        seismic_left = ml / w
    else:
        ssl = ml / w
        seismic_left = (ml + wsl + mm) / w

    adj = max(0, h - h_reqd) / 2
    seismic_bottom = (mb / h) + adj / h
    seismic_width_fraction = [sw / w for sw in seismic_width]
    seismic_height_fraction = seismic_height_raw / h

    # Publish some notices so user knows plot size.
    Notice.info("plot width   {:.2f} in".format(w))
    Notice.info("plot height  {:.2f} in".format(h))

    # Make the figure.
    fig = plt.figure(figsize=(w, h), facecolor='w')

    # Set the tickformat.
    tickfmt = mtick.FormatStrFormatter('%.0f')

    # Could definitely do better for default fontsize than 10.
    # Ideally would be adaptive to plot size.
    cfg['fontsize'] = cfg['fontsize'] or 10

    # Plot title.
    if cfg['title']:
        # Deal with Windows paths: \1 gets interpreted as a group by regex.
        newt = re.sub(r'\\', '@@@@@', target)
        temp = re.sub(r'_filename', newt, cfg['title'])
        title = re.sub(r'@@@', r'\\', temp)
        title_ax = fig.add_axes([ssl, 1 - mt / h, wsl / w, mt / h])
        title_ax = plotter.plot_title(title_ax,
                                      title,
                                      fs=1.4 * cfg['fontsize'],
                                      cfg=cfg)

    # Plot title.
    if cfg['subtitle']:
        date = str(datetime.date.today())
        subtitle = re.sub(r'_date', date, cfg['subtitle'])
        subtitle_ax = fig.add_axes([ssl, 1 - mt / h, wsl / w, mt / h],
                                   label='subtitle')
        title_ax = plotter.plot_subtitle(subtitle_ax,
                                         subtitle,
                                         fs=0.75 * cfg['fontsize'],
                                         cfg=cfg)

    # Plot text header.
    start = (h - 1.5 * mt - fhh) / h
    head_ax = fig.add_axes([ssl, start, wsl / w, fhh / h])
    head_ax = plotter.plot_header(head_ax,
                                  s.header,
                                  fs=9,
                                  cfg=cfg,
                                  version=__version__)

    # Plot histogram.
    # Params for histogram plot.
    pady = 0.75 / h  # 0.75 inch
    padx = 0.75 / w  # 0.75 inch
    cstrip = 0.3 / h  # color_strip height = 0.3 in
    charth = 1.25 / h  # height of charts = 1.25 in
    chartw = wsl / w - mr / w - padx  # or ml/w for left-hand sidelabel; same thing
    chartx = (ssl + padx)
    histy = 1.5 * mb / h + charth + pady
    # Plot colourbar under histogram.
    clrbar_ax = fig.add_axes([chartx, histy - cstrip, chartw, cstrip])
    clrbar_ax = plotter.plot_colourbar(clrbar_ax, cmap=cfg['cmap'])
    # Plot histogram itself.
    hist_ax = fig.add_axes([chartx, histy, chartw, charth])
    hist_ax = plotter.plot_histogram(hist_ax, s.data, tickfmt, cfg)

    # Plot spectrum.
    specy = 1.5 * mb / h
    spec_ax = fig.add_axes([chartx, specy, chartw, charth])

    try:
        colour = utils.rgb_to_hex(cfg['highlight_colour'])
        spec_ax = s.plot_spectrum(
            ax=spec_ax,
            tickfmt=tickfmt,
            ntraces=20,
            fontsize=cfg['fontsize'],
            colour=colour,
        )
    except:
        pass  # No spectrum, oh well.

    for i, line in enumerate(ss):
        # Add the seismic axis.
        ax = fig.add_axes([
            seismic_left,
            seismic_bottom + i * seismic_height_fraction + i * pady,
            seismic_width_fraction[i], seismic_height_fraction
        ])

        # Plot seismic data.
        if cfg['display'].lower() in ['vd', 'varden', 'variable', 'both']:
            im = ax.imshow(line.data.T,
                           cmap=cfg['cmap'],
                           clim=[-clip_val, clip_val],
                           extent=[
                               line.olineidx[0], line.olineidx[-1],
                               1000 * line.tbasis[-1], line.tbasis[0]
                           ],
                           aspect='auto',
                           interpolation=cfg['interpolation'])

            if np.argmin(seismic_width) == i:
                cax = utils.add_subplot_axes(ax, [1.01, 0.02, 0.01, 0.2])
                _ = plt.colorbar(im, cax=cax)

        if cfg['display'].lower() in ['wiggle', 'both']:
            ax = line.wiggle_plot(
                cfg['number'],
                direction,
                ax=ax,
                skip=cfg['skip'],
                gain=cfg['gain'],
                rgb=cfg['colour'],
                alpha=cfg['opacity'],
                lw=cfg['lineweight'],
            )

        valid = ['vd', 'varden', 'variable', 'wiggle', 'both']
        if cfg['display'].lower() not in valid:
            Notice.fail("You must specify the display: wiggle, vd, both.")
            return

        # Seismic axis annotations.
        ax.set_ylabel(utils.LABELS[line.ylabel], fontsize=cfg['fontsize'])
        ax.set_xlabel(utils.LABELS[line.xlabel],
                      fontsize=cfg['fontsize'],
                      ha='center')
        ax.tick_params(axis='both', labelsize=cfg['fontsize'] - 2)

        ax.xaxis.set_major_formatter(tickfmt)
        ax.yaxis.set_major_formatter(tickfmt)
        if ('tslice' not in direction):
            ax.set_ylim(1000 * cfg['trange'][1] or 1000 * line.tbasis[-1],
                        1000 * cfg['trange'][0])

        # Crossing point. Will only work for non-arb lines.
        try:
            ax.axvline(ss[i - 1].slineidx[0],
                       c=utils.rgb_to_hex(cfg['highlight_colour']),
                       alpha=0.5)
        except IndexError:
            pass  # Nevermind.

        # Grid, optional.
        if cfg['grid_time'] or cfg['grid_traces']:
            ax.grid()
            for l in ax.get_xgridlines():
                l.set_color(utils.rgb_to_hex(cfg['grid_colour']))
                l.set_linestyle('-')
                if cfg['grid_traces']:
                    l.set_linewidth(1)
                else:
                    l.set_linewidth(0)
                l.set_alpha(min(1, cfg['grid_alpha']))
            for l in ax.get_ygridlines():
                l.set_color(utils.rgb_to_hex(cfg['grid_colour']))
                l.set_linestyle('-')
                if cfg['grid_time']:
                    if 'tslice' in direction:
                        l.set_linewidth(1)
                    else:
                        l.set_linewidth(1.4)
                else:
                    l.set_linewidth(0)
                l.set_alpha(min(1, 2 * cfg['grid_alpha']))

        # Watermark.
        if cfg['watermark_text']:
            ax = plotter.watermark_seismic(ax, cfg)

        # Make parasitic (top) axis for labeling CDP number.
        if (s.data.ndim > 2) and ('tslice' not in direction):
            ylim = ax.get_ylim()
            par1 = ax.twiny()
            par1.spines["top"].set_position(("axes", 1.0))
            par1.plot(line.slineidx, np.zeros_like(line.slineidx), alpha=0)
            par1.set_xlabel(utils.LABELS[line.slabel],
                            fontsize=cfg['fontsize'])
            par1.set_ylim(ylim)

            # Adjust ticks
            tx = par1.get_xticks()
            newtx = [
                line.slineidx[len(line.slineidx) * (i // len(tx))]
                for i, _ in enumerate(tx)
            ]
            par1.set_xticklabels(newtx, fontsize=cfg['fontsize'] - 2)

    t2 = time.time()
    Notice.ok("Built plot in {:.1f} s".format(t2 - t1))

    #####################################################################
    #
    # SAVE FILE
    #
    #####################################################################
    Notice.hr_header("Saving")

    dname, fname, ext = utils.path_bits(target)
    outfile = cfg['outfile'] or ''
    if not os.path.splitext(outfile)[1]:
        outfile = os.path.join(cfg['outfile'] or dname, fname + '.png')

    fig.savefig(outfile)

    t3 = time.time()
    Notice.info("output file {}".format(outfile))
    Notice.ok("Saved output in {:.1f} s".format(t3 - t2))

    if cfg['stain_paper'] or cfg['coffee_rings'] or cfg['distort'] or cfg[
            'scribble']:
        fname = os.path.splitext(outfile)[0] + ".stupid.png"
        fig.savefig(fname)
    else:
        return

    #####################################################################
    #
    # SAVE STUPID FILE
    #
    #####################################################################
    Notice.hr_header("Applying the stupidity")

    stupid_image = Image.open(fname)
    if cfg['stain_paper']:
        utils.stain_paper(stupid_image)
    utils.add_rings(stupid_image, cfg['coffee_rings'])
    if cfg['scribble']:
        utils.add_scribble(stupid_image)

    # Trick to remove remaining semi-transparent pixels.
    result = Image.new("RGB", stupid_image.size, (255, 255, 255))
    result.paste(stupid_image)

    result.save(fname)

    t4 = time.time()
    Notice.info("output file {}".format(fname))
    Notice.ok("Saved stupidity in {:.1f} s".format(t4 - t3))

    return
コード例 #40
0
def plot(tc):
    """
    Constructs a multi-subplot matplotlib figure.

    Args:
        transect (TransectContainer): A transect container.
    """
    h = 15
    mw = 16  # width of main section (inches) must be div by 4
    fw = 5  # width of the feature plot (inches) must be div by 5
    n_grids = len(tc.potfield.data)

    # We will save the same figure we make, to ensure the saved figure
    # has everything in the right places. For example, see this discussion:
    # http://stackoverflow.com/questions/7906365/
    save_dpi = getattr(tc, 'save_dpi', tc.settings.get('default_dpi'))
    dpi = save_dpi or 80
    fig = plt.figure(figsize=(mw + fw + 1, 15),
                     facecolor='w',
                     edgecolor='k',
                     dpi=dpi,
                     frameon=True)

    gs = gridspec.GridSpec(h, mw + fw + 1)

    # Left-hand column.
    header = fig.add_subplot(gs[0:1, 0:mw / 2])
    description = fig.add_subplot(gs[1:3, 0:mw / 2])
    locmap = fig.add_subplot(gs[0:3, mw / 2:mw])  # Aspect = 8:3
    elevation = fig.add_subplot(gs[3, :mw])
    xsection = fig.add_subplot(gs[4:h - n_grids, :mw])
    xsec_logs = fig.add_subplot(gs[4:h - n_grids, :mw])
    potfield = fig.add_subplot(gs[h - n_grids:, :mw])

    # Right-hand column.
    log_header = fig.add_subplot(gs[0:1, -1 * fw:])
    # log_plot is dealt with by passing gs to feature_plot.plot_feature_well()

    # Adjust white space between subplots
    # ------------------------------------------------------------ #
    left = 0.05  # left side of the subplots of the figure
    right = 0.95  # right side of the subplots of the figure
    bottom = 0.05  # bottom of the subplots of the figure
    top = 0.95  # top of the subplots of the figure
    wspace = 0.05  # blank w space between subplots
    hspace = 0.1  # blank h space between subplots

    fig.subplots_adjust(left, bottom, right, top, wspace, hspace)

    bbox = {'fc': 'w', 'pad': 0, 'ec': 'none', 'alpha': 0.5}
    props = {'ha': 'left', 'va': 'center', 'bbox': bbox}

    # Header
    # ---------------------------------------------------------#
    print "Header"
    header.axis("off")
    dy = 0.2
    header.text(0.0,
                0.5 + dy,
                tc.title,
                props,
                fontsize=30,
                horizontalalignment='left',
                verticalalignment='bottom')

    # horizontal line
    header.axhline(y=0.5, xmin=0, xmax=1.25, linewidth=1.5, color='k')

    # Subtitle
    header.text(1.0,
                0.5 + dy, (tc.subtitle),
                fontsize=15,
                horizontalalignment='right',
                verticalalignment='bottom',
                weight='bold')

    descr = tc.description
    if tc.meta:
        description.text(0,
                         1.0,
                         tc.domain.upper(),
                         horizontalalignment='left',
                         verticalalignment='bottom',
                         fontsize=14)

        description.text(1.0,
                         1.0,
                         tc.velocity,
                         horizontalalignment='right',
                         verticalalignment='bottom',
                         fontsize=12)
        descr_pos = 0.8  # Where to position the rest.
    else:
        descr_pos = 1.0

    # Paragraph description
    # -----------------------------------------------------#
    description.text(0,
                     descr_pos,
                     descr,
                     horizontalalignment='left',
                     verticalalignment='top',
                     fontsize=12,
                     family='serif')

    description.axis('off')

    # Wrap text
    fig.canvas.mpl_connect('draw_event',
                           lambda event: on_draw(event, description))

    # Map
    # ---------------------------------------------------------#
    print "Locmap"
    tx, ty = tc.data.coords.xy

    res = 'h'  # c, l, i, h, f

    # Generate Basemap object.
    m = Basemap(projection='tmerc',
                lon_0=tc.locmap.mid.x,
                lat_0=tc.locmap.mid.y,
                resolution=res,
                llcrnrlon=tc.locmap.ll.x,
                llcrnrlat=tc.locmap.ll.y,
                urcrnrlon=tc.locmap.ur.x,
                urcrnrlat=tc.locmap.ur.y,
                ax=locmap)

    # Finish drawing the basemap.
    draw_basemap(m, tc)

    for layer, details in tc.locmap.layers.items():
        data = getattr(tc.locmap, layer)
        for l in data:
            line_t = utils.utm2lola(l)
            params = details.get('params', None)
            if params:
                plot_line(m, line_t, **params)
            else:
                plot_line(m, line_t, colour='k', alpha=0.5)
        if layer == "wells":
            for p in data:
                point_t = utils.utm2lola(p)
                params = details.get('params', None)
                if params:
                    plot_point(m, point_t, zorder=100, **params)
                else:
                    plot_point(m, point_t, zorder=100, colour='k', alpha=0.5)
                lo, la = point_t.xy
                x, y = m(lo, la)
                # Plot the names of wells in the xsection
                # When we have names we can also plot special symbol
                # for the feature well.

    # Plot this transect line
    line_t = utils.utm2lola(tc.data)
    plot_line(m, line_t, colour='r', lw=3)

    # Adjust border thickness
    [i.set_linewidth(8) for i in locmap.spines.itervalues()]
    [i.set_color("white") for i in locmap.spines.itervalues()]

    # Elevation and bedrock plot
    # -----------------------------------------------------------#
    print "Elevation"
    for i, geo in enumerate(tc.bedrock.data[:-1]):
        lim1 = tc.bedrock.coords[i]
        lim2 = tc.bedrock.coords[i + 1]
        idx = np.where(
            np.logical_and(tc.elevation.coords >= lim1,
                           tc.elevation.coords <= lim2))[0]
        if len(idx) > 1:
            if idx[-1] < tc.elevation.coords.size - 1:
                idx = np.append(idx, (idx[-1] + 1))
        hsv = np.array([[geo["AV_HUE"], geo["AV_SAT"],
                         geo["AV_VAL"]]]).reshape(1, 1, 3)
        color = hsv_to_rgb(hsv / 255.)

        elevation.bar(tc.elevation.coords[idx],
                      tc.elevation.data[idx],
                      width=1.0,
                      linewidth=0,
                      color=color.flatten())

        elevation.plot(tc.elevation.coords[idx],
                       tc.elevation.data[idx],
                       lw=0.5,
                       color='k')

    max_height = np.amax(tc.elevation.all_data)

    elevation.set_ylim((0, max_height))
    elevation.set_xlim(tc.extents[:2])
    elevation.set_yticks([0, int(max_height), int(np.amax(tc.elevation.data))])
    elevation.set_xticklabels([])
    elevation.tick_params(axis='y', which='major', labelsize=8)
    elevation.patch.set_alpha(0.1)
    elevation.set_ylabel("Elevation [m]", fontsize=8)
    elevation.grid(True)
    elevation.tick_params(axis='x', which='major', labelsize=0)
    elevation.xaxis.grid(True, which='major')
    elevation.text(0.01,
                   0.8,
                   "Elevation",
                   props,
                   va='bottom',
                   fontsize=11,
                   weight='bold',
                   transform=elevation.transAxes)
    elevation.text(0.01,
                   0.75,
                   "Surface geology",
                   props,
                   va='top',
                   fontsize=10,
                   transform=elevation.transAxes)
    elevation.set_frame_on(False)
    for tick in elevation.get_xaxis().get_major_ticks():
        tick.set_pad(-8.)
        tick.label1 = tick._get_text1()

    # Seismic cross section
    # ------------------------------------------------------------#
    print "Seismic"
    for coords, data in zip(tc.seismic.coords, tc.seismic.data):

        max_z = data["traces"].shape[0] * data["sample_interval"]
        im = xsection.imshow(data["traces"],
                             extent=[
                                 np.amin(coords) / 1000.0,
                                 np.amax(coords) / 1000.0, max_z, 0
                             ],
                             aspect="auto",
                             cmap=tc.seismic_cmap)

    # Horizons
    colours = ['b', 'g', 'orange', 'c', 'magenta', 'pink']
    for i, (horizon, data) in enumerate(tc.horizons.data.items()):

        coords = tc.horizons.coords[horizon]
        xsection.scatter(coords / 1000, data, color=colours[i], marker='.')

        # labels
        xsection.text(0.01,
                      0.025 * (i + 1),
                      horizon,
                      transform=xsection.transAxes,
                      ha='left',
                      color=colours[i],
                      va='center',
                      fontsize=12)

    # Axes etc.
    plot_axis = [
        tc.extents[0] / 1000., tc.extents[1] / 1000., tc.extents[2],
        tc.extents[3]
    ]
    xsection.axis(plot_axis)
    xsection.set_xticklabels([])
    if tc.domain.lower() in ['depth', 'd', 'z']:
        xsection.set_ylabel("Depth [m]", fontsize=8)
    else:
        xsection.set_ylabel("TWTT [ms]", fontsize=8)
    xsection.tick_params(axis='y', which='major', labelsize=8)
    xsection.tick_params(axis='x', which='major', labelsize=0)
    xsection.yaxis.grid(True, which='major')
    xsection.xaxis.grid(True, which='major')
    xsection.set_frame_on(False)

    # Seismic colorbar
    colorbar_ax = add_subplot_axes(xsection, [0.975, 0.025, 0.01, 0.1])
    fig.colorbar(im, cax=colorbar_ax)
    colorbar_ax.text(0.5,
                     0.9,
                     "+",
                     transform=colorbar_ax.transAxes,
                     ha='center',
                     color='white',
                     va='center',
                     fontsize=12)
    colorbar_ax.text(0.5,
                     0.15,
                     "-",
                     transform=colorbar_ax.transAxes,
                     color='k',
                     ha='center',
                     va='center',
                     fontsize=16)
    colorbar_ax.set_axis_off()

    # Title
    xsection.text(0.01,
                  0.99,
                  "Seismic",
                  color='k',
                  ha='left',
                  va='top',
                  fontsize=12,
                  weight='bold',
                  transform=xsec_logs.transAxes)
    # Potential field data
    # -----------------------------------------------------------#
    print "Potfields"
    for i, (field, payload) in enumerate(tc.potfield.data.items()):
        bot = 1 - (i + 1.) / n_grids
        height = (1. / n_grids) - 0.05
        rect = [0, bot, 1, height]
        this_ax = add_subplot_axes(potfield, rect)

        sc = this_ax.scatter(payload['coords'],
                             payload['data'],
                             c=payload['colour'],
                             cmap=payload['cmap'],
                             s=1,
                             edgecolor='',
                             vmin=-50,
                             vmax=150)

        this_ax.set_xlim(tc.extents[:2])
        this_ax.set_frame_on(False)
        this_ax.set_xticks([])
        this_ax.tick_params(axis='y', which='major', labelsize=8)
        this_ax.grid(True)
        scale = payload['scale']
        if scale:
            this_ax.set_ylim(float(scale[1]), float(scale[0]))

        if payload['colour_is_file']:
            tcol = '#555555'
        else:
            tcol = payload['colour']

        this_ax.text(0.01,
                     0.01,
                     field,
                     ha='left',
                     va='bottom',
                     fontsize=10,
                     color=tcol,
                     transform=this_ax.transAxes)

        # potfield colorbar
        # TODO: This doesn't work.
        if payload.get('cmap'):
            # pf_cbar_ax = add_subplot_axes(this_ax, [0.975, 0.1, 0.01, 0.8])
            # fig.colorbar(sc, cax=pf_cbar_ax)
            # pf_cbar_ax.set_axis_off()
            pass

    potfield.axis(plot_axis)
    potfield.set_frame_on(False)
    potfield.set_yticks([])
    potfield.xaxis.grid(True, which='major')
    potfield.tick_params(axis='x', which='major', labelsize=10)
    potfield.set_xlabel("Transect range [km]", fontsize=10, ha='center')

    potfield.text(0.01,
                  1.0,
                  "Potential fields",
                  ha='left',
                  va='top',
                  fontsize=11,
                  weight='bold',
                  color='k',
                  transform=potfield.transAxes)
    # Log overlays
    # --------------------------------------------------------#
    print "Logs"
    if tc.locmap.layers.get('wells'):
        if tc.locmap.layers['wells'].get('colour'):
            well_colour = tc.locmap.layers['wells']['colour']
        else:
            well_colour = tc.settings.get('default_colour')
            if not well_colour:
                well_colour = 'k'

    c = tc.seismic_log_colour
    for name, las, pos in zip(tc.log.names, tc.log.data, tc.log.coords):

        if name == tc.feature_well:
            alpha, lw = 0.5, 1.5
            weight = 'bold'
        else:
            alpha, lw = 0.25, 1.0
            weight = 'normal'

        if las:
            data = np.nan_to_num(las.data[tc.seismic_log])
            data /= np.amax(data)
            z = las.data['DEPT']

            if tc.domain.lower() in ['time', 'twt', 'twtt', 't']:
                dt = 0.001
                data = tc.seismic.velocity.depth2time(data, pos, dz=z, dt=dt)
                start = tc.seismic.velocity.depth2timept(las.start, pos)
                z = np.arange(0, len(data), 1) + 1000 * start  # ms

            # Some post-processing for display
            lgsc = 0.015  # hack to compress the log width
            data *= lgsc * (tc.extents[1] - tc.extents[0])
            if data.size > 0:
                data += pos - 0.5 * np.amax(data)

            xsec_logs.axvline(x=pos,
                              color=well_colour,
                              alpha=alpha,
                              lw=lw,
                              ymin=0,
                              ymax=z[-1])
            xsec_logs.plot(data, z, c, lw=0.5, alpha=0.75)
        else:
            # Need to get TD from SHP or well header sheet.
            z = [tc.extents[2] - 40]
            xsec_logs.axvline(x=pos, color=well_colour, alpha=0.25)

        elevation.axvline(x=pos, color=well_colour, alpha=alpha, lw=lw)
        potfield.axvline(x=pos / 1000, color=well_colour, alpha=alpha, lw=lw)

        # Well name annotation
        elevation.text(pos,
                       max_height - 10,
                       name,
                       color=well_colour,
                       va='top',
                       ha='center',
                       fontsize=10,
                       weight=weight)

    xsec_logs.set_xlim((tc.extents[0], tc.extents[1]))
    xsec_logs.set_ylim((tc.extents[2], tc.extents[3]))
    xsec_logs.axis("off")

    # Log type annotation, top left
    xsec_logs.text(0.01,
                   0.965,
                   tc.seismic_log + ' log',
                   color=c,
                   ha='left',
                   va='top',
                   fontsize=12,
                   transform=xsec_logs.transAxes)

    #  Feature plot
    # -----------------------------------------------------#
    if tc.feature_well:
        print "Feature well:", tc.feature_well
        log_header.text(0.0,
                        1.0, ("Well " + tc.feature_well),
                        verticalalignment='top',
                        horizontalalignment='left',
                        fontsize=14,
                        fontweight='bold')

        # horizontal line
        log_header.axhline(y=0.5, xmin=0, xmax=1.25, linewidth=1, color='k')

        plot_feature_well(tc, gs)
    else:
        Notice.warning("No feature well")

    log_header.axis("off")

    # Logo etc.
    # --------------------------------------------------------------#
    print "Logo"

    try:
        path = os.path.join(tc.data_dir, tc.settings['logo_file'])
        im = Image.open(path)
        im.thumbnail((fig.dpi, fig.dpi), Image.ANTIALIAS)
    except IOError:
        print "Image is missing", path
        im = np.zeros((1, 1, 3))

    w, h = im.size

    # We need a float array between 0-1, rather than
    # a uint8 array between 0-255
    im = np.array(im).astype(np.float) / 255

    # With newer (1.0) versions of matplotlib, you can
    # use the "zorder" kwarg to make the image overlay
    # the plot, rather than hide behind it... (e.g. zorder=10)
    fig.figimage(im, (0.95 * fig.bbox.xmax) - w, (0.96 * fig.bbox.ymax) - h)

    # Annotate config file and creation date
    plt.figtext(0.950,
                0.030,
                tc.time,
                ha="right",
                va="bottom",
                color="gray",
                size=8)
    plt.figtext(0.950,
                0.04,
                tc.config_file,
                ha="right",
                va="bottom",
                color="gray",
                size=8)

    year = datetime.datetime.now().year
    text = "$\copyright$ {} Department of Energy".format(year)
    plt.figtext(0.750,
                0.03,
                text,
                ha="left",
                va="bottom",
                color="gray",
                size=8)

    # Finish
    # --------------------------------------------------------------#
    save_file = getattr(tc, 'save_file', None)
    if save_file:
        if type(save_file) != 'str':
            # Then it's probably a bool from 'yes' or 'true' in the config
            save_file = tc.config_file.split('.')[0] + '.png'
            if save_file == 'config.png':
                save_file = 'temp.png'
        Notice.ok("Saving file " + save_file + "...", hold=True)
        plt.savefig(save_file, dpi=fig.dpi)
        Notice.ok("Done")
        Notice.warning("The displayed image is not identical to the saved one")
        plt.show()
    else:
        plt.show()
コード例 #41
0
    parser = argparse.ArgumentParser(
        description='Convert a RAD file to SEG-Y.')
    parser.add_argument(
        'filename',
        metavar='RAD file',
        type=str,
        nargs='*',
        default='./*.RA[D,1,2]',
        help=
        'The path to one or more RAD files. Uses Unix-style pathname expansion. Omit to find all RAD files in current directory.'
    )
    parser.add_argument(
        '-o',
        '--out',
        metavar='output file',
        type=str,
        nargs='?',
        default='',
        help=
        'The path to an output file. Default: same as input file, but with the nominal frequency and sgy file extension.'
    )
    args = parser.parse_args()

    Notice.header("This is rad2segy. Stand back.")
    for f in args.filename:
        Notice.info("{}".format(f), hold=True)
        Notice.ok(" >>> ", hold=True)
        outfile = rad2segy(f, args.out)
        Notice.info(outfile)
    Notice.header("Done")
コード例 #42
0
def plot_feature_well(tc, gs):
    """
    Plotting function for the feature well.

    Args:
        tc (TransectContainer): The container for the main plot.
        log (axis): A matplotlib axis.
        gs (GridSpec): A matplotlib gridspec.
    """
    fname = tc.settings['curve_display']

    logs = tc.log.get(tc.feature_well)

    if not logs:
        # There was no data for this well, so there won't be a feature plot.
        Notice.fail("There's no well data for feature well " + tc.feature_well)
        return gs

    Z = logs.data['DEPT']

    curves = [
        'GR', 'DT', 'DPHI_SAN', 'NPHI_SAN', 'DTS', 'RT_HRLT', 'RHOB', 'DRHO'
    ]

    window = tc.settings.get('curve_smooth_window') or 51
    ntracks = 5
    lw = 1.0
    smooth = True
    naxes = 0
    ncurv_per_track = np.zeros(ntracks)

    if getattr(tc.log, 'striplog', None):
        ncurv_per_track[0] = 1

    for curve in curves:
        naxes += 1
        params = get_curve_params(curve, fname)
        ncurv_per_track[params['track']] += 1

    axss = plt.subplot(gs[2:, -5])
    axs0 = [axss, axss.twiny()]
    axs1 = [plt.subplot(gs[2:, -4])]
    axs2 = [plt.subplot(gs[2:, -3])]
    axs3 = [plt.subplot(gs[2:, -2])]
    axs4 = [plt.subplot(gs[2:, -1])]

    axs = [axs0, axs1, axs2, axs3, axs4]

    if getattr(tc.log, 'striplog', None):
        legend = Legend.default()
        try:
            logs.striplog[tc.log.striplog].plot_axis(axs0[0], legend=legend)
        except KeyError:
            # In fact, this striplog doesn't exist.
            Notice.fail("There is no such striplog" + tc.log.striplog)
            # And move on...

    axs0[0].set_ylim([Z[-1], 0])
    label_shift = np.zeros(len(axs))

    for curve in curves:
        try:
            values = logs.data[curve]
        except ValueError:
            Notice.warning("Curve not present: " + curve)
            values = np.empty_like(Z)
            values[:] = np.nan

        params = get_curve_params(curve, fname)
        i = params['track']

        j = 0

        label_shift[i] += 1

        linOrlog = params['logarithmic']

        sxticks = np.array(params['xticks'])
        xticks = np.array(sxticks, dtype=float)
        whichticks = 'major'

        if linOrlog == 'log':
            midline = np.log(np.mean(xticks))
            xpos = midline
            whichticks = 'minor'
        else:
            midline = np.mean(xticks)
            xpos = midline

        if smooth:
            values = utils.rolling_median(values, window)

        if curve == 'GR':
            j = 1  # second axis in first track
            label_shift[i] = 1
            if params['fill_left_cond']:
                # do the fill for the lithology track
                axs[i][j].fill_betweenx(Z,
                                        params['xleft'],
                                        values,
                                        facecolor=params['fill_left'],
                                        alpha=1.0,
                                        zorder=11)

        if (curve == 'DPHI_SAN') and params['fill_left_cond']:
            # do the fill for the neutron porosity track
            try:
                nphi = utils.rolling_median(logs.data['NPHI_SAN'], window)
            except ValueError:
                Notice.warning("No NPHI in this well")
                nphi = np.empty_like(Z)
                nphi[:] = np.nan
            axs[i][j].fill_betweenx(Z,
                                    nphi,
                                    values,
                                    where=nphi >= values,
                                    facecolor=params['fill_left'],
                                    alpha=1.0,
                                    zorder=11)

            axs[i][j].fill_betweenx(Z,
                                    nphi,
                                    values,
                                    where=nphi <= values,
                                    facecolor='#8C1717',
                                    alpha=0.5,
                                    zorder=12)

        if curve == 'DRHO':
            blk_drho = 3.2
            values += blk_drho  # this is a hack to get DRHO on RHOB scale
            axs[i][j].fill_betweenx(Z,
                                    blk_drho,
                                    values,
                                    where=nphi <= values,
                                    facecolor='#CCCCCC',
                                    alpha=0.5,
                                    zorder=12)

        # fill right
        if params['fill_right_cond']:

            axs[i][j].fill_betweenx(Z,
                                    values,
                                    params['xright'],
                                    facecolor=params['fill_right'],
                                    alpha=1.0,
                                    zorder=12)

        # plot curve
        axs[i][j].plot(values, Z, color=params['hexcolor'], lw=lw, zorder=13)

        # set scale of curve
        axs[i][j].set_xlim([params['xleft'], params['xright']])

        # ------------------------------------------------- #
        # curve labels
        # ------------------------------------------------- #

        trans = transforms.blended_transform_factory(axs[i][j].transData,
                                                     axs[i][j].transData)

        magic = -Z[-1] / 12.
        axs[i][j].text(xpos,
                       magic - (magic / 4) * (label_shift[i] - 1),
                       curve,
                       horizontalalignment='center',
                       verticalalignment='bottom',
                       fontsize=12,
                       color=params['hexcolor'],
                       transform=trans)
        # curve units
        units = '${}$'.format(params['units'])
        if label_shift[i] <= 1:
            axs[i][j].text(xpos,
                           magic * 0.5,
                           units,
                           horizontalalignment='center',
                           verticalalignment='top',
                           fontsize=12,
                           color='k',
                           transform=trans)

        # ------------------------------------------------- #
        # scales and tickmarks
        # ------------------------------------------------- #

        axs[i][j].set_xscale(linOrlog)
        axs[i][j].set_ylim([Z[-1], 0])
        axs[i][j].axes.xaxis.set_ticks(xticks)
        axs[i][j].axes.xaxis.set_ticklabels(sxticks, fontsize=8)
        for label in axs[i][j].axes.xaxis.get_ticklabels():
            label.set_rotation(90)
        axs[i][j].tick_params(axis='x', direction='out')
        axs[i][j].xaxis.tick_top()
        axs[i][j].xaxis.set_label_position('top')
        axs[i][j].xaxis.grid(True,
                             which=whichticks,
                             linewidth=0.25,
                             linestyle='-',
                             color='0.75',
                             zorder=100)

        axs[i][j].yaxis.grid(True,
                             which=whichticks,
                             linewidth=0.25,
                             linestyle='-',
                             color='0.75',
                             zorder=100)
        axs[i][j].yaxis.set_ticks(np.arange(0, max(Z), 100))
        if i != 0:
            axs[i][j].set_yticklabels("")

    # ------------------------------------------------- #
    # End of curve loop
    # ------------------------------------------------- #

    # Add Depth label
    axs[0][0].text(0,
                   1.05,
                   'MD\n$m$',
                   fontsize='10',
                   horizontalalignment='center',
                   verticalalignment='center',
                   transform=axs[0][0].transAxes)

    axs[0][0].axes.yaxis.get_ticklabels()
    axs[0][0].axes.xaxis.set_ticklabels('')

    for label in axs[0][0].axes.yaxis.get_ticklabels():
        label.set_rotation(90)
        label.set_fontsize(10)

    for label in axs[1][0].axes.xaxis.get_ticklabels():
        label.set_rotation(90)
        label.set_fontsize(10)

    # Add Tops
    try:
        if os.path.exists(tc.tops_file):
            tops = utils.get_tops(tc.tops_file)
            topx = get_curve_params('DT', fname)
            topmidpt = np.amax((topx)['xright'])

            # plot tops
            for i in range(ntracks):

                for mkr, depth in tops.iteritems():

                    # draw horizontal bars at the top position
                    axs[i][-1].axhline(y=depth,
                                       xmin=0.01,
                                       xmax=.99,
                                       color='b',
                                       lw=2,
                                       alpha=0.5,
                                       zorder=100)

                    # draw text box at the right edge of the last track
                    axs[-1][-1].text(x=topmidpt,
                                     y=depth,
                                     s=mkr,
                                     alpha=0.5,
                                     color='k',
                                     fontsize='8',
                                     horizontalalignment='center',
                                     verticalalignment='center',
                                     zorder=10000,
                                     bbox=dict(facecolor='white',
                                               edgecolor='k',
                                               alpha=0.25,
                                               lw=0.25),
                                     weight='light')

    except AttributeError:
        Notice.warning("No tops for this well")
    except TypeError:
        # We didn't get a tops file so move along.
        print "No tops for this well"

    return gs
コード例 #43
0
ファイル: plot.py プロジェクト: stenotech/geotransect
def plot(tc):
    """
    Constructs a multi-subplot matplotlib figure.

    Args:
        transect (TransectContainer): A transect container.
    """
    h = 15
    mw = 16  # width of main section (inches) must be div by 4
    fw = 5   # width of the feature plot (inches) must be div by 5
    n_grids = len(tc.potfield.data)

    # We will save the same figure we make, to ensure the saved figure
    # has everything in the right places. For example, see this discussion:
    # http://stackoverflow.com/questions/7906365/
    save_dpi = getattr(tc, 'save_dpi', tc.settings.get('default_dpi'))
    dpi = save_dpi or 80
    fig = plt.figure(figsize=(mw + fw + 1, 15),
                     facecolor='w',
                     edgecolor='k',
                     dpi=dpi,
                     frameon=True)

    gs = gridspec.GridSpec(h, mw + fw + 1)

    # Left-hand column.
    header = fig.add_subplot(gs[0:1, 0:mw/2])
    description = fig.add_subplot(gs[1:3, 0:mw/2])
    locmap = fig.add_subplot(gs[0:3, mw/2:mw])  # Aspect = 8:3
    elevation = fig.add_subplot(gs[3, :mw])
    xsection = fig.add_subplot(gs[4:h-n_grids, :mw])
    xsec_logs = fig.add_subplot(gs[4:h-n_grids, :mw])
    potfield = fig.add_subplot(gs[h-n_grids:, :mw])

    # Right-hand column.
    log_header = fig.add_subplot(gs[0:1, -1*fw:])
    # log_plot is dealt with by passing gs to feature_plot.plot_feature_well()

    # Adjust white space between subplots
    # ------------------------------------------------------------ #
    left = 0.05     # left side of the subplots of the figure
    right = 0.95    # right side of the subplots of the figure
    bottom = 0.05   # bottom of the subplots of the figure
    top = 0.95      # top of the subplots of the figure
    wspace = 0.05   # blank w space between subplots
    hspace = 0.1   # blank h space between subplots

    fig.subplots_adjust(left, bottom, right, top, wspace, hspace)

    bbox = {'fc': 'w', 'pad': 0, 'ec': 'none', 'alpha': 0.5}
    props = {'ha': 'left', 'va': 'center', 'bbox': bbox}

    # Header
    # ---------------------------------------------------------#
    print "Header"
    header.axis("off")
    dy = 0.2
    header.text(0.0, 0.5 + dy, tc.title,
                props,
                fontsize=30,
                horizontalalignment='left',
                verticalalignment='bottom'
                )

    # horizontal line
    header.axhline(y=0.5,
                   xmin=0,
                   xmax=1.25,
                   linewidth=1.5,
                   color='k')

    # Subtitle
    header.text(1.0, 0.5 + dy,
                (tc.subtitle),
                fontsize=15,
                horizontalalignment='right',
                verticalalignment='bottom', weight='bold')

    descr = tc.description
    if tc.meta:
        description.text(0, 1.0,
                         tc.domain.upper(),
                         horizontalalignment='left',
                         verticalalignment='bottom',
                         fontsize=14
                         )

        description.text(1.0, 1.0,
                         tc.velocity,
                         horizontalalignment='right',
                         verticalalignment='bottom',
                         fontsize=12
                         )
        descr_pos = 0.8  # Where to position the rest.
    else:
        descr_pos = 1.0

    # Paragraph description
    # -----------------------------------------------------#
    description.text(0, descr_pos,
                     descr,
                     horizontalalignment='left',
                     verticalalignment='top',
                     fontsize=12, family='serif'
                     )

    description.axis('off')

    # Wrap text
    fig.canvas.mpl_connect('draw_event', lambda event: on_draw(event, description))

    # Map
    # ---------------------------------------------------------#
    print "Locmap"
    tx, ty = tc.data.coords.xy

    res = 'h'   # c, l, i, h, f

    # Generate Basemap object.
    m = Basemap(projection='tmerc',
                lon_0=tc.locmap.mid.x, lat_0=tc.locmap.mid.y,
                resolution=res,
                llcrnrlon=tc.locmap.ll.x, llcrnrlat=tc.locmap.ll.y,
                urcrnrlon=tc.locmap.ur.x, urcrnrlat=tc.locmap.ur.y,
                ax=locmap)

    # Finish drawing the basemap.
    draw_basemap(m, tc)

    for layer, details in tc.locmap.layers.items():
        data = getattr(tc.locmap, layer)
        for l in data:
            line_t = utils.utm2lola(l)
            params = details.get('params', None)
            if params:
                plot_line(m, line_t, **params)
            else:
                plot_line(m, line_t, colour='k', alpha=0.5)
        if layer == "wells":
            for p in data:
                point_t = utils.utm2lola(p)
                params = details.get('params', None)
                if params:
                    plot_point(m,
                               point_t,
                               zorder=100,
                               **params)
                else:
                    plot_point(m,
                               point_t,
                               zorder=100,
                               colour='k',
                               alpha=0.5)
                lo, la = point_t.xy
                x, y = m(lo, la)
                # Plot the names of wells in the xsection
                # When we have names we can also plot special symbol
                # for the feature well.

    # Plot this transect line
    line_t = utils.utm2lola(tc.data)
    plot_line(m, line_t, colour='r', lw=3)

    # Adjust border thickness
    [i.set_linewidth(8) for i in locmap.spines.itervalues()]
    [i.set_color("white") for i in locmap.spines.itervalues()]

    # Elevation and bedrock plot
    # -----------------------------------------------------------#
    print "Elevation"
    for i, geo in enumerate(tc.bedrock.data[:-1]):
        lim1 = tc.bedrock.coords[i]
        lim2 = tc.bedrock.coords[i + 1]
        idx = np.where(np.logical_and(tc.elevation.coords >= lim1,
                                      tc.elevation.coords <= lim2))[0]
        if len(idx) > 1:
            if idx[-1] < tc.elevation.coords.size - 1:
                idx = np.append(idx, (idx[-1] + 1))
        hsv = np.array([[geo["AV_HUE"], geo["AV_SAT"],
                         geo["AV_VAL"]]]).reshape(1, 1, 3)
        color = hsv_to_rgb(hsv / 255.)

        elevation.bar(tc.elevation.coords[idx],
                      tc.elevation.data[idx],
                      width=1.0,
                      linewidth=0,
                      color=color.flatten())

        elevation.plot(tc.elevation.coords[idx],
                      tc.elevation.data[idx],
                      lw=0.5, color='k')

    max_height = np.amax(tc.elevation.all_data)

    elevation.set_ylim((0, max_height))
    elevation.set_xlim(tc.extents[:2])
    elevation.set_yticks([0, int(max_height),
                          int(np.amax(tc.elevation.data))])
    elevation.set_xticklabels([])
    elevation.tick_params(axis='y', which='major', labelsize=8)
    elevation.patch.set_alpha(0.1)
    elevation.set_ylabel("Elevation [m]", fontsize=8)
    elevation.grid(True)
    elevation.tick_params(axis='x', which='major', labelsize=0)
    elevation.xaxis.grid(True, which='major')
    elevation.text(0.01, 0.8,
                   "Elevation",
                   props, va='bottom',
                   fontsize=11, weight='bold',
                   transform=elevation.transAxes)
    elevation.text(0.01, 0.75,
                   "Surface geology",
                   props, va='top',
                   fontsize=10,
                   transform=elevation.transAxes)
    elevation.set_frame_on(False)
    for tick in elevation.get_xaxis().get_major_ticks():
        tick.set_pad(-8.)
        tick.label1 = tick._get_text1()

    # Seismic cross section
    # ------------------------------------------------------------#
    print "Seismic"
    for coords, data in zip(tc.seismic.coords, tc.seismic.data):

        max_z = data["traces"].shape[0] * data["sample_interval"]
        im = xsection.imshow(data["traces"],
                             extent=[np.amin(coords) / 1000.0,
                                     np.amax(coords) / 1000.0,
                                     max_z, 0],
                             aspect="auto", cmap=tc.seismic_cmap)

    # Horizons
    colours = ['b', 'g', 'orange', 'c', 'magenta', 'pink']
    for i, (horizon, data) in enumerate(tc.horizons.data.items()):

        coords = tc.horizons.coords[horizon]
        xsection.scatter(coords/1000, data,
                         color=colours[i],
                         marker='.')

        # labels
        xsection.text(0.01, 0.025*(i+1),
                      horizon,
                      transform=xsection.transAxes,
                      ha='left', color=colours[i],
                      va='center', fontsize=12)

    # Axes etc.
    plot_axis = [tc.extents[0] / 1000., tc.extents[1] / 1000.,
                 tc.extents[2], tc.extents[3]]
    xsection.axis(plot_axis)
    xsection.set_xticklabels([])
    if tc.domain.lower() in ['depth', 'd', 'z']:
        xsection.set_ylabel("Depth [m]", fontsize=8)
    else:
        xsection.set_ylabel("TWTT [ms]", fontsize=8)
    xsection.tick_params(axis='y', which='major', labelsize=8)
    xsection.tick_params(axis='x', which='major', labelsize=0)
    xsection.yaxis.grid(True, which='major')
    xsection.xaxis.grid(True, which='major')
    xsection.set_frame_on(False)

    # Seismic colorbar
    colorbar_ax = add_subplot_axes(xsection, [0.975, 0.025, 0.01, 0.1])
    fig.colorbar(im, cax=colorbar_ax)
    colorbar_ax.text(0.5, 0.9, "+",
                     transform=colorbar_ax.transAxes,
                     ha='center', color='white',
                     va='center', fontsize=12)
    colorbar_ax.text(0.5, 0.15, "-",
                     transform=colorbar_ax.transAxes, color='k',
                     ha='center', va='center', fontsize=16)
    colorbar_ax.set_axis_off()

    # Title
    xsection.text(0.01, 0.99,
                  "Seismic",
                  color='k',
                  ha='left', va='top',
                  fontsize=12, weight='bold',
                  transform=xsec_logs.transAxes)
    # Potential field data
    # -----------------------------------------------------------#
    print "Potfields"
    for i, (field, payload) in enumerate(tc.potfield.data.items()):
        bot = 1 - (i+1.)/n_grids
        height = (1./n_grids) - 0.05
        rect = [0, bot, 1, height]
        this_ax = add_subplot_axes(potfield, rect)

        sc = this_ax.scatter(payload['coords'],
                        payload['data'],
                        c=payload['colour'],
                        cmap=payload['cmap'],
                        s=1,
                        edgecolor='',
                        vmin=-50, vmax=150)

        this_ax.set_xlim(tc.extents[:2])
        this_ax.set_frame_on(False)
        this_ax.set_xticks([])
        this_ax.tick_params(axis='y', which='major', labelsize=8)
        this_ax.grid(True)
        scale = payload['scale']
        if scale:
            this_ax.set_ylim(float(scale[1]), float(scale[0]))

        if payload['colour_is_file']:
            tcol = '#555555'
        else:
            tcol = payload['colour']

        this_ax.text(0.01, 0.01, field,
                     ha='left', va='bottom',
                     fontsize=10, color=tcol,
                     transform=this_ax.transAxes)

        # potfield colorbar
        # TODO: This doesn't work.
        if payload.get('cmap'):
            # pf_cbar_ax = add_subplot_axes(this_ax, [0.975, 0.1, 0.01, 0.8])
            # fig.colorbar(sc, cax=pf_cbar_ax)
            # pf_cbar_ax.set_axis_off()
            pass

    potfield.axis(plot_axis)
    potfield.set_frame_on(False)
    potfield.set_yticks([])
    potfield.xaxis.grid(True, which='major')
    potfield.tick_params(axis='x', which='major', labelsize=10)
    potfield.set_xlabel("Transect range [km]", fontsize=10, ha='center')

    potfield.text(0.01, 1.0, "Potential fields",
                  ha='left', va='top',
                  fontsize=11, weight='bold', color='k',
                  transform=potfield.transAxes)
    # Log overlays
    # --------------------------------------------------------#
    print "Logs"
    if tc.locmap.layers.get('wells'):
        if tc.locmap.layers['wells'].get('colour'):
            well_colour = tc.locmap.layers['wells']['colour']
        else:
            well_colour = tc.settings.get('default_colour')
            if not well_colour:
                well_colour = 'k'

    c = tc.seismic_log_colour
    for name, las, pos in zip(tc.log.names, tc.log.data, tc.log.coords):

        if name == tc.feature_well:
            alpha, lw = 0.5, 1.5
            weight = 'bold'
        else:
            alpha, lw = 0.25, 1.0
            weight = 'normal'

        if las:
            data = np.nan_to_num(las.data[tc.seismic_log])
            data /= np.amax(data)
            z = las.data['DEPT']

            if tc.domain.lower() in ['time', 'twt', 'twtt', 't']:
                dt = 0.001
                data = tc.seismic.velocity.depth2time(data, pos, dz=z, dt=dt)
                start = tc.seismic.velocity.depth2timept(las.start, pos)
                z = np.arange(0, len(data), 1) + 1000*start  # ms

            # Some post-processing for display
            lgsc = 0.015  # hack to compress the log width
            data *= lgsc * (tc.extents[1] - tc.extents[0])
            if data.size > 0:
                data += pos - 0.5 * np.amax(data)

            xsec_logs.axvline(x=pos,
                              color=well_colour,
                              alpha=alpha,
                              lw=lw,
                              ymin=0,
                              ymax=z[-1])
            xsec_logs.plot(data, z, c, lw=0.5, alpha=0.75)
        else:
            # Need to get TD from SHP or well header sheet.
            z = [tc.extents[2]-40]
            xsec_logs.axvline(x=pos, color=well_colour, alpha=0.25)

        elevation.axvline(x=pos, color=well_colour, alpha=alpha, lw=lw)
        potfield.axvline(x=pos/1000, color=well_colour, alpha=alpha, lw=lw)

        # Well name annotation
        elevation.text(pos, max_height-10,
                       name,
                       color=well_colour,
                       va='top',
                       ha='center',
                       fontsize=10,
                       weight=weight)

    xsec_logs.set_xlim((tc.extents[0], tc.extents[1]))
    xsec_logs.set_ylim((tc.extents[2], tc.extents[3]))
    xsec_logs.axis("off")

    # Log type annotation, top left
    xsec_logs.text(0.01, 0.965,
                   tc.seismic_log+' log',
                   color=c,
                   ha='left', va='top',
                   fontsize=12,
                   transform=xsec_logs.transAxes)

    #  Feature plot
    # -----------------------------------------------------#
    if tc.feature_well:
        print "Feature well:", tc.feature_well
        log_header.text(0.0, 1.0,
                        ("Well " + tc.feature_well),
                        verticalalignment='top',
                        horizontalalignment='left',
                        fontsize=14,
                        fontweight='bold'
                        )

        # horizontal line
        log_header.axhline(y=0.5,
                           xmin=0,
                           xmax=1.25,
                           linewidth=1,
                           color='k')

        plot_feature_well(tc, gs)
    else:
        Notice.warning("No feature well")

    log_header.axis("off")

    # Logo etc.
    # --------------------------------------------------------------#
    print "Logo"

    try:
        path = os.path.join(tc.data_dir, tc.settings['logo_file'])
        im = Image.open(path)
        im.thumbnail((fig.dpi, fig.dpi), Image.ANTIALIAS)
    except IOError:
        print "Image is missing", path
        im = np.zeros((1, 1, 3))

    w, h = im.size

    # We need a float array between 0-1, rather than
    # a uint8 array between 0-255
    im = np.array(im).astype(np.float) / 255

    # With newer (1.0) versions of matplotlib, you can
    # use the "zorder" kwarg to make the image overlay
    # the plot, rather than hide behind it... (e.g. zorder=10)
    fig.figimage(im, (0.95*fig.bbox.xmax) - w, (0.96*fig.bbox.ymax) - h)

    # Annotate config file and creation date
    plt.figtext(0.950, 0.030, tc.time,
                ha="right", va="bottom", color="gray", size=8)
    plt.figtext(0.950, 0.04, tc.config_file,
                ha="right", va="bottom", color="gray", size=8)

    year = datetime.datetime.now().year
    text = "$\copyright$ {} Department of Energy".format(year)
    plt.figtext(0.750, 0.03, text,
                ha="left", va="bottom", color="gray", size=8)

    # Finish
    # --------------------------------------------------------------#
    save_file = getattr(tc, 'save_file', None)
    if save_file:
        if type(save_file) != 'str':
            # Then it's probably a bool from 'yes' or 'true' in the config
            save_file = tc.config_file.split('.')[0] + '.png'
            if save_file == 'config.png':
                save_file = 'temp.png'
        Notice.ok("Saving file "+save_file+"...", hold=True)
        plt.savefig(save_file, dpi=fig.dpi)
        Notice.ok("Done")
        Notice.warning("The displayed image is not identical to the saved one")
        plt.show()
    else:
        plt.show()
コード例 #44
0
ファイル: containers.py プロジェクト: stenotech/geotransect
    def update(self, transect, flat=False):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
            flat (Bool): Reads data into a flat list instead of
                         sorting by files.
        """
        Notice.info("Updating " + self.__class__.__name__)

        self.reset_data()

        # Preprocessing
        prepared = prep(transect.buffer(self.settings['buffer']))

        # Get intersecting points
        points = filter(prepared.contains, self.lookup.keys())

        # Lookup for grouping traces into segy files
        count = 0
        file_lookup = {}
        for point in points:
            meta = self.lookup[point]
            count += 1
            f = meta["segyfile"]
            if f in file_lookup:
                proj_d = transect.project(point)
                if proj_d:
                    file_lookup[f]["pos"].append(proj_d)
                    file_lookup[f]["trace"].append(meta["trace"])
                    file_lookup[f]["point"].append(point)
            else:
                file_lookup[f] = {}
                file_lookup[f]["trace"] = [meta["trace"]]
                file_lookup[f]["pos"] = [transect.project(point)]
                file_lookup[f]["point"] = [point]

        # Read in the chunks from the segy file
        self.files = []
        for segyfile in file_lookup.keys():
            self.files.append(os.path.basename(segyfile))
            segy = readSEGY(segyfile, unpack_trace_headers=True)
            traces = file_lookup[segyfile]["trace"]
            coords = file_lookup[segyfile]["pos"]
            points = file_lookup[segyfile]["point"]

            # Get the sort order.
            idx = sorted(range(len(traces)), key=lambda k: traces[k])
            idx = filter(None, idx)

            coords = [coords[i] for i in idx]
            data = [segy.traces[traces[i]] for i in idx]

            if flat:
                self.data += data
                self.coords += coords
            else:
                self.data.append(data)
                self.coords.append(coords)
コード例 #45
0
ファイル: pixiv.py プロジェクト: qwqqq6/PixivSpider
 def __init__(self, core=None, notice=None):
     self.core = core if core is not None else Core()
     self.info = notice if notice is not None else Notice()
コード例 #46
0
ファイル: seisplot.py プロジェクト: Aleks-Canstrat/seisplot
def main(target, cfg):
    """
    Puts everything together.
    """
    t0 = time.time()

    # Read the file.
    section = readSEGY(target, unpack_headers=True)

    # Calculate some things.
    # NB Getting nsamples and dt from the first trace assumes that all
    # traces are the same length, which is not a safe assumption in SEGY v2.
    ninlines = section.traces[-1].header.trace_sequence_number_within_line
    last_tr = section.traces[-1].header.trace_sequence_number_within_segy_file
    nxlines = last_tr / ninlines

    nsamples = section.traces[0].header.number_of_samples_in_this_trace
    dt = section.traces[0].header.sample_interval_in_ms_for_this_trace
    ntraces = len(section.traces)
    tbase = 0.001 * np.arange(0, nsamples * dt, dt)
    tstart = 0
    tend = np.amax(tbase)

    # Make the data array.
    data = np.vstack([t.data for t in section.traces]).T

    threed = False
    if nxlines > 1:  # Then it's a 3D and `data` is an ensemble.
        threed = True
        cube = np.reshape(data.T, (ninlines, nxlines, nsamples))
        l = cfg['number']
        if cfg['direction'].lower()[0] == 'i':
            direction = 'inline'
            ntraces = nxlines
            l *= ninlines if (l < 1) else 1
            data = cube[l, :, :].T
        else:
            direction = 'xline'
            ntraces = ninlines
            l *= nxlines if (l < 1) else 1
            data = cube[:, l, :].T

    # Collect some other data. Use a for loop because there are several.
    elev, esp, ens, tsq = [], [], [], []
    for i, trace in enumerate(section.traces):
        elev.append(trace.header.receiver_group_elevation)
        esp.append(trace.header.energy_source_point_number)
        tsq.append(trace.header.trace_sequence_number_within_line)

        if threed:
            trs = []
            if direction == 'inline':
                cdp_label_text = 'Crossline number'
                trace_label_text = 'Trace number'
                ens.append(trace.header.for_3d_poststack_data_this_field_is_for_cross_line_number)
                trs.append(trace.header.for_3d_poststack_data_this_field_is_for_in_line_number)
            else:
                cdp_label_text = 'Inline number'
                trace_label_text = 'Trace number'
                ens.append(trace.header.for_3d_poststack_data_this_field_is_for_in_line_number)
                trs.append(trace.header.for_3d_poststack_data_this_field_is_for_cross_line_number)
            line_no = min(trs)
        else:
            cdp_label_text = 'CDP number'
            trace_label_text = 'Trace number'
            ens.append(trace.header.ensemble_number)
        min_tr, max_tr = 0, ntraces

    traces = (min_tr, max_tr)

    clip_val = np.percentile(data, cfg['percentile'])

    # Notify user of parameters
    Notice.info("n_traces   {}".format(ntraces))
    Notice.info("n_samples  {}".format(nsamples))
    Notice.info("dt         {}".format(dt))
    Notice.info("t_start    {}".format(tstart))
    Notice.info("t_end      {}".format(tend))
    Notice.info("max_val    {}".format(np.amax(data)))
    Notice.info("min_val    {}".format(np.amin(data)))
    Notice.info("clip_val   {}".format(clip_val))

    t1 = time.time()
    Notice.ok("Read data in {:.1f} s".format(t1-t0))

    #####################################################################
    #
    # MAKE PLOT
    #
    #####################################################################
    Notice.hr_header("Plotting")

    ##################################
    # Plot size parameters
    # Some constants
    fs = cfg['fontsize']
    wsl = 6  # Width of sidelabel, inches
    mih = 12  # Minimum plot height, inches
    fhh = 5  # File header box height, inches
    m = 0.5  # basic unit of margins, inches

    # Margins, CSS like: top, right, bottom, left.
    mt, mr, mb, ml = m,  2 * m, m, 2 * m
    mm = m  # padded margin between seismic and label

    # Width is determined by seismic width, plus sidelabel, plus margins.
    seismic_width = ntraces / cfg['tpi']
    w = ml + seismic_width + mm + wsl + mr  # inches

    # Height is given by ips, but with a minimum of mih inches
    seismic_height = cfg['ips'] * (tbase[-1] - tbase[0]) / 1000
    h_reqd = mb + seismic_height + mt  # inches
    h = max(mih, h_reqd)

    # Calculate where to start sidelabel and seismic data.
    # Depends on whether sidelabel is on the left or right.
    if cfg['sidelabel'] == 'right':
        ssl = (ml + seismic_width + mm) / w  # Start of side label (ratio)
        seismic_left = ml / w
    else:
        ssl = ml / w
        seismic_left = (ml + wsl + mm) / w

    adj = max(0, h - h_reqd) / 2
    seismic_bottom = (mb / h) + adj / h
    seismic_width_fraction = seismic_width / w
    seismic_height_fraction = seismic_height / h

    # Publish some notices so user knows plot size.
    Notice.info("Width of plot   {} in".format(w))
    Notice.info("Height of plot  {} in".format(h))

    ##################################
    # Make the figure.
    fig = plt.figure(figsize=(w, h), facecolor='w')

    # Add the main seismic axis.
    ax = fig.add_axes([seismic_left,
                       seismic_bottom,
                       seismic_width_fraction,
                       seismic_height_fraction
                       ])

    # make parasitic axes for labeling CDP number
    par1 = ax.twiny()
    par1.spines["top"].set_position(("axes", 1.0))
    tickfmt = mtick.FormatStrFormatter('%.0f')
    par1.plot(ens, np.zeros_like(ens))
    par1.set_xlabel(cdp_label_text, fontsize=fs-2)
    par1.set_xticklabels(par1.get_xticks(), fontsize=fs-2)
    par1.xaxis.set_major_formatter(tickfmt)

    # Plot title
    title_ax = fig.add_axes([ssl, 1-mt/h, wsl/w, mt/(h)])
    title_ax = plotter.plot_title(title_ax, target, fs=1.5*fs, cfg=cfg)
    if threed:
        title_ax.text(0.0, 0.0, '{} {}'.format(direction.title(), line_no))

    # Plot text header.
    s = section.textual_file_header.decode()
    start = (h - 1.5*mt - fhh) / h
    head_ax = fig.add_axes([ssl, start, wsl/w, fhh/h])
    head_ax = plotter.plot_header(head_ax, s, fs=fs-1, cfg=cfg)

    # Plot histogram.
    # Params for histogram plot
    pady = 0.75 / h  # 0.75 inch
    padx = 0.75 / w   # 0.75 inch
    cstrip = 0.3/h   # color_strip height = 0.3 in
    charth = 1.5/h   # height of charts = 1.5 in
    chartw = wsl/w - mr/w - padx  # or ml/w for left-hand sidelabel; same thing
    chartx = (ssl + padx)
    histy = 1.5 * mb/h + charth + pady
    # Plot colourbar under histogram
    clrbar_ax = fig.add_axes([chartx, histy - cstrip, chartw, cstrip])
    clrbar_ax = plotter.plot_colourbar(clrbar_ax, cmap=cfg['cmap'])
    # Plot histogram itself
    hist_ax = fig.add_axes([chartx, histy, chartw, charth])
    hist_ax = plotter.plot_histogram(hist_ax,
                                     data,
                                     tickfmt,
                                     percentile=cfg['percentile'],
                                     fs=fs)

    # Plot spectrum.
    specy = 1.5 * mb/h
    spec_ax = fig.add_axes([chartx, specy, chartw, charth])

    try:
        spec_ax = plotter.plot_spectrum(spec_ax,
                                        data,
                                        dt,
                                        tickfmt,
                                        ntraces=20,
                                        fontsize=fs)
    except:
        pass

    # Plot seismic data.
    if cfg['display'].lower() in ['vd', 'varden', 'variable']:
        _ = ax.imshow(data,
                      cmap=cfg['cmap'],
                      clim=[-clip_val, clip_val],
                      extent=[0, ntraces, tbase[-1], tbase[0]],
                      aspect='auto'
                      )

    elif cfg['display'].lower() == 'wiggle':
        ax = plotter.wiggle_plot(ax,
                                 data,
                                 tbase,
                                 ntraces,
                                 skip=cfg['skip'],
                                 gain=cfg['gain'],
                                 rgb=cfg['colour'],
                                 alpha=cfg['opacity'],
                                 lw=cfg['lineweight']
                                 )
        ax.set_ylim(ax.get_ylim()[::-1])

    elif cfg['display'].lower() == 'both':
        # variable density goes on first
        _ = ax.imshow(data,
                      cmap=cfg['cmap'],
                      clim=[-clip_val, clip_val],
                      extent=[0, ntraces, tbase[-1], tbase[0]],
                      aspect='auto'
                      )

        # wiggle plots go on top
        ax = plotter.wiggle_plot(ax,
                                 data,
                                 tbase,
                                 ntraces,
                                 skip=cfg['skip'],
                                 gain=cfg['gain'],
                                 rgb=cfg['colour'],
                                 alpha=cfg['opacity'],
                                 lw=cfg['lineweight']
                                 )
        # ax.set_ylim(ax.get_ylim()[::-1])

    else:
        Notice.fail("You need to specify the type of display: wiggle or vd")

    # Seismic axis annotations.
    ax = plotter.decorate_seismic(ax, traces, trace_label_text, tickfmt, cfg)

    # Watermark.
    if cfg['watermark_text']:
        Notice.info("Adding watermark")
        ax = plotter.watermark_seismic(ax, cfg)

    t2 = time.time()
    Notice.ok("Built plot in {:.1f} s".format(t2-t1))

    #####################################################################
    #
    # SAVE FILE
    #
    #####################################################################
    Notice.hr_header("Saving")

    if cfg['stain_paper'] or cfg['coffee_rings'] or cfg['distort'] or cfg['scribble']:
        stupid = True
    else:
        stupid = False

    s = "Saved image file {} in {:.1f} s"
    if cfg['outfile']:

        if os.path.isfile(cfg['outfile']):
            outfile = cfg['outfile']
        else:  # is directory
            stem, ext = os.path.splitext(os.path.split(target)[1])
            outfile = os.path.join(cfg['outfile'], stem + '.png')

        stem, _ = os.path.splitext(outfile)  # Needed for stupidity.
        fig.savefig(outfile)
        t3 = time.time()
        Notice.ok(s.format(outfile, t3-t2))
    else:  # Do the default: save a PNG in the same dir as the target.
        stem, _ = os.path.splitext(target)
        fig.savefig(stem)
        t3 = time.time()
        Notice.ok(s.format(stem+'.png', t3-t2))

    if stupid:
        fig.savefig(stem + ".stupid.png")
    else:
        return

    #####################################################################
    #
    # SAVE STUPID FILE
    #
    #####################################################################
    Notice.hr_header("Applying the stupidity")

    stupid_image = Image.open(stem + ".stupid.png")
    if cfg['stain_paper']:
        utils.stain_paper(stupid_image)
    utils.add_rings(stupid_image, cfg['coffee_rings'])
    if cfg['scribble']:
        utils.add_scribble(stupid_image)
    stupid_image.save(stem + ".stupid.png")

    s = "Saved stupid file stupid.png in {:.1f} s"
    t4 = time.time()
    Notice.ok(s.format(t4-t3))

    return
コード例 #47
0
    def update(self, transect, flat=False):
        """
        Updates the container data to a profile that intersect the
        transect line.

        Returns nothing. Sets attributes as a side effect.

        Args:
            transect (LineString): A transect line.
            flat (Bool): Reads data into a flat list instead of
                         sorting by files.
        """
        Notice.info("Updating " + self.__class__.__name__)

        self.reset_data()

        # Preprocessing
        prepared = prep(transect.buffer(self.settings['buffer']))

        # Get intersecting points
        points = filter(prepared.contains, self.lookup.keys())

        # Lookup for grouping traces into segy files
        count = 0
        file_lookup = {}
        for point in points:
            meta = self.lookup[point]
            count += 1
            f = meta["segyfile"]
            if f in file_lookup:
                proj_d = transect.project(point)
                if proj_d:
                    file_lookup[f]["pos"].append(proj_d)
                    file_lookup[f]["trace"].append(meta["trace"])
                    file_lookup[f]["point"].append(point)
            else:
                file_lookup[f] = {}
                file_lookup[f]["trace"] = [meta["trace"]]
                file_lookup[f]["pos"] = [transect.project(point)]
                file_lookup[f]["point"] = [point]

        # Read in the chunks from the segy file
        self.files = []
        for segyfile in file_lookup.keys():
            self.files.append(os.path.basename(segyfile))
            segy = readSEGY(segyfile, unpack_trace_headers=True)
            traces = file_lookup[segyfile]["trace"]
            coords = file_lookup[segyfile]["pos"]
            points = file_lookup[segyfile]["point"]

            # Get the sort order.
            idx = sorted(range(len(traces)), key=lambda k: traces[k])
            idx = filter(None, idx)

            coords = [coords[i] for i in idx]
            data = [segy.traces[traces[i]] for i in idx]

            if flat:
                self.data += data
                self.coords += coords
            else:
                self.data.append(data)
                self.coords.append(coords)
コード例 #48
0
ファイル: seisplot.py プロジェクト: agile-geoscience/seisplot
    stupid_image = Image.open(fname)
    if cfg['stain_paper']: utils.stain_paper(stupid_image)
    utils.add_rings(stupid_image, cfg['coffee_rings'])
    if cfg['scribble']: utils.add_scribble(stupid_image)
    stupid_image.save(fname)

    t4 = time.time()
    Notice.ok("Saved stupid file {} in {:.1f} s".format(fname, t4-t3))

    return


if __name__ == "__main__":

    Notice.title()
    parser = argparse.ArgumentParser(description='Plot a SEGY file.')
    parser.add_argument("-c", "--config",
                        metavar="config file",
                        type=argparse.FileType('r'),
                        default="config.yaml",
                        nargs="?",
                        help="The name of a YAML config file. Default: config.yaml.")
    parser.add_argument('filename',
                        metavar='SEGY file',
                        type=str,
                        nargs='?',
                        help='The path to one or more SEGY files. Uses Unix-style pathname expansion.')
    parser.add_argument('-o', '--out',
                        metavar='output file',
                        type=str,
コード例 #49
0
ファイル: seisplot.py プロジェクト: agile-geoscience/seisplot
def main(target, cfg):
    """
    Puts everything together.
    """
    t0 = time.time()

    #####################################################################
    #
    # READ SEGY
    #
    #####################################################################
    s = Seismic.from_segy(target, params={'ndim': cfg['ndim']})

    # Set the line and/or xline number.
    try:
        n, xl = cfg['number']
    except:
        n, xl = cfg['number'], 0.5

    # Set the direction.
    if (s.ndim) == 2:
        direction = ['inline']
    elif cfg['direction'].lower()[0] == 'i':
        direction = ['inline']
    elif cfg['direction'].lower()[0] == 'x':
        direction = ['xline']
    elif cfg['direction'].lower()[0] == 't':
        direction = ['tslice']
    else:
        direction = ['inline', 'xline']

    # Get the data.
    ss = [Seismic.from_seismic(s, n=n, direction=d) for n, d in zip((n, xl), direction)]
    data = [s.data for s in ss]

    clip_val = np.percentile(s.data, cfg['percentile'])

    # Notify user of parameters.
    Notice.info("n_traces   {}".format(s.ntraces))
    Notice.info("n_samples  {}".format(s.nsamples))
    Notice.info("dt         {}".format(s.dt))
    Notice.info("t_start    {}".format(s.tstart))
    Notice.info("t_end      {}".format(s.tend))
    Notice.info("max_val    {:.3f}".format(np.amax(s.data)))
    Notice.info("min_val    {:.3f}".format(np.amin(s.data)))
    Notice.info("clip_val   {:.3f}".format(clip_val))

    t1 = time.time()
    Notice.ok("Read data in {:.1f} s".format(t1-t0))

    #####################################################################
    #
    # MAKE PLOT
    #
    #####################################################################
    Notice.hr_header("Plotting")

    # Plot size parameters.
    fs = cfg['fontsize']
    wsl = 6  # Width of sidelabel, inches
    mih = 12  # Minimum plot height, inches
    fhh = 5  # File header box height, inches
    m = 0.5  # basic unit of margins, inches

    # Margins, CSS like: top, right, bottom, left.
    mt, mr, mb, ml = m, 2 * m, m, 2 * m
    mm = m  # padded margin between seismic and label

    # Width is determined by seismic width, plus sidelabel, plus margins.
    # Height is given by ips, but with a minimum of mih inches.
    if 'tslice' in direction:
        print('doing tslice')
        seismic_width = max([s.ninlines for s in ss]) / cfg['tpi']
        seismic_height_raw = max([s.nxlines for s in ss]) / cfg['tpi']
        print(seismic_width, seismic_height_raw)
    else:
        seismic_width = max([s.ntraces for s in ss]) / cfg['tpi']
        seismic_height_raw = cfg['ips'] * (s.tbasis[-1] - s.tbasis[0])

    w = ml + seismic_width + mm + wsl + mr  # inches
    seismic_height = len(ss) * seismic_height_raw
    h_reqd = mb + seismic_height + 0.75*(len(ss)-1) + mt  # inches
    h = max(mih, h_reqd)

    # Calculate where to start sidelabel and seismic data.
    # Depends on whether sidelabel is on the left or right.
    if cfg['sidelabel'] == 'right':
        ssl = (ml + seismic_width + mm) / w  # Start of side label (ratio)
        seismic_left = ml / w
    else:
        ssl = ml / w
        seismic_left = (ml + wsl + mm) / w

    adj = max(0, h - h_reqd) / 2
    seismic_bottom = (mb / h) + adj / h
    seismic_width_fraction = seismic_width / w
    seismic_height_fraction = seismic_height_raw / h

    # Publish some notices so user knows plot size.
    Notice.info("Width of plot   {} in".format(w))
    Notice.info("Height of plot  {} in".format(h))

    # Make the figure.
    fig = plt.figure(figsize=(w, h), facecolor='w')

    # Set the tickformat.
    tickfmt = mtick.FormatStrFormatter('%.0f')

    # Plot title.
    if cfg['filename']:
        title_ax = fig.add_axes([ssl, 1-mt/h, wsl/w, mt/h])
        title_ax = plotter.plot_title(title_ax, target, fs=1.5*fs, cfg=cfg)

    # Plot text header.
    start = (h - 1.5*mt - fhh) / h
    head_ax = fig.add_axes([ssl, start, wsl/w, fhh/h])
    head_ax = plotter.plot_header(head_ax, s.header, fs=fs-1, cfg=cfg)

    # Plot histogram.
    # Params for histogram plot.
    pady = 0.75 / h  # 0.75 inch
    padx = 0.75 / w   # 0.75 inch
    cstrip = 0.3/h   # color_strip height = 0.3 in
    charth = 1.5/h   # height of charts = 1.5 in
    chartw = wsl/w - mr/w - padx  # or ml/w for left-hand sidelabel; same thing
    chartx = (ssl + padx)
    histy = 1.5 * mb/h + charth + pady
    # Plot colourbar under histogram.
    clrbar_ax = fig.add_axes([chartx, histy - cstrip, chartw, cstrip])
    clrbar_ax = plotter.plot_colourbar(clrbar_ax, cmap=cfg['cmap'])
    # Plot histogram itself.
    hist_ax = fig.add_axes([chartx, histy, chartw, charth])
    hist_ax = plotter.plot_histogram(hist_ax,
                                     s.data,
                                     tickfmt,
                                     percentile=cfg['percentile'],
                                     fs=fs)

    # Plot spectrum.
    specy = 1.5 * mb/h
    spec_ax = fig.add_axes([chartx, specy, chartw, charth])

    try:
        spec_ax = s.plot_spectrum(ax=spec_ax,
                                  tickfmt=tickfmt,
                                  ntraces=20,
                                  fontsize=fs)
    except:
        pass

    for i, line in enumerate(ss):
        # Add the seismic axis.
        ax = fig.add_axes([seismic_left,
                           seismic_bottom + i*seismic_height_fraction + i*pady,
                           seismic_width_fraction,
                           seismic_height_fraction
                           ])

        # Plot seismic data.
        if cfg['display'].lower() in ['vd', 'varden', 'variable', 'both']:
            _ = ax.imshow(line.data.T,
                          cmap=cfg['cmap'],
                          clim=[-clip_val, clip_val],
                          extent=[0, 
                                  line.ntraces,
                                  1000*line.tbasis[-1],
                                  line.tbasis[0]],
                          aspect='auto'
                          )

            # This does not work: should cut off line at cfg['tmax']
            # ax.set_ylim(1000*cfg['tmax'] or 1000*line.tbasis[-1], line.tbasis[0])

        if cfg['display'].lower() in ['wiggle', 'both']:
            ax = line.wiggle_plot(cfg['number'], direction,
                               ax=ax,
                               skip=cfg['skip'],
                               gain=cfg['gain'],
                               rgb=cfg['colour'],
                               alpha=cfg['opacity'],
                               lw=cfg['lineweight'],
                               tmax=cfg['tmax'],
                               )

        if cfg['display'].lower() not in ['vd', 'varden', 'variable', 'wiggle', 'both']:
            Notice.fail("You must specify the type of display: wiggle, vd, both.")
            return

        # Seismic axis annotations.
        fs = cfg['fontsize'] - 2
        ax.set_xlim([0, line.data.shape[0]])
        ax.set_ylabel(line.ylabel, fontsize=fs)
        ax.set_xlabel(line.xlabel, fontsize=fs, horizontalalignment='center')
        ax.set_xticklabels(ax.get_xticks(), fontsize=fs)
        ax.set_yticklabels(ax.get_yticks(), fontsize=fs)
        ax.xaxis.set_major_formatter(tickfmt)
        ax.yaxis.set_major_formatter(tickfmt)


        # Watermark.
        if cfg['watermark_text']:
            ax = plotter.watermark_seismic(ax, cfg)

        # Make parasitic axes for labeling CDP number.
        par1 = ax.twiny()
        par1.spines["top"].set_position(("axes", 1.0))
        par1.plot(s.xlines, np.zeros_like(s.xlines))
        par1.set_xlabel(line.xlabel, fontsize=fs)
        par1.set_xticklabels(par1.get_xticks(), fontsize=fs)
        par1.xaxis.set_major_formatter(tickfmt)

    t2 = time.time()
    Notice.ok("Built plot in {:.1f} s".format(t2-t1))

    #####################################################################
    #
    # SAVE FILE
    #
    #####################################################################
    Notice.hr_header("Saving")

    dname, fname, ext = utils.path_bits(target)
    outfile = cfg['outfile'] or ''
    if not os.path.splitext(outfile)[1]:
        outfile = os.path.join(cfg['outfile'] or dname, fname + '.png')

    fig.savefig(outfile)

    t3 = time.time()
    Notice.ok("Saved image file {} in {:.1f} s".format(outfile, t3-t2))

    if cfg['stain_paper'] or cfg['coffee_rings'] or cfg['distort'] or cfg['scribble']:
        fname = os.path.splitext(outfile)[0] + ".stupid.png"
        fig.savefig(fname)
    else:
        return

    #####################################################################
    #
    # SAVE STUPID FILE
    #
    #####################################################################
    Notice.hr_header("Applying the stupidity")

    stupid_image = Image.open(fname)
    if cfg['stain_paper']: utils.stain_paper(stupid_image)
    utils.add_rings(stupid_image, cfg['coffee_rings'])
    if cfg['scribble']: utils.add_scribble(stupid_image)
    stupid_image.save(fname)

    t4 = time.time()
    Notice.ok("Saved stupid file {} in {:.1f} s".format(fname, t4-t3))

    return
コード例 #50
0
ファイル: seisplot.py プロジェクト: irek-zaripov/seisplot
def main(target, cfg):
    """
    Puts everything together.
    """
    t0 = time.time()

    # Read the file.
    section = readSEGY(target, unpack_headers=True)

    # Calculate some things
    nsamples = section.traces[0].header.number_of_samples_in_this_trace
    dt = section.traces[0].header.sample_interval_in_ms_for_this_trace
    ntraces = len(section.traces)
    tbase = 0.001 * np.arange(0, nsamples * dt, dt)
    tstart = 0
    tend = np.amax(tbase)
    wsd = ntraces / cfg['tpi']

    # Build the data container
    elev, esp, ens, tsq = [], [], [], []  # energy source point number
    data = np.zeros((nsamples, ntraces))
    for i, trace in enumerate(section.traces):
        data[:, i] = trace.data
        elev.append(trace.header.receiver_group_elevation)
        esp.append(trace.header.energy_source_point_number)
        ens.append(trace.header.ensemble_number)
        tsq.append(trace.header.trace_sequence_number_within_line)

    clip_val = np.percentile(data, 99.0)

    # Notify user of parameters
    Notice.info("n_traces   {}".format(ntraces))
    Notice.info("n_samples  {}".format(nsamples))
    Notice.info("dt         {}".format(dt))
    Notice.info("t_start    {}".format(tstart))
    Notice.info("t_end      {}".format(tend))
    Notice.info("max_val    {}".format(np.amax(data)))
    Notice.info("min_val    {}".format(np.amin(data)))
    Notice.info("clip_val   {}".format(clip_val))

    t1 = time.time()
    Notice.ok("Read data successfully in {:.1f} s".format(t1-t0))

    #####################################################################
    #
    # MAKE PLOT
    #
    #####################################################################
    Notice.hr_header("Plotting")

    ##################################
    # Plot size parameters
    # Some constants
    wsl = 6  # Width of sidelabel
    mih = 10  # Minimum plot height
    fhh = 5  # File header height
    m = 0.5  # margin in inches

    # Margins, CSS like
    mt, mb, ml, mr = m, m, 2 * m, 2 * m
    mm = mr / 2  # padded margin between seismic and label

    # Width is determined by tpi, plus a constant for the sidelabel, plus 1 in
    w = ml + wsd + wsl + mr + mm

    # Height is given by ips, but with a minimum of 8 inches, plus 1 in
    h = max(mih, cfg['ips'] * (np.amax(tbase) - np.amin(tbase)) / 1000 + mt + mb)

    # More settings
    ssl = (ml + wsd + mm) / w  # Start of side label (ratio)
    fs = cfg['fontsize']

    Notice.info("Width of plot   {} in".format(w))
    Notice.info("Height of plot  {} in".format(h))

    ##################################
    # Make the figure.
    fig = plt.figure(figsize=(w, h), facecolor='w')
    ax = fig.add_axes([ml / w, mb / h, wsd / w, (h - mb - mt) / h])

    # make parasitic axes for labeling CDP number
    par1 = ax.twiny()
    par1.spines["top"].set_position(("axes", 1.0))
    tickfmt = mtick.FormatStrFormatter('%.0f')
    par1.plot(ens, np.zeros_like(ens))
    par1.set_xlabel("CDP number", fontsize=fs-2)
    par1.set_xticklabels(par1.get_xticks(), fontsize=fs-2)
    par1.xaxis.set_major_formatter(tickfmt)

    ax = wiggle_plot(ax,
                     data,
                     tbase,
                     ntraces,
                     skip=cfg['skip'],
                     gain=cfg['gain'],
                     rgb=cfg['colour'],
                     alpha=cfg['opacity'],
                     lw=cfg['lineweight']
                     )

    ax = decorate_seismic(ax, ntraces, tickfmt, fs)

    # Plot title
    title_ax = fig.add_axes([ssl, 1-mt/h, wsl/w, mt/(2*h)])
    title_ax = plot_title(title_ax, target, fs=fs)

    # Plot text header.
    s = str(section.textual_file_header)[2:-1]
    start = (h - mt - fhh) / h
    head_ax = fig.add_axes([ssl, start, wsl/w, fhh/h])
    head_ax = plot_header(head_ax, s, fs)

    # Plot histogram.
    pad = 0.05
    charty = 0.125  # height of chart
    xhist = (ssl + pad)
    whist = (1 - ssl - (ml/w)) - 2 * pad
    hist_ax = fig.add_axes([xhist, 1.5 * mb/h + charty + pad, whist, charty])
    hist_ax = plot_histogram(hist_ax, data, fs)

    # Plot spectrum.
    spec_ax = fig.add_axes([xhist, 1.5 * mb/h, whist, charty])
    spec_ax = plot_spectrum(spec_ax, data, dt, fs)

    t2 = time.time()
    Notice.ok("Built plot in {:.1f} s".format(t2-t1))

    #####################################################################
    #
    # SAVE FILE
    #
    #####################################################################
    Notice.hr_header("Saving")
    s = "Saved image file {} in {:.1f} s"
    if cfg['outfile']:
        fig.savefig(cfg['outfile'])
        t3 = time.time()
        Notice.ok(s.format(cfg['outfile'], t3-t2))
    else:
        stem, _ = os.path.splitext(target)
        fig.savefig(stem)
        t3 = time.time()
        Notice.ok(s.format(stem+'.png', t3-t2))

    return
コード例 #51
0
ファイル: feature_plot.py プロジェクト: stenotech/geotransect
def plot_feature_well(tc, gs):
    """
    Plotting function for the feature well.

    Args:
        tc (TransectContainer): The container for the main plot.
        log (axis): A matplotlib axis.
        gs (GridSpec): A matplotlib gridspec.
    """
    fname = tc.settings['curve_display']

    logs = tc.log.get(tc.feature_well)

    if not logs:
        # There was no data for this well, so there won't be a feature plot.
        Notice.fail("There's no well data for feature well " + tc.feature_well)
        return gs

    Z = logs.data['DEPT']

    curves = ['GR', 'DT',
              'DPHI_SAN',
              'NPHI_SAN',
              'DTS',
              'RT_HRLT',
              'RHOB',
              'DRHO']

    window = tc.settings.get('curve_smooth_window') or 51
    ntracks = 5
    lw = 1.0
    smooth = True
    naxes = 0
    ncurv_per_track = np.zeros(ntracks)

    if getattr(tc.log, 'striplog', None):
        ncurv_per_track[0] = 1

    for curve in curves:
        naxes += 1
        params = get_curve_params(curve, fname)
        ncurv_per_track[params['track']] += 1

    axss = plt.subplot(gs[2:, -5])
    axs0 = [axss, axss.twiny()]
    axs1 = [plt.subplot(gs[2:, -4])]
    axs2 = [plt.subplot(gs[2:, -3])]
    axs3 = [plt.subplot(gs[2:, -2])]
    axs4 = [plt.subplot(gs[2:, -1])]

    axs = [axs0, axs1, axs2, axs3, axs4]

    if getattr(tc.log, 'striplog', None):
        legend = Legend.default()
        try:
            logs.striplog[tc.log.striplog].plot_axis(axs0[0], legend=legend)
        except KeyError:
            # In fact, this striplog doesn't exist.
            Notice.fail("There is no such striplog" + tc.log.striplog)
            # And move on...

    axs0[0].set_ylim([Z[-1], 0])
    label_shift = np.zeros(len(axs))

    for curve in curves:
        try:
            values = logs.data[curve]
        except ValueError:
            Notice.warning("Curve not present: "+curve)
            values = np.empty_like(Z)
            values[:] = np.nan

        params = get_curve_params(curve, fname)
        i = params['track']

        j = 0

        label_shift[i] += 1

        linOrlog = params['logarithmic']

        sxticks = np.array(params['xticks'])
        xticks = np.array(sxticks, dtype=float)
        whichticks = 'major'

        if linOrlog == 'log':
            midline = np.log(np.mean(xticks))
            xpos = midline
            whichticks = 'minor'
        else:
            midline = np.mean(xticks)
            xpos = midline

        if smooth:
            values = utils.rolling_median(values, window)

        if curve == 'GR':
            j = 1  # second axis in first track
            label_shift[i] = 1
            if params['fill_left_cond']:
                # do the fill for the lithology track
                axs[i][j].fill_betweenx(Z, params['xleft'], values,
                                        facecolor=params['fill_left'],
                                        alpha=1.0, zorder=11)

        if (curve == 'DPHI_SAN') and params['fill_left_cond']:
            # do the fill for the neutron porosity track
            try:
                nphi = utils.rolling_median(logs.data['NPHI_SAN'], window)
            except ValueError:
                Notice.warning("No NPHI in this well")
                nphi = np.empty_like(Z)
                nphi[:] = np.nan
            axs[i][j].fill_betweenx(Z,
                                    nphi,
                                    values,
                                    where=nphi >= values,
                                    facecolor=params['fill_left'],
                                    alpha=1.0,
                                    zorder=11)

            axs[i][j].fill_betweenx(Z,
                                    nphi,
                                    values,
                                    where=nphi <= values,
                                    facecolor='#8C1717',
                                    alpha=0.5,
                                    zorder=12)

        if curve == 'DRHO':
            blk_drho = 3.2
            values += blk_drho   # this is a hack to get DRHO on RHOB scale
            axs[i][j].fill_betweenx(Z,
                                    blk_drho,
                                    values,
                                    where=nphi <= values,
                                    facecolor='#CCCCCC',
                                    alpha=0.5,
                                    zorder=12)

        # fill right
        if params['fill_right_cond']:

            axs[i][j].fill_betweenx(Z, values, params['xright'],
                                    facecolor=params['fill_right'],
                                    alpha=1.0, zorder=12)

        # plot curve
        axs[i][j].plot(values, Z, color=params['hexcolor'],
                       lw=lw, zorder=13)

        # set scale of curve
        axs[i][j].set_xlim([params['xleft'], params['xright']])

        # ------------------------------------------------- #
        # curve labels
        # ------------------------------------------------- #

        trans = transforms.blended_transform_factory(axs[i][j].transData,
                                                     axs[i][j].transData)

        magic = -Z[-1] / 12.
        axs[i][j].text(xpos, magic - (magic/4)*(label_shift[i]-1),
                       curve,
                       horizontalalignment='center',
                       verticalalignment='bottom',
                       fontsize=12, color=params['hexcolor'],
                       transform=trans)
        # curve units
        units = '${}$'.format(params['units'])
        if label_shift[i] <= 1:
            axs[i][j].text(xpos, magic*0.5,
                           units,
                           horizontalalignment='center',
                           verticalalignment='top',
                           fontsize=12, color='k',
                           transform=trans)

        # ------------------------------------------------- #
        # scales and tickmarks
        # ------------------------------------------------- #

        axs[i][j].set_xscale(linOrlog)
        axs[i][j].set_ylim([Z[-1], 0])
        axs[i][j].axes.xaxis.set_ticks(xticks)
        axs[i][j].axes.xaxis.set_ticklabels(sxticks, fontsize=8)
        for label in axs[i][j].axes.xaxis.get_ticklabels():
            label.set_rotation(90)
        axs[i][j].tick_params(axis='x', direction='out')
        axs[i][j].xaxis.tick_top()
        axs[i][j].xaxis.set_label_position('top')
        axs[i][j].xaxis.grid(True, which=whichticks,
                             linewidth=0.25, linestyle='-',
                             color='0.75', zorder=100)

        axs[i][j].yaxis.grid(True, which=whichticks,
                             linewidth=0.25, linestyle='-',
                             color='0.75', zorder=100)
        axs[i][j].yaxis.set_ticks(np.arange(0, max(Z), 100))
        if i != 0:
                axs[i][j].set_yticklabels("")

    # ------------------------------------------------- #
    # End of curve loop
    # ------------------------------------------------- #

    # Add Depth label
    axs[0][0].text(0, 1.05, 'MD\n$m$', fontsize='10',
                   horizontalalignment='center',
                   verticalalignment='center',
                   transform=axs[0][0].transAxes)

    axs[0][0].axes.yaxis.get_ticklabels()
    axs[0][0].axes.xaxis.set_ticklabels('')

    for label in axs[0][0].axes.yaxis.get_ticklabels():
            label.set_rotation(90)
            label.set_fontsize(10)

    for label in axs[1][0].axes.xaxis.get_ticklabels():
        label.set_rotation(90)
        label.set_fontsize(10)

    # Add Tops
    try:
        if os.path.exists(tc.tops_file):
            tops = utils.get_tops(tc.tops_file)
            topx = get_curve_params('DT', fname)
            topmidpt = np.amax((topx)['xright'])

            # plot tops
            for i in range(ntracks):

                for mkr, depth in tops.iteritems():

                    # draw horizontal bars at the top position
                    axs[i][-1].axhline(y=depth,
                                       xmin=0.01, xmax=.99,
                                       color='b', lw=2,
                                       alpha=0.5,
                                       zorder=100)

                    # draw text box at the right edge of the last track
                    axs[-1][-1].text(x=topmidpt, y=depth, s=mkr,
                                     alpha=0.5, color='k',
                                     fontsize='8',
                                     horizontalalignment='center',
                                     verticalalignment='center',
                                     zorder=10000,
                                     bbox=dict(facecolor='white',
                                               edgecolor='k',
                                               alpha=0.25,
                                               lw=0.25),
                                     weight='light')

    except AttributeError:
        Notice.warning("No tops for this well")
    except TypeError:
        # We didn't get a tops file so move along.
        print "No tops for this well"

    return gs
コード例 #52
0
ファイル: seisplot.py プロジェクト: irek-zaripov/seisplot
    if cfg['outfile']:
        fig.savefig(cfg['outfile'])
        t3 = time.time()
        Notice.ok(s.format(cfg['outfile'], t3-t2))
    else:
        stem, _ = os.path.splitext(target)
        fig.savefig(stem)
        t3 = time.time()
        Notice.ok(s.format(stem+'.png', t3-t2))

    return


if __name__ == "__main__":

    Notice.title()
    parser = argparse.ArgumentParser(description='Plot a SEGY file.')
    parser.add_argument("-c", "--config",
                        metavar="config file",
                        type=argparse.FileType('r'),
                        default="config.yaml",
                        nargs="?",
                        help="The name of a YAML config file.")
    parser.add_argument('filename',
                        metavar='SEGY file',
                        type=str,
                        nargs='?',
                        help='The path to a SEGY file.')
    parser.add_argument('-o', '--out',
                        metavar='Output file',
                        type=str,