Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UTM Conversion Utility #321

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4f1888a
ready to merge
dsentinel Sep 4, 2019
699ee8e
ready to merge
dsentinel Sep 4, 2019
3731a3b
really ready to merge this time, honest
dsentinel Sep 4, 2019
99c826c
conversions consolidated into ph5utils
Oct 2, 2019
fc789d5
re-integrated with segd2ph5
Oct 2, 2019
5a194ee
reconciling pyproj utilities
Oct 21, 2019
26a933f
flake8 updates
Oct 22, 2019
5c06647
segd2ph5 version number set to 2019.252.
Oct 22, 2019
504892e
Merge branch 'master' into utm_util
Oct 22, 2019
d3e5cd2
Updating pyproj version to 2.2
Oct 23, 2019
26e9ee4
Merge branch 'master' into utm_util
dthomas1953 Oct 23, 2019
4942cff
pyproj update, flake8 2
Oct 23, 2019
bcb902b
pyproj, flake8
Oct 23, 2019
18fba3e
fixed ph5utils declaration of run_geod
Oct 24, 2019
e3b18fe
refactored utm tests
Oct 25, 2019
bfc83fd
Latest updates
Dec 17, 2019
0d51891
Fix'd segd2ph5.py, got it working.
Dec 23, 2019
d3a9664
consolidated map functions
Jan 17, 2020
b1c2ae8
redo of segd2ph5.py
Jan 17, 2020
984e95b
redoing segd2ph5.py again
Jan 18, 2020
b91119c
Merge branch 'master' into utm_util
Jan 29, 2020
ddaf759
flake, remove extra line
Jan 29, 2020
9c77f13
Fixed run_geod call syntax, good for merge (hopefully)
Jan 30, 2020
c5b72c3
restructure and pep8 finished
Feb 25, 2020
3e5cd61
removed pinning of pyproj in environment.yml
Feb 26, 2020
ade0cf9
eliminated UTM class, all functions now
Mar 5, 2020
d83bc1c
Merge branch 'master' into utm_util
dthomas1953 Mar 5, 2020
98b5ff0
updates per Lloyd's review
Mar 6, 2020
c258a02
Merge branch 'utm_util' of https://github.com/PIC-IRIS/PH5 into utm_util
Mar 6, 2020
3e62af5
fixed lowercase data entry issue
Mar 6, 2020
8a07b8b
Merge branch 'master' into utm_util
dthomas1953 Mar 13, 2020
91452e9
Added UPS, logger usage, name cleanups
Mar 31, 2020
d5d9453
Merge branch 'master' into utm_util
dthomas1953 Mar 31, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
- nose
- numpy
- numexpr
- pyproj
- pyproj=2.2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the justification for pinning this?

- psutil
- obspy
- vispy
Expand Down
92 changes: 0 additions & 92 deletions ph5/core/cs2cs.py

This file was deleted.

26 changes: 5 additions & 21 deletions ph5/core/ph5api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
import re
import numpy as np
import math
from pyproj import Geod
from ph5.core import columns, experiment, timedoy
from ph5.core import columns, experiment, timedoy, ph5utils
from tables.exceptions import NoSuchNodeError

PROG_VERSION = '2019.93'
PROG_VERSION = '2020.017'

LOGGER = logging.getLogger(__name__)
PH5VERSION = columns.PH5VERSION
Expand Down Expand Up @@ -329,14 +328,16 @@ def get_offset(self, sta_line, sta_id, evt_line, evt_id):
LOGGER.warning("Couldn't get offset.")
return {}
try:
UNITS = 'm'
if sta_line in self.Array_t and evt_line in self.Event_t:
array_t = self.Array_t[sta_line]['byid'][sta_id][c]
event_t = self.Event_t[evt_line]['byid'][evt_id]
lon0 = array_t[0]['location/X/value_d']
lat0 = array_t[0]['location/Y/value_d']
lon1 = event_t['location/X/value_d']
lat1 = event_t['location/Y/value_d']
az, baz, dist = run_geod(lat0, lon0, lat1, lon1)
az, baz, dist = ph5utils.run_geod(lat0, lon0, lat1, lon1,
FACTS_M[UNITS])
except Exception as e:
LOGGER.warning("Couldn't get offset. {0}".format(repr(e)))
return {}
Expand Down Expand Up @@ -1664,23 +1665,6 @@ def by_id(rows, key='id_s', secondary_key=None, unique_key=True):
return byid, order


def run_geod(lat0, lon0, lat1, lon1):
UNITS = 'm'
ELLIPSOID = 'WGS84'

