Browse Source

adapt to new module scheme

hyposat
Marius Kriegerowski 4 years ago
parent
commit
4ec5245ba0
27 changed files with 98 additions and 99 deletions
  1. +1
    -1
      ahfullgreen.py
  2. +1
    -1
      audio.py
  3. +1
    -1
      beam_stack.py
  4. +2
    -2
      cake_phase.py
  5. +2
    -2
      catalog_stats.py
  6. +7
    -8
      cc_matrix/snuffling.py
  7. +26
    -31
      cc_relocation.py
  8. +21
    -21
      corrsearch.py
  9. +2
    -2
      drumplot.py
  10. +3
    -3
      export_waveforms.py
  11. +1
    -1
      extract_catalog.py
  12. +1
    -1
      extract_events.py
  13. +2
    -2
      fk_parstack.py
  14. +6
    -4
      hyposat-snuffling/snuffling.py
  15. +1
    -1
      kiwi_seismosizer.py
  16. +2
    -2
      local_magnitude.py
  17. +6
    -3
      map/snuffling.py
  18. +1
    -1
      notch.py
  19. +1
    -1
      obspy_fk_analyse_polar.py
  20. +2
    -2
      okada/snuffling.py
  21. +2
    -2
      particle_motion.py
  22. +1
    -1
      plot_traces.py
  23. +1
    -1
      psd.py
  24. +1
    -1
      seismosizer.py
  25. +1
    -1
      spectrogram.py
  26. +2
    -2
      time_line.py
  27. +1
    -1
      vtk-map/snuffling.py

+ 1
- 1
ahfullgreen.py View File

@ -4,7 +4,7 @@ import os
from PyQt4.QtCore import *
from pyrocko import moment_tensor, model, trace
from pyrocko.snuffling import Snuffling, Param, Choice, Switch, EventMarker
from pyrocko.gui.snuffling import Snuffling, Param, Choice, Switch, EventMarker
from pyrocko import gf
from pyrocko.ahfullgreen import add_seismogram, Gauss, Impulse


+ 1
- 1
audio.py View File

@ -1,7 +1,7 @@
from __future__ import print_function
from PyQt4.QtCore import QThread, SIGNAL, QTimer
from pyrocko.snuffling import Snuffling, Param, Choice, Switch, NoTracesSelected
from pyrocko.gui.snuffling import Snuffling, Param, Choice, Switch, NoTracesSelected
import pyrocko.trace as trace
from pyrocko.trace import CosFader
from scipy.io.wavfile import write, read


+ 1
- 1
beam_stack.py View File

@ -1,6 +1,6 @@
from __future__ import print_function
from pyrocko.snuffling import Snuffling, Param, Switch, Choice
from pyrocko.gui.snuffling import Snuffling, Param, Switch, Choice
from pyrocko.model import Station, dump_stations
from pyrocko import orthodrome as ortho
from pyrocko import util, io, trace


+ 2
- 2
cake_phase.py View File

@ -1,7 +1,7 @@
from builtins import str
import os
from pyrocko.snuffling import Snuffling, Param, Switch, Choice
from pyrocko.pile_viewer import PhaseMarker
from pyrocko.gui.snuffling import Snuffling, Param, Switch, Choice
from pyrocko.gui.pile_viewer import PhaseMarker
from pyrocko import orthodrome
from pyrocko import gf
from pyrocko import cake


+ 2
- 2
catalog_stats.py View File

@ -1,5 +1,5 @@
from pyrocko.snuffling import Snuffling, Param, Choice
from pyrocko.gui_util import EventMarker
from pyrocko.gui.snuffling import Snuffling, Param, Choice
from pyrocko.gui.gui_util import EventMarker
from pyrocko import util
from pyrocko import moment_tensor
from pyrocko.orthodrome import distance_accurate50m as distance


+ 7
- 8
cc_matrix/snuffling.py View File