config = "+ellps={0}".format(ELLIPSOID)

g = Geod(config)

az, baz, dist = g.inv(lon0, lat0, lon1, lat1)

if dist:
dist /= FACTS_M[UNITS]

# Return list containing azimuth, back azimuth, distance
return az, baz, dist


def rect(r, w, deg=0):
# Convert from polar to rectangular coordinates
# radian if deg=0; degree if deg=1
Expand Down
80 changes: 79 additions & 1 deletion ph5/core/ph5utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
from ph5.core.timedoy import epoch2passcal, passcal2epoch, TimeDOY, TimeError
import time
import re
from pyproj import Transformer, Geod
import math

PROG_VERSION = "2019.81"
PROG_VERSION = "2020.017"


class PH5Response(object):
Expand Down Expand Up @@ -68,6 +70,82 @@ def get_n_i(self, sensor_keys, datalogger_keys):
return ph5_resp.n_i


class UTMConversions:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use singular from, drop the s


def __init__(self, lat, lon, side, zone):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that one UTMConversions can be reused for a set of lat lons, but here a new one has to be created for each conversion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

side and zone can be None so they should probably be optional and default to None

Lat and long should not be required, only provided in the call of the functions latlong2XXX(lat, long)
e.g. review comment aug 2

self.epsg_wgs84 = "EPSG:4326"

if side is not None and lat is None:
if side == "S":
epsgroot = "327"
elif side == "N":
epsgroot = "326"
elif lat is not None:
if lat < 0.0:
epsgroot = "327"
side = 'S'
elif lat >= 0.0:
epsgroot = "326"
side = 'N'

if zone is not None and lon is None:
self.epsg_utm = "EPSG:" + epsgroot + str(zone)
elif lon is not None:
zone = self.lon2zone(lon)
self.epsg_utm = "EPSG:" + epsgroot + str(zone)

self.utm_zone = zone
self.hemisphere = side

def lon2zone(self, lon):
''' Get UTM zone from longitude '''
zone = int(math.floor((float(lon) + 180.)/6.0) % 60) + 1
return zone

def utm2latlong(self, easting, northing):
transformer = Transformer.from_crs(self.epsg_utm, self.epsg_wgs84,
always_xy=True)
lon, lat = transformer.transform(float(easting), float(northing))
return (lat, lon)

def geod2utm(self, lat, lon, elev): # utility function
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid inline comments, and comments that don't add information.

transformer = Transformer.from_crs(self.epsg_wgs84, self.epsg_utm,
always_xy=True)
easting, northing = transformer.transform(lon, lat)
return (northing, easting, elev) # e.g. Y, X, Z

def latlong2utm(self, lat, lon):
transformer = Transformer.from_crs(self.epsg_wgs84, self.epsg_utm,
always_xy=True)
easting, northing = transformer.transform(lon, lat)
return (easting, northing, self.utm_zone, self.hemisphere)


def tspc_lat_long(easting, northing): # Texas State Plane Coords
epsg_wgs84 = "EPSG:4326"
epsg_sp4202 = "EPSG:2276" # State Plane Coords in US FEET
transformer = Transformer.from_crs(epsg_sp4202, epsg_wgs84,
always_xy=True)
lon, lat = transformer.transform(easting, northing)
return (lon, lat)


def run_geod(lat0, lon0, lat1, lon1, scalar=1.0):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better named latlong2geod?

ELLIPSOID = 'WGS84'

config = "+ellps={0}".format(ELLIPSOID)

g = Geod(config)

az, baz, dist = g.inv(lon0, lat0, lon1, lat1)

if dist:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this conditional is to test ==0, then if dist == 0

dist /= scalar

# Return list containing azimuth, back azimuth, distance
return az, baz, dist


"""
===============
Utility methods
Expand Down
54 changes: 20 additions & 34 deletions ph5/core/segyfactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
import string
import sys
import logging
from pyproj import Geod
from ph5.core.cs2cs import geod2utm
from ph5.core import ph5utils # for geod2utm, run_geod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...same as inline comment above.

from ph5.core import segy_h, ebcdic

PROG_VERSION = '2018.268'
PROG_VERSION = '2020.015'
LOGGER = logging.getLogger(__name__)

os.environ['TZ'] = 'UTC'
Expand Down Expand Up @@ -787,11 +786,11 @@ def set_trace_header(self):

if self.utm is True:
try:
Y, X, Z = geod2utm(None, # Zone goes here
"WGS84",
self.array_t['location/Y/value_d'],
self.array_t['location/X/value_d'],
self.array_t['location/Z/value_d'])
lat = self.array_t['location/Y/value_d']
lon = self.array_t['location/X/value_d']
elev = self.array_t['location/Z/value_d']
utmc = ph5utils.UTMConversions(lat, lon, None, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...as above, shouldn't need to create a new instance for each conversion

Y, X, Z = utmc.geod2utm(lat, lon, elev)
s, vx, vy = pick_values_32(X, Y)

tra['coordScale'] = s
Expand Down Expand Up @@ -844,11 +843,11 @@ def set_trace_header(self):

if self.utm:
try:
Y, X, Z = geod2utm(None, # Zone goes here
"WGS84",
self.event_t['location/Y/value_d'],
self.event_t['location/X/value_d'],
self.event_t['location/Z/value_d'])
lat = self.event_t['location/Y/value_d']
lon = self.event_t['location/X/value_d']
elev = self.event_t['location/Z/value_d']
utmc = ph5utils.UTMConversions(lat, lon, None, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...as above

Y, X, Z = utmc.geod2utm(lat, lon, elev)

s, vx, vy = pick_values_32(X, Y)
tra['sourceLongOrX'] = vx
Expand All @@ -873,10 +872,14 @@ def set_trace_header(self):
tra['sourceToRecDist'] = self.offset_t['offset/value_d']
else:
try:
az_baz_dist = run_geod(self.event_t['location/Y/value_d'],
self.event_t['location/X/value_d'],
self.array_t['location/Y/value_d'],
self.array_t['location/X/value_d'])
lat1 = self.event_t['location/Y/value_d']
lon1 = self.event_t['location/X/value_d']
lat2 = self.array_t['location/Y/value_d']
lon2 = self.array_t['location/X/value_d']

UNITS = 'm'
az_baz_dist = ph5utils.run_geod(lat1, lon1, lat2, lon2,
FACTS[UNITS])
tra['sourceToRecDist'] = az_baz_dist[2]
except Exception as e:
# sys.stderr.write (e.message)
Expand Down Expand Up @@ -1058,23 +1061,6 @@ def pick_values_32(X, Y):
return sx, vx, vy


def run_geod(lat0, lon0, lat1, lon1):
ELLIPSOID = 'WGS84'
UNITS = 'm'

config = "+ellps={0}".format(ELLIPSOID)

g = Geod(config)

az, baz, dist = g.inv(lon0, lat0, lon1, lat1)

if dist:
dist /= FACTS[UNITS]

# Return list containing azimuth, back azimuth, distance
return az, baz, dist


#
# Write standard SEG-Y reel header
#
Expand Down
7 changes: 6 additions & 1 deletion ph5/entry_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Dave Thomas, 2019-08-06

PROG_VERSION = '2019.218'
PROG_VERSION = '2019.330'


class EntryPointTypes():
Expand Down Expand Up @@ -277,5 +277,10 @@ def __init__(self):
'Takes PH5 files and returns time series '
'availability info.',
type=EntryPointTypes.CLIENT),
EntryPoint('utm_latlong',
'ph5.utilities.utm_latlong:main',
'Converts UTM coordinates to/from'
' Latitudes & Longitudes.',
type=EntryPointTypes.INGESTION),
]
}
12 changes: 5 additions & 7 deletions ph5/utilities/novenqc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from random import randint
from inspect import stack
from ast import literal_eval
from pyproj import Geod
from ph5.core import ph5utils # for run_geod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... bad comment

import simplekml as kml

from ph5.core import timedoy

PROG_VERSION = '2019.14'
PROG_VERSION = '2020.015'
LOGGER = logging.getLogger(__name__)

FACTS = {'km': 1000., 'm': 1., 'dm': 1. / 10., 'cm': 1. / 100.,
Expand Down Expand Up @@ -216,15 +216,13 @@ def qc_dist(ys, xs, zs):
# Need to check for UTM and convert to lat/lon
#
units = 'm'
ellipsoid = 'WGS84'
config = "+ellps={0}".format(ellipsoid)
g = Geod(config)
az, baz, dist = g.inv(xs[0], ys[0], xs[1], ys[1])
az, baz, dist = ph5utils.run_geod(ys[0], xs[0], ys[1], xs[1],
FACTS[units])
if len(zs) > 1:
zdelta = float(zs[1]) - float(zs[0])
else:
zdelta = 0.0
return az, baz, dist / FACTS[units], zdelta
return az, baz, dist, zdelta

def qc_time(t1, t2):
'''
Expand Down
Loading