@ -1,19 +1,19 @@
from __future__ import print_function
import sys
import logging
import os.path as op
import numpy as num
import progressbar
import matplotlib.pyplot as plt
from pyrocko import model, trace, util, orthodrome, cake, gui_util
from pyrocko import trace, util, cake
from pyrocko.gf import Target
from pyrocko.snuffling import Snuffling, Choice, Param, Switch
from similarity import SimilarityMatrix, Similarity
import matplotlib.pyplot as plt
from pyrocko.gui.snuffling import Snuffling, Choice, Param, Switch
util.setup_logging('cc.py')
logger = logging.getLogger('cc-snuffling')
def make_targets(pile, stations):
targets = []
for nslc_id in pile.nslc_ids.keys():
@ -128,7 +128,7 @@ class SimilaritySnuffling(Snuffling):
load_data=False))
traces = [tr for trs in traces for tr in trs ]
visible_nslcs = [tr.nslc_id for tr in traces]
stations = [x for x in stations is util.match_nslcs(
stations = [x for x in stations if util.match_nslcs(
"%s.%s.%s.*" % x.nsl(), visible_nslcs)]
# TODO option to choose other models
@ -148,7 +148,6 @@ class SimilaritySnuffling(Snuffling):
vmax=float(self.vmax),
vmin=float(self.vmin))
similarities = []
trs2add = []
if self.save_traces :
figure_dir = self.input_directory(caption='Select directory to store images')
for itarget, target in enumerate(targets):
@ -210,7 +209,6 @@ class SimilaritySnuffling(Snuffling):
t_mini, v_mini = c_tr_chopped.min()
t_maxi, v_maxi = c_tr_chopped.max()
b_tr_shifted = b_tr.copy()
a_tr_shifted = a_tr.copy()
if abs(v_mini) > abs(v_maxi):
v_cc = v_mini
@ -285,5 +283,6 @@ class SimilaritySnuffling(Snuffling):
output_filename = self.output_filename()
self.similarity_matrix.dump(filename=output_filename)
def __snufflings__():
return [SimilaritySnuffling()]

+ 26
- 31
cc_relocation.py View File

@ -1,30 +1,32 @@
from __future__ import print_function
from builtins import range
from pyrocko.snuffling import Snuffling, Param, Switch, NoViewerSet, Choice
from pyrocko.trace import Trace
from pyrocko.pile_viewer import Marker, EventMarker, PhaseMarker
from pyrocko import io, trace, util, cake, crust2x2, orthodrome, model
import numpy as num
import logging, math
from pyrocko.gui.snuffling import Snuffling, Param, Switch, NoViewerSet, Choice
from pyrocko.gui.pile_viewer import Marker, EventMarker, PhaseMarker
from pyrocko.trace import Trace
from pyrocko import io, trace, util, cake, orthodrome, model
from pyrocko.dataset import crust2x2
km = 1000.
d2r = math.pi / 180.
class CorrelateEvents(Snuffling):
def setup(self):
self.set_name('Cross correlation relocation')
self.add_parameter(Param('Highpass [Hz]', 'corner_highpass', 1.0,
0.001, 50., low_is_none=True))
self.add_parameter(Param('Lowpass [Hz]', 'corner_lowpass', 4.0,
self.add_parameter(Param('Lowpass [Hz]', 'corner_lowpass', 4.0,
0.001, 50., high_is_none=True))
self.add_parameter(Param('Time window begin', 'tstart', -1.0,
-100., 0.))
self.add_parameter(Param('Time window end', 'tend', 3.0,
0., 100.))
self.add_parameter(Param('Minimum correlation', 'min_corr', 0.5,
self.add_parameter(Param('Minimum correlation', 'min_corr', 0.5,
0.0, 1.0))
self.add_parameter(Param('Replace master depth [km]', 'master_depth_km', None,
@ -33,9 +35,9 @@ class CorrelateEvents(Snuffling):
self.add_parameter(Switch('Save figure', 'save', False))
self.add_parameter(Switch('Fix depth', 'fix_depth', False))
self.add_parameter(Switch('Show correlation traces', 'show_correlation_traces', False))
self.add_parameter(Choice('Weighting', 'weighting', 'cubic',
self.add_parameter(Choice('Weighting', 'weighting', 'cubic',
['equal', 'linear', 'quadratic']))
self.add_parameter(Choice('Earth model', 'model_select', 'Global',
self.add_parameter(Choice('Earth model', 'model_select', 'Global',
['Global (ak135)', 'Local (from crust2x2)']))
self.set_live_update(False)
@ -111,7 +113,7 @@ class CorrelateEvents(Snuffling):
azi = orthodrome.azimuth(master, station)
arrivals = self.model.arrivals(
phases=phases[phasename][0],
phases=phases[phasename][0],
distances=[ dist*cake.m2d ],
zstart = master_depth,
zstop = 0.0)
@ -127,7 +129,7 @@ class CorrelateEvents(Snuffling):
math.cos(azi*d2r) * math.sin(takeoff*d2r) * u,
math.sin(azi*d2r) * math.sin(takeoff*d2r) * u,
math.cos(takeoff*d2r) * u ])
# gather picks for each event
for ev in events:
@ -149,7 +151,7 @@ class CorrelateEvents(Snuffling):
nsp = station.network, station.station, phasename
datasyn.append(tt.get(nsp,None))
for ev in events:
if nsp in ev.picks:
if nsp in ev.picks:
ttobs = ev.picks[nsp] - ev.time
else:
ttobs = None
@ -193,7 +195,7 @@ class CorrelateEvents(Snuffling):
iev = event_to_number[ev]
for istation, station in enumerate(stations):
nsp = station.network, station.station, phasename
if nsp in tt and nsp in ev.picks:
if nsp in tt and nsp in ev.picks:
tarr = ev.time + tt[nsp]
tarr_ec = tarr + tt_corr_event[iphasename, iev]
tarr_ec_sc = tarr_ec + tt_corr_station[iphasename, istation]
@ -206,7 +208,7 @@ class CorrelateEvents(Snuffling):
data = num.array(data, dtype=num.float).T
print('event %10s %3s %3i %15.2g %15.2g %15.2g' % (
(ev.name, phasename, data.shape[1]) +
(ev.name, phasename, data.shape[1]) +
tuple( num.mean(num.abs(x)) for x in data )))
else:
print('event %10s %3s no picks' % (ev.name, phasename))
@ -218,7 +220,6 @@ class CorrelateEvents(Snuffling):
if f is not None:
tpad = max(tpad, 1.0/f)
pile = self.get_pile()
waveforms = {}
for ev in events:
@ -245,14 +246,14 @@ class CorrelateEvents(Snuffling):
tmin = tarr2+self.tstart
tmax = tarr2+self.tend
marker = PhaseMarker( nslcs,
marker = PhaseMarker( nslcs,
tmin, tmax, 3, event=ev,
phasename=phasename)
markers.append(marker)
trs = pile.all(tmin, tmax, tpad=tpad, trace_selector=
lambda tr: tr.nslc_id[:2] == nsp[:2],
lambda tr: tr.nslc_id[:2] == nsp[:2],
want_incomplete=False)
trok = []
@ -265,12 +266,10 @@ class CorrelateEvents(Snuffling):
if self.corner_lowpass:
tr.lowpass(4, self.corner_lowpass)
tr.chop(tmin, tmax)
tr.set_location(ev.name)
#tr.shift( - (tmin - master.time) )
if num.all(num.isfinite(tr.ydata)):
trok.append(tr)
@ -309,7 +308,7 @@ class CorrelateEvents(Snuffling):
if nsp in a.picks and nsp in b.picks:
tshifts_picked[iphase,istation,ia,ib] = \
b.picks[nsp] - a.picks[nsp]
wa = waveforms[nsp+(ia,)]
wb = waveforms[nsp+(ib,)]
@ -328,9 +327,9 @@ class CorrelateEvents(Snuffling):
tcc = trace.correlate(ta,tb, mode='full', normalization='normal',
use_fft=True)
tccs.append(tcc)
if not tccs:
continue
@ -443,7 +442,7 @@ class CorrelateEvents(Snuffling):
if self.fix_depth:
for ievent in range(nevents):
row = num.zeros(nevents*4)
row[ievent*4+2] = 1.0
row[ievent*4+2] = 1.0
rows.append(row)
data.append(0.0)
@ -490,7 +489,7 @@ class CorrelateEvents(Snuffling):
north = x[0::4]
east = x[1::4]
down = x[2::4]
down = x[2::4]
etime = x[3::4] + tmean
def plot_range(x):
@ -564,7 +563,6 @@ class CorrelateEvents(Snuffling):
if not self.fix_depth:
p = fig.add_subplot(2,2,2, sharey=p0, aspect=1.0)
p.set_xlabel(d+'Depth [km]')
p.set_ylabel(d+'North [km]')
@ -573,7 +571,6 @@ class CorrelateEvents(Snuffling):
for i,ev in enumerate(events):
p.text(down[i]/km, north[i]/km, ev.name, clip_on=True)
p1 = p
p = fig.add_subplot(2,2,3, sharex=p0, aspect=1.0)
@ -594,15 +591,13 @@ class CorrelateEvents(Snuffling):
if not self.fix_depth:
p1.set_xlim(mi_down/km, ma_down/km)
p2.set_ylim(mi_down/km, ma_down/km)
if self.save:
fig.savefig(self.output_filename(dir='locations.pdf'))
fig.canvas.draw()
def __snufflings__():
return [ CorrelateEvents() ]
return [CorrelateEvents()]

+ 21
- 21
corrsearch.py View File

@ -1,15 +1,16 @@
from pyrocko.snuffling import Snuffling, Param, Switch, NoViewerSet, Choice
from pyrocko.pile_viewer import Marker, EventMarker
from pyrocko.gui.snuffling import Snuffling, Param, Switch, NoViewerSet, Choice
from pyrocko.gui.pile_viewer import Marker, EventMarker
from pyrocko import io, trace, model
class CorrsearchSnuffling(Snuffling):
'''
'''
def setup(self):
'''Customization of the snuffling.'''
self.set_name('Cross Correlation Search')
self.add_parameter(Param('Downsample to [Hz]', 'downsample', None, 0.1, 200., high_is_none=True))
self.add_parameter(Param('Highpass [Hz]', 'corner_highpass', 1., 0.001, 50.))
@ -21,21 +22,21 @@ class CorrsearchSnuffling(Snuffling):
def call(self):
'''Main work routine of the snuffling.'''
self.cleanup()
period_highpass = 1./self.corner_highpass
tpad = period_highpass
try:
try:
viewer = self.get_viewer()
markers = viewer.selected_markers()
if not markers:
return
if len(markers) != 1:
return
marker = markers[0]
master_tmin, master_tmax = marker.tmin, marker.tmax
if master_tmin >= master_tmax:
@ -44,7 +45,6 @@ class CorrsearchSnuffling(Snuffling):
except NoViewerSet:
viewer = None
master_tmin, master_tmax = self.master_tmin, self.master_tmax
pile = self.get_pile()
masters = {}
@ -60,7 +60,7 @@ class CorrsearchSnuffling(Snuffling):
tmin, tmax = pile.get_tmin()+tpad, pile.get_tmax()
else:
tmin, tmax = self.get_viewer().get_time_range()
tmaster = master_tmax-master_tmin
tinc = min(20*tmaster, max(tmaster, tmax-tmin))
@ -79,7 +79,7 @@ class CorrsearchSnuffling(Snuffling):
c = trace.correlate(a,b, mode='valid', normalization=normalization)
c.shift(-c.tmin + b.tmin)
c.meta = { 'tabu' : True }
if scc is None:
scc = c.copy()
scc.wmin = b.wmin
@ -90,7 +90,7 @@ class CorrsearchSnuffling(Snuffling):
else:
scc.add(c)
sccn += 1
if scc is not None:
scc.ydata /= sccn
scc.chop(scc.wmin, scc.wmax)
@ -99,21 +99,22 @@ class CorrsearchSnuffling(Snuffling):
for t, a in zip(*scc.peaks(self.threshold, tsearch=2./self.corner_highpass)):
m = EventMarker(model.Event(time=t, lat=0., lon=0., name='Event(%.2g)' % a))
markers.append(m)
if viewer:
self.add_traces([scc])
self.add_markers(markers)
else:
io.save([scc], self.out_path, format='from_extension')
def __snufflings__():
'''Returns a list of snufflings to be exported by this module.'''
return [ CorrsearchSnuffling() ]
return [CorrsearchSnuffling()]
if __name__ == '__main__':
snuf = CorrsearchSnuffling()
snuf.setup()
snuf.apply_to_all = True
@ -123,4 +124,3 @@ if __name__ == '__main__':
snuf.master_tmin, snuf.master_tmax = m.tmin, m.tmax
snuf.out_path = 'corr/%(tmin)s.yaff'
snuf.call()

+ 2
- 2
drumplot.py View File

@ -4,9 +4,9 @@ import matplotlib.pyplot as plt
import copy
from pyrocko import util, trace
from pyrocko.snuffling import Snuffling, Choice, Switch, Param
from pyrocko.gui.snuffling import Snuffling, Choice, Switch, Param
logger = logging.getLogger('pyrocko.snuffling.drumplot')
logger = logging.getLogger('pyrocko.gui.snuffling.drumplot')
class DrumPlot(Snuffling):


+ 3
- 3
export_waveforms.py View File

@ -1,6 +1,6 @@
from pyrocko import io, io_common
from pyrocko import io
from pyrocko import model
from pyrocko.snuffling import Snuffling, Choice, Switch, Param
from pyrocko.gui.snuffling import Snuffling, Choice, Switch, Param
class ExportWaveforms(Snuffling):
@ -86,7 +86,7 @@ class ExportWaveforms(Snuffling):
format=self.format,
overwrite=True)
except io_common.FileSaveError as e:
except io.io_common.FileSaveError as e:
self.fail(str(e))
if self.save_stations:


+ 1
- 1
extract_catalog.py View File

@ -1,5 +1,5 @@
from pyrocko import model
from pyrocko.snuffling import Snuffling
from pyrocko.gui.snuffling import Snuffling
class ExtractEvents(Snuffling):


+ 1
- 1
extract_events.py View File

@ -1,6 +1,6 @@
import sys
from pyrocko import util, io
from pyrocko.snuffling import Snuffling, load_markers, Param, NoViewerSet
from pyrocko.gui.snuffling import Snuffling, load_markers, Param, NoViewerSet
default_output_filename = '%(eventname)s_%(network)s.%(station)s.%(location)s.%(channel)s.mseed'


+ 2
- 2
fk_parstack.py View File

@ -6,7 +6,7 @@ import numpy as num
import time
from matplotlib.animation import FuncAnimation
from pyrocko.snuffling import Param, Snuffling, Choice, Switch
from pyrocko.gui.snuffling import Param, Snuffling, Choice, Switch
from scipy.signal import fftconvolve, lfilter, hilbert
from scipy.interpolate import UnivariateSpline
from pyrocko import orthodrome as ortho
@ -17,7 +17,7 @@ from pyrocko import model
import logging
logger = logging.getLogger('pyrocko.snufflings.fk_parstack.py')
logger = logging.getLogger('pyrocko.gui.snufflings.fk_parstack.py')
d2r = num.pi/180.
km = 1000.


+ 6
- 4
hyposat-snuffling/snuffling.py View File

@ -1,15 +1,17 @@
from __future__ import print_function
from pyrocko.snuffling import Snuffling, Switch, Param, Choice
from pyrocko.pile_viewer import EventMarker, PhaseMarker
from pyrocko import util, model, orthodrome, gmtpy
from subprocess import Popen, PIPE, check_call
import os
import tempfile
import math
import glob
import numpy as num
from pyrocko.gui.snuffling import Snuffling, Switch, Param, Choice
from pyrocko.gui.pile_viewer import EventMarker, PhaseMarker
from pyrocko import util, model, orthodrome
from pyrocko.plot import gmtpy
from subprocess import Popen, PIPE, check_call
deg2rad = math.pi/180.
pjoin = os.path.join


+ 1
- 1
kiwi_seismosizer.py View File

@ -3,7 +3,7 @@ import re
import copy
import logging
from pyrocko.snuffling import Snuffling, Param
from pyrocko.gui.snuffling import Snuffling, Param
from pyrocko import model, eventdata
logger = logging.getLogger('seismosizer')


+ 2
- 2
local_magnitude.py View File

@ -4,10 +4,10 @@ import os
import copy
import numpy as num
from collections import defaultdict
from pyrocko.snuffling import Snuffling, Param, PhaseMarker, Switch, Choice, \
from pyrocko.gui.snuffling import Snuffling, Param, PhaseMarker, Switch, Choice, \
EventMarker
from pyrocko import guts, orthodrome, trace
from pyrocko.gui_util import to01
from pyrocko.gui.gui_util import to01
from pyrocko.plot import graph_colors
__author__ = 'Catarina Matos (cpfcmatos@gmail.com)'


+ 6
- 3
map/snuffling.py View File

@ -3,12 +3,15 @@ import tempfile
import shutil
import numpy as num
from pyrocko.snuffling import Snuffling, Switch, Choice, NoViewerSet
from pyrocko import util, gui_util, model, orthodrome as ortho
from pyrocko import util, model, orthodrome as ortho
from pyrocko import moment_tensor
from pyrocko.automap import Map
from pyrocko.gui.snuffling import Snuffling, Switch, Choice, NoViewerSet
from pyrocko.gui import gui_util
from pyrocko.plot.automap import Map
from xmlMarker import XMLEventMarker, EventMarkerList, XMLStationMarker
from xmlMarker import StationMarkerList, MarkerLists, dump_xml
from PyQt4.QtCore import QUrl
from PyQt4.QtGui import QDesktopServices


+ 1
- 1
notch.py View File

@ -1,7 +1,7 @@
from pyrocko import trace
import math
import numpy as num
from pyrocko.snuffling import Param, Snuffling, Switch
from pyrocko.gui.snuffling import Param, Snuffling, Switch
import scipy.signal as S
import scipy.stats as SS


+ 1
- 1
obspy_fk_analyse_polar.py View File

@ -1,5 +1,5 @@
from __future__ import print_function
from pyrocko.snuffling import Param, Snuffling, Choice
from pyrocko.gui.snuffling import Param, Snuffling, Choice
import numpy as num


+ 2
- 2
okada/snuffling.py View File

@ -1,13 +1,13 @@
import numpy
from matplotlib import pylab as plt
from pyrocko.snuffling import Snuffling, Param
from pyrocko.gui.snuffling import Snuffling, Param
from pyrocko import io
from pyrocko import util
from pyrocko import trace
import logging
logger = logging.getLogger('pyrocko.snuffling.okada')
logger = logging.getLogger('pyrocko.gui.snuffling.okada')
try:
import okada


+ 2
- 2
particle_motion.py View File

@ -6,10 +6,10 @@ import copy
from matplotlib.collections import LineCollection
from mpl_toolkits.mplot3d import Axes3D # noqa
from pyrocko import util
from pyrocko.snuffling import Snuffling, Choice, Switch
from pyrocko.gui.snuffling import Snuffling, Choice, Switch
logger = logging.getLogger('pyrocko.snuffling.particle_motion')
logger = logging.getLogger('pyrocko.gui.snuffling.particle_motion')
class ParticleMotion(Snuffling):


+ 1
- 1
plot_traces.py View File

@ -1,5 +1,5 @@
import numpy as num
from pyrocko.snuffling import Snuffling, Param, Choice, Switch
from pyrocko.gui.snuffling import Snuffling, Param, Choice, Switch
from pyrocko import orthodrome as ortho
from pyrocko import util


+ 1
- 1
psd.py View File

@ -1,4 +1,4 @@
from pyrocko.snuffling import Snuffling, Param, Switch
from pyrocko.gui.snuffling import Snuffling, Param, Switch
import numpy as num
from pyrocko.plot import graph_colors as colors


+ 1
- 1
seismosizer.py View File

@ -2,7 +2,7 @@ import numpy as num
import os
from pyrocko import moment_tensor, model
from pyrocko.snuffling import Snuffling, Param, Choice, EventMarker
from pyrocko.gui.snuffling import Snuffling, Param, Choice, EventMarker
from pyrocko import gf
km = 1000.


+ 1
- 1
spectrogram.py View File

@ -1,5 +1,5 @@
import math
from pyrocko.snuffling import Snuffling, Param, Choice, Switch
from pyrocko.gui.snuffling import Snuffling, Param, Choice, Switch
import numpy as num
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.colors import LinearSegmentedColormap


+ 2
- 2
time_line.py View File

@ -1,5 +1,5 @@
from pyrocko.snuffling import Snuffling, Param
from pyrocko.gui_util import EventMarker
from pyrocko.gui.snuffling import Snuffling, Param
from pyrocko.gui.gui_util import EventMarker
from pyrocko.orthodrome import distance_accurate50m as distance
from pyrocko import util, model
import matplotlib.dates as mdates


+ 1
- 1
vtk-map/snuffling.py View File

@ -1,6 +1,6 @@
import numpy as num
from pyrocko.snuffling import Snuffling, Param, Switch
from pyrocko.gui.snuffling import Snuffling, Param, Switch
from pyrocko import orthodrome as ortho


Loading…
Cancel
Save