├── .gitignore ├── Makefile ├── README.md ├── docs └── HASH_manual_v1.2.pdf ├── hashpy ├── __init__.py ├── data │ ├── dbhash.pf │ ├── vz.kds │ ├── vz.kds_orig │ ├── vz.lab1 │ ├── vz.north │ ├── vz.pickema1 │ ├── vz.pickema2 │ ├── vz.pickema3 │ ├── vz.sgm1 │ ├── vz.socal │ └── vz.vb1 ├── doublecouple.py ├── examples │ └── hash_example2.py ├── hashpype.py ├── io │ ├── __init__.py │ ├── antelopeIO.py │ ├── core.py │ ├── fpfitIO.py │ └── obspyIO.py ├── plotting │ ├── __init__.py │ └── focalmechplotter.py ├── scripts │ ├── __init__.py │ ├── dbhash │ ├── hash_driver2.py │ └── hash_utils.py ├── src │ ├── Makefile │ ├── fmamp_subs.f │ ├── fmech_subs.f │ ├── param.inc │ ├── pol_subs.f │ ├── rot.inc │ ├── station_subs.f │ ├── station_subs_5char.f │ ├── uncert_subs.f │ ├── util_subs.f │ ├── vel.inc │ ├── vel_subs.f │ └── vel_subs2.f └── tests │ ├── data │ ├── example1.inp │ ├── example1.out │ ├── example1.out2 │ ├── example2.inp │ ├── example2.out │ ├── example2.out2 │ ├── example3.inp │ ├── example3.out │ ├── example4.inp │ ├── example4.out │ ├── example4.out2 │ ├── example5.inp │ ├── example5.out │ ├── example5.out2 │ ├── north1.phase │ ├── north2.phase │ ├── north3.amp │ ├── north3.statcor │ ├── north4.phase │ ├── north5.simul │ ├── scsn.reverse │ ├── scsn.stations │ ├── scsn.stations_5char │ ├── vz.kds │ ├── vz.kds_orig │ ├── vz.lab1 │ ├── vz.north │ ├── vz.pickema1 │ ├── vz.pickema2 │ ├── vz.pickema3 │ ├── vz.sgm1 │ ├── vz.socal │ └── vz.vb1 │ ├── test_dbhash.py │ └── test_hashpype.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *DS_Store 2 | *.pyc 3 | *.o 4 | *.so 5 | *settings.py 6 | test2.out 7 | test2.out2 8 | *.png 9 | *.egg-info 10 | *.json 11 | examples 12 | build 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # HASHpype Makefile 2 | # 3 | # - Mark Williams 2012.320 4 | # Based on HASH Makefile 5 | 6 | SRCF= fmech_subs.f uncert_subs.f util_subs.f \ 7 | pol_subs.f vel_subs.f station_subs.f vel_subs2.f 8 | 9 | SRC= $(addprefix hashpy/src/, $(SRCF)) 10 | 11 | # HASHpype library module: 12 | hashpy: libhashpy.so 13 | 14 | libhashpy.so: Makefile $(SRC) 15 | f2py -c -m libhashpy $(SRC) 16 | mv libhashpy.so hashpy 17 | 18 | .PHONY : install 19 | install : libhashpy.so 20 | python setup.py install 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HASHpy 2 | ------ 3 | 4 | [![DOI](https://zenodo.org/badge/3723/markcwill/hashpy.png)](http://dx.doi.org/10.5281/zenodo.9808) 5 | 6 | This is a fork of HASH v1.2, the first motion focal mechanism program by Hardebeck and Shearer. The subroutines (in Fortran 77, which I did not write) are compiled into a python module, 'libhashpy.so', which will import all the subs and common blocks into the python namespace. There is a base class, HashPype, that contains attributes which hold data for a HASH calculation, and methods which can be called to do the HASH calculation. This class facilitates easily writing a 'hash driver' script in python. See below for details. 7 | 8 | Note: As stated in the in-code docs, the current code is based on the 'hashdriver2' script, and as such, does not utilize the 'amp' routines for S/P amplitude measurements. This will most likely be added in the near future. If someone wants to take it upon themselves to add the compiler directives in the source and the methods to the HashPype class, throw me a pull request. 9 | 10 | ### Installation 11 | 12 | The latest version of this code uses `numpy.distutils`, which can nicely compile Fortran code. The source code and makefiles to remake the libhashpy module are installed to the hashpy folder, so with a little hacking, one could just remake them in place, if one wanted to change the source code. 13 | 14 | For basic install: 15 | 16 | ```shell 17 | # First, install dependencies. Then cd to this top directory and: 18 | python setup.py install 19 | 20 | # or use pip 21 | pip install git+https://github.com/markcwill/hashpy.git 22 | 23 | ``` 24 | 25 | ### Testing and Usage 26 | 27 | For lower-level programming, the Fortran subroutines are available in `hashpy.libhashpy` 28 | 29 | ```python 30 | In [1]: from hashpy import libhashpy 31 | 32 | In [2]: libhashpy? 33 | Type: module 34 | Base Class: 35 | String Form: 36 | Namespace: Interactive 37 | File: /opt/antelope/python2.7.2-64/lib/python2.7/site-packages/hashpy/libhashpy.so 38 | Docstring: 39 | This module 'libhashpy' is auto-generated with f2py (version:1). 40 | Functions: 41 | nf,strike,dip,rake,faults,slips = focalmc(p_azi_mc,p_the_mc,p_pol,p_qual,nmc,dang,maxout,nextra,ntotal,npsta=len(p_pol)) 42 | nsltn,str_avg,dip_avg,rak_avg,prob,rms_diff = mech_prob(norm1in,norm2in,cangle,prob_max,nf=shape(norm1in,1)) 43 | norm1_avg,norm2_avg = mech_avg(norm1,norm2,nf=shape(norm1,1)) 44 | rota = mech_rot(norm1,norm2,slip1,slip2) 45 | v3 = cross(v1,v2) 46 | to_car(the,phi,r,x,y,z) 47 | fpcoor(strike,dip,rake,fnorm,slip,idir) 48 | fran = ran_norm() 49 | mfrac,stdr = get_misf(p_azi_mc,p_the_mc,p_pol,p_qual,str_avg,dip_avg,rak_avg,npol=len(p_azi_mc)) 50 | magap,mpgap = get_gap(p_azi_mc,p_the_mc,npol=len(p_azi_mc)) 51 | sort(ra,n=len(ra)) 52 | ntab = mk_table(ntab) 53 | tt,iflag = get_tts(ip,del,qdep) 54 | layertrace(p1,h1,utop1,ubot1,imth,dx1,dt1,irtr) 55 | flat,flon,felev = getstat_tri(stlfile,snam,scom,snet) 56 | stpol = check_pol(polfile,snam,evyr,evmon,evdy,evhr) 57 | qcor = get_cor(stlfile,snam,scom,snet) 58 | ntab = mk_table_add(ind,vmodel) 59 | COMMON blocks: 60 | /angtable/ table(101,14,10),delttab(101),deptab(14),ndel,ndep 61 | . 62 | 63 | In [3]: 64 | ``` 65 | 66 | ### Input/Output 67 | 68 | Data can be input into HASH in various formats. This is currently handled in HASHpy by registering a format in the `hashpy.io` module by adding a module/functions to the dictionary in `hashpy.io.core`. (May change in future releases). I/O functions are then called by the HashPype methods `HashPype.input()` and `HashPype.output()`. If the 'output' method is called with no format it will return a simple string with the event ID with the best strike/dip/rake 69 | 70 | Currently Supports: 71 | * ObsPy Event object I/O 72 | * Antelope Datascope database I/O 73 | 74 | ```python 75 | # Usage example: 76 | # Typical "hash_driver2" style script 77 | # Using the ObsPy Event format as input for origin, picks, and arrivals 78 | 79 | from hashpy import HashPype, HashError 80 | 81 | # Make an ObsPy Event, or get from a QuakeML file 82 | from obspy.core.event import readEvents 83 | event = readEvents('my_quakeml_file.xml').events[0] 84 | 85 | # Set configuration at creation with a dict... 86 | # ...can from file or interactively, etc 87 | config = { "npolmin" : 10, 88 | "max_agap": 90, 89 | "vmodels" : ['/path/to/my/vmodel/file1.vz', 90 | '/new/picking/model/file2.vz', 91 | ] 92 | } 93 | 94 | hp = HashPype(**config) 95 | hp.input(event, format="OBSPY") 96 | hp.load_velocity_models() 97 | hp.generate_trial_data() 98 | hp.calculate_takeoff_angles() 99 | 100 | pass1 = hp.check_minimum_polarity() 101 | pass2 = hp.check_maximum_gap() 102 | 103 | if pass1 and pass2: 104 | hp.calculate_hash_focalmech() 105 | hp.calculate_quality() 106 | print hp.output() # default output is a simple string 107 | else: 108 | raise HashError("Didn't pass user checks!") 109 | 110 | ``` 111 | 112 | ### Plotting 113 | 114 | A trial implementation of plotting exists, using `matplotlib` and the `mplstereonet` package, as the `hashpy.plotting.focalmechplotter.FocalMechPlotter` class. It accepts an ObsPy Event containing Picks, Origin/Arrivals, FocalMechanism, etc, objects (as output from HashPype) and generates a stereonet plot. Multiple FocalMechansim solutions from HASH are accessible through the navigation toolbar 'back' and 'forward' arrows. 115 | 116 | ```python 117 | # Get an obspy Event object as output 118 | >>> event = hp.output(format="OBSPY") 119 | # Pass to plotter class as constructor variable 120 | >>> fmp = FocalMechPlotter(event) 121 | # Plots a figure, accessible as 'fmp.fig' 122 | ``` 123 | ![](http://markcwill.github.io/hashpy/images/979567_focalmech.png) 124 | 125 | ### Dependencies 126 | 127 | #### Required 128 | * Fortran compiler + library (tested with gfortran + libgfortran3) 129 | * NumPy (main dependancy, for numerical arrays and f2py compiling) 130 | 131 | #### Optional 132 | * [ObsPy](https://github.com/obspy/obspy.git) (Only for plotting and ObsPy I/O)) 133 | * [mplstereonet](https://github.com/joferkington/mplstereonet.git) (Only for plotting) 134 | * [Antelope](http://www.brtt.com) (Only for Antelope database I/O) 135 | 136 | ### HASH references 137 | 138 | * Hardebeck, Jeanne L. and Peter M. Shearer, A new method for determining first- 139 | motion focal mechanisms, Bulletin of the Seismological Society of America, 92, 140 | 2264-2276, 2002. 141 | * Hardebeck, Jeanne L. and Peter M. Shearer, Using S/P Amplitude Ratios to 142 | Constrain the Focal Mechanisms of Small Earthquakes, Bulletin of the 143 | Seismological Society of America, 93, 2434-2444, 2003. 144 | 145 | ### Future 146 | Add remaining HASH routines (like those in fmamp_subs.f) to wrapped library and class methods. 147 | 148 | If I ever get ambitious, I would redo the structure of some of the Fortran subroutines (already started this with vel-subs2) and rewrite them in Fortran 90/95/2003. Probably couldn't ditch the common blocks without a full rewrite, but at least try and get rid of the GOTOs. Biggest improvement would be allocatable arrays, so you could avoid the includes and max-size arrays. 149 | 150 | There will probably be small adjustments to the locations and structure of what functions are in what files, but the HashPype class and methods will be the main way to interact with HASH. 151 | 152 | -------------------------------------------------------------------------------- /docs/HASH_manual_v1.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markcwill/hashpy/d6a334717e603936cf537646955b0c114c9bedf6/docs/HASH_manual_v1.2.pdf -------------------------------------------------------------------------------- /hashpy/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | HASHpy 4 | 5 | Module for calculating first motion focal mechanisms for earthquakes 6 | using Python and HASH 7 | 8 | :copyright: 9 | Mark C. Williams 10 | 11 | """ 12 | 13 | from hashpype import HashPype, HashError 14 | from doublecouple import DoubleCouple 15 | 16 | __version__ = "0.5.6" 17 | 18 | -------------------------------------------------------------------------------- /hashpy/data/dbhash.pf: -------------------------------------------------------------------------------- 1 | # pf file for dbhash 2 | # 3 | # These are parameters passed to the interactive version of HASH. 4 | # They are used to constrain various things during runtime. An 5 | # additional constraint is found in the include files for the FORTRAN 6 | # routines, but libhashpy must be recompiled if those files are changed. 7 | 8 | npolmin 8 # Enter mininum number of polarities (e.g., 8) 9 | max_agap 90 # Enter maximum azimuthal gap (e.g., 90) 10 | max_pgap 60 # Enter maximum takeoff angle gap (e.g., 60) 11 | dang 5 # Enter grid angle for focal mech search, in degrees 5(min {0}) 12 | nmc 25 # Enter number of trials (e.g., 30) 13 | maxout 100 # Enter maxout for focal mech. output (e.g., 500) 14 | badfrac 0.1 # Enter fraction of picks presumed bad (e.g., 0.10) 15 | delmax 500 # Enter maximum allowed source-station distance, in km (e.g., 120) 16 | cangle 45 # Enter angle for computing mechanisms probability, in degrees (e.g., 45) 17 | prob_max 0.25 # Enter probability threshold for multiples (e.g., 0.1) 18 | 19 | # Added by Mark ----------------------------------# 20 | # Directory containing velocity model files: 21 | vmodel_dir /home/markwill/Code/python/hashpy/hashpy/data 22 | 23 | # List of velocity model file names: 24 | # Format: z (km) v (km/s) 25 | vmodels &Tbl{ 26 | vz.pickema1 27 | vz.pickema2 28 | vz.pickema3 29 | } 30 | -------------------------------------------------------------------------------- /hashpy/data/vz.kds: -------------------------------------------------------------------------------- 1 | 0.00 3.0000 2 | 1.00 4.5000 3 | 2.00 5.5000 4 | 3.00 5.6000 5 | 4.00 5.7000 6 | 5.00 5.8000 7 | 6.00 5.9000 8 | 7.00 6.0000 9 | 8.00 6.0182 10 | 9.00 6.0364 11 | 10.00 6.0545 12 | 11.00 6.0727 13 | 12.00 6.0909 14 | 13.00 6.1091 15 | 14.00 6.1273 16 | 15.00 6.1455 17 | 16.00 6.1636 18 | 17.00 6.1818 19 | 18.00 6.2000 20 | 19.00 6.2300 21 | 20.00 6.2600 22 | 21.00 6.2900 23 | 22.00 6.3200 24 | 23.00 6.3500 25 | 24.00 6.3800 26 | 25.00 6.4100 27 | 26.00 6.4400 28 | 27.00 6.4700 29 | 28.00 6.5000 30 | 29.00 6.6300 31 | 30.00 6.7600 32 | 31.00 6.8900 33 | 32.00 7.0200 34 | 33.00 7.1500 35 | 34.00 7.2800 36 | 35.00 7.4100 37 | 36.00 7.5400 38 | 37.00 7.6700 39 | 38.00 7.8000 40 | 39.00 7.8182 41 | 40.00 7.8364 42 | 41.00 7.8545 43 | 42.00 7.8727 44 | 43.00 7.8909 45 | 44.00 7.9091 46 | 45.00 7.9273 47 | 46.00 7.9455 48 | 47.00 7.9636 49 | 48.00 7.9818 50 | 49.00 8.0000 51 | 50.00 8.0182 52 | 51.00 8.0364 53 | 52.00 8.0545 54 | 53.00 8.0727 55 | 54.00 8.0909 56 | 55.00 8.1091 57 | 56.00 8.1273 58 | 57.00 8.1455 59 | 58.00 8.1636 60 | 59.00 8.1818 61 | 60.00 8.2000 62 | 100.00 9.0 63 | -------------------------------------------------------------------------------- /hashpy/data/vz.kds_orig: -------------------------------------------------------------------------------- 1 | 0.0 3.0 2 | 1.0 4.5 3 | 2.0 5.5 4 | 7.0 6.0 5 | 18.0 6.2 6 | 28.0 6.5 7 | 38.0 7.8 8 | 60.0 8.2 9 | 100.0 10.2 10 | -------------------------------------------------------------------------------- /hashpy/data/vz.lab1: -------------------------------------------------------------------------------- 1 | 0.0 2.9300 2 | 1.0 3.5000 3 | 2.0 4.0667 4 | 3.0 4.6333 5 | 4.0 5.2000 6 | 5.0 5.4000 7 | 6.0 5.6000 8 | 7.0 5.8500 9 | 8.0 6.1000 10 | 9.0 6.1750 11 | 10.0 6.2500 12 | 11.0 6.3250 13 | 12.0 6.4000 14 | 13.0 6.4250 15 | 14.0 6.4500 16 | 15.0 6.4750 17 | 16.0 6.5000 18 | 17.0 6.5500 19 | 18.0 6.6000 20 | 19.0 6.6500 21 | 20.0 6.7000 22 | 21.0 6.7500 23 | 22.0 6.8000 24 | 23.0 6.8500 25 | 24.0 6.9000 26 | 25.0 6.9500 27 | 26.0 7.0000 28 | 27.0 7.0500 29 | 28.0 7.1000 30 | 29.0 7.1500 31 | 30.0 7.2000 32 | 31.0 7.2500 33 | 32.0 7.6700 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/data/vz.north: -------------------------------------------------------------------------------- 1 | 0.0 4.0200 2 | 1.0 4.2800 3 | 2.0 4.5350 4 | 3.0 4.7900 5 | 4.0 5.0450 6 | 5.0 5.3000 7 | 6.0 5.5900 8 | 7.0 5.6725 9 | 8.0 5.7550 10 | 9.0 5.8375 11 | 10.0 5.9200 12 | 11.0 6.0527 13 | 12.0 6.1855 14 | 13.0 6.3182 15 | 14.0 6.4509 16 | 15.0 6.5836 17 | 16.0 6.6800 18 | 17.0 6.7200 19 | 18.0 6.7400 20 | 19.0 6.7600 21 | 20.0 6.7800 22 | 21.0 6.8000 23 | 22.0 6.8200 24 | 23.0 6.8256 25 | 24.0 6.8311 26 | 25.0 6.8367 27 | 26.0 6.8422 28 | 27.0 6.8478 29 | 28.0 6.8533 30 | 29.0 6.8589 31 | 30.0 6.8644 32 | 31.0 6.8700 33 | 32.0 7.4800 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/data/vz.pickema1: -------------------------------------------------------------------------------- 1 | 0.00 3.0000 2 | 1.00 5.0000 3 | 2.00 6.0000 4 | 3.00 6.0385 5 | 4.00 6.0769 6 | 5.00 6.1154 7 | 6.00 6.1538 8 | 7.00 6.1923 9 | 8.00 6.2308 10 | 9.00 6.2692 11 | 10.00 6.3077 12 | 11.00 6.3462 13 | 12.00 6.3846 14 | 13.00 6.4231 15 | 14.00 6.4615 16 | 15.00 6.5000 17 | 16.00 6.5286 18 | 17.00 6.5571 19 | 18.00 6.5857 20 | 19.00 6.6143 21 | 20.00 6.6429 22 | 21.00 6.6714 23 | 22.00 6.7000 24 | 23.00 6.8917 25 | 24.00 7.0833 26 | 25.00 7.2750 27 | 26.00 7.4667 28 | 27.00 7.6583 29 | 28.00 7.8500 30 | 29.00 7.8609 31 | 30.00 7.8719 32 | 31.00 7.8828 33 | 32.00 7.8937 34 | 33.00 7.9047 35 | 34.00 7.9156 36 | 35.00 7.9266 37 | 36.00 7.9375 38 | 37.00 7.9484 39 | 38.00 7.9594 40 | 39.00 7.9703 41 | 40.00 7.9812 42 | 41.00 7.9922 43 | 42.00 8.0031 44 | 43.00 8.0141 45 | 44.00 8.0250 46 | 45.00 8.0359 47 | 46.00 8.0469 48 | 47.00 8.0578 49 | 48.00 8.0688 50 | 49.00 8.0797 51 | 50.00 8.0906 52 | 51.00 8.1016 53 | 52.00 8.1125 54 | 53.00 8.1234 55 | 54.00 8.1344 56 | 55.00 8.1453 57 | 56.00 8.1563 58 | 57.00 8.1672 59 | 58.00 8.1781 60 | 59.00 8.1891 61 | 60.00 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/data/vz.pickema2: -------------------------------------------------------------------------------- 1 | 0.00 5.8500 2 | 1.00 5.8714 3 | 2.00 5.8929 4 | 3.00 5.9143 5 | 4.00 5.9357 6 | 5.00 5.9571 7 | 6.00 5.9786 8 | 7.00 6.0000 9 | 8.00 6.0467 10 | 9.00 6.0933 11 | 10.00 6.1400 12 | 11.00 6.1867 13 | 12.00 6.2333 14 | 13.00 6.2800 15 | 14.00 6.3267 16 | 15.00 6.3733 17 | 16.00 6.4200 18 | 17.00 6.4667 19 | 18.00 6.5133 20 | 19.00 6.5600 21 | 20.00 6.6067 22 | 21.00 6.6533 23 | 22.00 6.7000 24 | 23.00 6.8917 25 | 24.00 7.0833 26 | 25.00 7.2750 27 | 26.00 7.4667 28 | 27.00 7.6583 29 | 28.00 7.8500 30 | 29.00 7.8609 31 | 30.00 7.8719 32 | 31.00 7.8828 33 | 32.00 7.8937 34 | 33.00 7.9047 35 | 34.00 7.9156 36 | 35.00 7.9266 37 | 36.00 7.9375 38 | 37.00 7.9484 39 | 38.00 7.9594 40 | 39.00 7.9703 41 | 40.00 7.9812 42 | 41.00 7.9922 43 | 42.00 8.0031 44 | 43.00 8.0141 45 | 44.00 8.0250 46 | 45.00 8.0359 47 | 46.00 8.0469 48 | 47.00 8.0578 49 | 48.00 8.0688 50 | 49.00 8.0797 51 | 50.00 8.0906 52 | 51.00 8.1016 53 | 52.00 8.1125 54 | 53.00 8.1234 55 | 54.00 8.1344 56 | 55.00 8.1453 57 | 56.00 8.1563 58 | 57.00 8.1672 59 | 58.00 8.1781 60 | 59.00 8.1891 61 | 60.00 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/data/vz.pickema3: -------------------------------------------------------------------------------- 1 | 0.00 3.0000 2 | 1.00 4.0000 3 | 2.00 5.2333 4 | 3.00 6.4667 5 | 3.50 5.8800 6 | 4.50 5.9100 7 | 5.50 5.9400 8 | 6.50 5.9700 9 | 7.50 6.0000 10 | 8.50 6.0625 11 | 9.50 6.1250 12 | 10.50 6.1875 13 | 11.50 6.2500 14 | 12.50 6.3125 15 | 13.50 6.3750 16 | 14.50 6.4375 17 | 15.50 6.5000 18 | 16.50 6.5286 19 | 17.50 6.5571 20 | 18.50 6.5857 21 | 19.50 6.6143 22 | 20.50 6.6429 23 | 21.50 6.6714 24 | 22.50 6.7000 25 | 23.50 6.8917 26 | 24.50 7.0833 27 | 25.50 7.2750 28 | 26.50 7.4667 29 | 27.50 7.6583 30 | 28.50 7.8500 31 | 29.50 7.8611 32 | 30.50 7.8722 33 | 31.50 7.8833 34 | 32.50 7.8944 35 | 33.50 7.9056 36 | 34.50 7.9167 37 | 35.50 7.9278 38 | 36.50 7.9389 39 | 37.50 7.9500 40 | 38.50 7.9611 41 | 39.50 7.9722 42 | 40.50 7.9833 43 | 41.50 7.9944 44 | 42.50 8.0056 45 | 43.50 8.0167 46 | 44.50 8.0278 47 | 45.50 8.0389 48 | 46.50 8.0500 49 | 47.50 8.0611 50 | 48.50 8.0722 51 | 49.50 8.0833 52 | 50.50 8.0944 53 | 51.50 8.1056 54 | 52.50 8.1167 55 | 53.50 8.1278 56 | 54.50 8.1389 57 | 55.50 8.1500 58 | 56.50 8.1611 59 | 57.50 8.1722 60 | 58.50 8.1833 61 | 59.50 8.1944 62 | 60.50 8.2056 63 | -------------------------------------------------------------------------------- /hashpy/data/vz.sgm1: -------------------------------------------------------------------------------- 1 | 0.0 5.0700 2 | 1.0 5.3000 3 | 2.0 5.5333 4 | 3.0 5.7667 5 | 4.0 6.0000 6 | 5.0 6.0500 7 | 6.0 6.1000 8 | 7.0 6.1500 9 | 8.0 6.2000 10 | 9.0 6.2500 11 | 10.0 6.3000 12 | 11.0 6.3500 13 | 12.0 6.4000 14 | 13.0 6.4000 15 | 14.0 6.4000 16 | 15.0 6.4000 17 | 16.0 6.4000 18 | 17.0 6.4500 19 | 18.0 6.5000 20 | 19.0 6.5500 21 | 20.0 6.6000 22 | 21.0 6.6500 23 | 22.0 6.7000 24 | 23.0 6.7500 25 | 24.0 6.8000 26 | 25.0 6.8500 27 | 26.0 6.9000 28 | 27.0 6.9500 29 | 28.0 7.0000 30 | 29.0 7.0500 31 | 30.0 7.1000 32 | 31.0 7.1500 33 | 32.0 7.6200 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/data/vz.socal: -------------------------------------------------------------------------------- 1 | 0.0 4.7000 2 | 1.0 4.9909 3 | 2.0 5.2818 4 | 3.0 5.5727 5 | 4.0 5.8636 6 | 5.0 6.1545 7 | 6.0 6.3075 8 | 7.0 6.3226 9 | 8.0 6.3377 10 | 9.0 6.3528 11 | 10.0 6.3679 12 | 11.0 6.3830 13 | 12.0 6.3981 14 | 13.0 6.4132 15 | 14.0 6.4283 16 | 15.0 6.4434 17 | 16.0 6.4585 18 | 17.0 6.4736 19 | 18.0 6.4887 20 | 19.0 6.5038 21 | 20.0 6.5189 22 | 21.0 6.5340 23 | 22.0 6.5491 24 | 23.0 6.5642 25 | 24.0 6.5792 26 | 25.0 6.5943 27 | 26.0 6.6094 28 | 27.0 6.6245 29 | 28.0 6.6396 30 | 29.0 6.6547 31 | 30.0 6.6698 32 | 31.0 6.6849 33 | 32.0 6.7000 34 | 33.0 7.8036 35 | 34.0 7.8071 36 | 35.0 7.8107 37 | 36.0 7.8143 38 | 37.0 7.8179 39 | 38.0 7.8214 40 | 39.0 7.8250 41 | 40.0 7.8286 42 | 41.0 7.8321 43 | 42.0 7.8357 44 | 43.0 7.8393 45 | 44.0 7.8429 46 | 45.0 7.8464 47 | 46.0 7.8500 48 | 47.0 7.8536 49 | 48.0 7.8571 50 | 49.0 7.8607 51 | 50.0 7.8643 52 | 51.0 7.8679 53 | 52.0 7.8714 54 | 53.0 7.8750 55 | 54.0 7.8786 56 | 55.0 7.8821 57 | 56.0 7.8857 58 | 57.0 7.8893 59 | 58.0 7.8929 60 | 59.0 7.8964 61 | 60.0 7.9000 62 | -------------------------------------------------------------------------------- /hashpy/data/vz.vb1: -------------------------------------------------------------------------------- 1 | 0.0 3.4300 2 | 1.0 3.7000 3 | 2.0 3.9667 4 | 3.0 4.2333 5 | 4.0 4.5000 6 | 5.0 5.0000 7 | 6.0 5.5000 8 | 7.0 5.5500 9 | 8.0 5.6000 10 | 9.0 5.7000 11 | 10.0 5.8000 12 | 11.0 5.9000 13 | 12.0 6.0000 14 | 13.0 6.1750 15 | 14.0 6.3500 16 | 15.0 6.5250 17 | 16.0 6.7000 18 | 17.0 6.7250 19 | 18.0 6.7500 20 | 19.0 6.7750 21 | 20.0 6.8000 22 | 21.0 6.8255 23 | 22.0 6.8509 24 | 23.0 6.8764 25 | 24.0 6.9018 26 | 25.0 6.9273 27 | 26.0 6.9527 28 | 27.0 6.9782 29 | 28.0 7.0036 30 | 29.0 7.0291 31 | 30.0 7.0545 32 | 31.0 7.0800 33 | 32.0 7.5850 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/doublecouple.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Calulator for getting double couple information 4 | 5 | :copyright: 6 | Mark Williams (2013) 7 | Nevada Seismological Laboratory 8 | 9 | """ 10 | 11 | import numpy as np 12 | 13 | class NodalPlane(list): 14 | """ 15 | List to hold strike, dip, rake of a nodal plane 16 | 17 | Overview 18 | -------- 19 | Basically, a list consisting of: 20 | [strike, dip, rake] 21 | with each element accessible by name as well as index. 22 | 23 | Construct with sequence, list, or named keyword args, see 24 | constructor doc for details. 25 | 26 | 27 | :type strike: int or float 28 | :param strike: degrees of strike 29 | :type dip: int or float 30 | :param dip: degrees of dip 31 | :type rake: int or float 32 | :param rake: degrees of rake 33 | 34 | """ 35 | 36 | @property 37 | def strike(self): 38 | return self[0] 39 | @strike.setter 40 | def strike(self, value): 41 | self[0] = value 42 | 43 | @property 44 | def dip(self): 45 | return self[1] 46 | @dip.setter 47 | def dip(self, value): 48 | self[1] = value 49 | 50 | @property 51 | def rake(self): 52 | return self[2] 53 | @rake.setter 54 | def rake(self, value): 55 | self[2] = value 56 | 57 | def __init__(self, *args, **kwargs): 58 | """ 59 | Build as a list or use keywords 60 | 61 | :param args: One list or three numbers (strike,dip,rake) 62 | :param kwargs: Optionally specify 'strike','dip', 'rake' by name 63 | 64 | .. rubric:: Constructor Forms 65 | 66 | NodalPlane(strk, dp, rk) 67 | NodalPlane([strk,dp,rk]) 68 | NodalPlane(strike=strk, dip=dp, rake=rk) 69 | 70 | .. rubric:: Examples 71 | 72 | >>> l = [123, 45, 67] 73 | >>> p = NodalPlane(l) 74 | >>> p = NodalPlane(145, 45, 67) 75 | >>> p = NodalPlane(strike=145, dip=45, rake=67) 76 | >>> p.dip = 30 77 | """ 78 | super(NodalPlane,self).__init__([None,None,None]) 79 | 80 | if args: 81 | if isinstance(args[0], list) or isinstance(args[0], tuple) and len(args[0]) == 3 : 82 | self[:] = [float(n) for n in args[0]] 83 | elif len(args) == 3: 84 | self[:] = [float(n) for n in args] 85 | else: 86 | pass 87 | for key, value in kwargs.items(): 88 | if hasattr(self, key): 89 | self.__setattr__(key, float(value)) 90 | 91 | 92 | class DoubleCouple(object): 93 | """ 94 | Calulate nodal planes and P and T axes of a double couple focal mech 95 | 96 | The attributes are set up to calulate everything on the fly from the 97 | initial plane (strike, dip, rake), so you can change something (like 98 | a rake in your primary plane), and calling for a 'P' axis, e.g. will 99 | give you the new answer... 100 | 101 | :type plane1: :class:`~hashpy.doublecoule.NodalPlane` 102 | :param plane1: Primary plane containing strike/dip/rake 103 | :type plane2: :class:`~hashpy.doublecoule.NodalPlane` 104 | :param plane2: Auxiliary plane caculated from primary 105 | :type axis: dict of key/dict pairs 106 | :param axis: Keys ('P' and 'T') contain dict with keys 107 | 'azimuth' and 'dip' for that axis 108 | 109 | .. rubric:: Example 110 | 111 | >>> dc = DoubleCouple([270, 90, 180]) 112 | >>> dc.plane1 113 | >>> dc.plane2 114 | >>> dc.axis['P'] 115 | 116 | """ 117 | 118 | _plane = None 119 | 120 | @property 121 | def plane1(self): 122 | '''Return Preferred plane''' 123 | return NodalPlane(*self._plane) 124 | 125 | @property 126 | def plane2(self): 127 | '''Return Auxiliary plane''' 128 | auxplane = self.aux_plane(*self._plane) 129 | return NodalPlane(*auxplane) 130 | 131 | @property 132 | def axis(self): 133 | '''return direction and dip for P and T axes''' 134 | dipP, dipT, aziP, aziT = self.nodal2pt(*self.plane1+self.plane2) 135 | return {'P': {'azimuth': aziP, 'dip': dipP}, 'T': {'azimuth': aziT, 'dip': dipT}} 136 | 137 | def __init__(self, nodal_plane=None): 138 | self._plane = nodal_plane 139 | 140 | @staticmethod 141 | def zero_360(str1): 142 | '''Put an angle between 0 and 360 degrees 143 | 144 | Genevieve Patau 145 | ''' 146 | if str1 >= 360: 147 | str1 -= 360 148 | elif str1 < 0: 149 | str1 += 360 150 | else: 151 | pass 152 | return str1 153 | 154 | @classmethod 155 | def nodal2pt(cls, str1,da1,sa1,str2,da2,sa2): 156 | '''Compute azimuth and plungement of P-T axis 157 | (from nodal plane strikes, dips and rakes.) 158 | 159 | Mark's python port from Gabe's perl port from: 160 | FORTRAN routines of Anne Deschamps :: 161 | 162 | Inputs 163 | ------ 164 | *args == (str1,da1,sa1,str2,da2,sa2) 165 | For each plane: 166 | str : strike angle in degrees 167 | da : dip angle in degrees 168 | sa : rake (slip angle) in degrees 169 | 170 | Returns 171 | ------- 172 | Dips and azimuths of P and T axes 173 | (dip_p, dip_t, azi_p, azi_t) 174 | 175 | (Original fxn used azimuth of dip plane, not strike) 176 | str1 = dd1 - 90; 177 | str2 = dd2 - 90; 178 | ''' 179 | # Constants, mostly unnecessary, fix later: 180 | # e.g. M_PI = np.pi 181 | EPSIL = .0001 182 | M_PI = 3.14159265358979323846 183 | M_PI_2 = 1.57079632679489661923 184 | M_PI_4 = 0.78539816339744830962 185 | M_SQRT2 = 1.41421356237309504880 186 | TWO_PI = 6.28318530717958647692 187 | D2R = M_PI / 180.0 188 | 189 | #my ($pp, $dp, $pt, $dt, $xp, $yp); 190 | 191 | im = 0 192 | pure_strike_slip = 0 193 | 194 | if abs(np.sin(sa1 * D2R)) > EPSIL: 195 | im = sa1 / abs(sa1) 196 | elif abs(np.sin(sa2 * D2R)) > EPSIL: 197 | im = sa2 / abs(sa2) 198 | else: 199 | pure_strike_slip = 1 200 | 201 | if pure_strike_slip: 202 | if np.cos(sa1 * D2R) < 0: 203 | pp = cls.zero_360(str1 + 45) 204 | pt = cls.zero_360(str1 - 45) 205 | else: 206 | pp = cls.zero_360(str1 - 45); 207 | pt = cls.zero_360(str1 + 45); 208 | dp = 0 209 | dt = 0 210 | else: 211 | cd1 = np.cos(da1 * D2R) * M_SQRT2 212 | sd1 = np.sin(da1 * D2R) * M_SQRT2 213 | cd2 = np.cos(da2 * D2R) * M_SQRT2 214 | sd2 = np.sin(da2 * D2R) * M_SQRT2 215 | cp1 = -(np.cos(str1 * D2R)) * sd1 216 | sp1 = np.sin(str1 * D2R) * sd1 217 | cp2 = -(np.cos(str2 * D2R)) * sd2 218 | sp2 = np.sin(str2 * D2R) * sd2 219 | 220 | amz = -(cd1 + cd2) 221 | amx = -(sp1 + sp2) 222 | amy = cp1 + cp2 223 | dx = np.arctan2(np.sqrt(amx * amx + amy * amy), amz) - M_PI_2 224 | px = np.arctan2(amy, -amx) 225 | 226 | if px < 0: 227 | px += TWO_PI 228 | 229 | amz = cd1 - cd2 230 | amx = sp1 - sp2 231 | amy = - cp1 + cp2 232 | dy = np.arctan2(np.sqrt(amx * amx + amy * amy), -abs(amz)) - M_PI_2 233 | py = np.arctan2(amy, -amx) 234 | 235 | if amz > 0: 236 | py -= M_PI 237 | if py < 0: 238 | py += TWO_PI 239 | 240 | if im == 1: 241 | dp = dy 242 | pp = py 243 | dt = dx 244 | pt = px 245 | else: 246 | dp = dx 247 | pp = px 248 | dt = dy 249 | pt = py 250 | 251 | pp *= 180 / M_PI 252 | dp *= 180 / M_PI 253 | pt *= 180 / M_PI 254 | dt *= 180 / M_PI 255 | 256 | # I added this line b/c the names are confusing - MCW 257 | dip_p, dip_t, azi_p, azi_t = dp, dt, pp, pt 258 | return dip_p, dip_t, azi_p, azi_t 259 | 260 | # These two taken from obspy.imaging.beachball 261 | @staticmethod 262 | def get_strike_dip(n, e, u): 263 | """ 264 | Finds strike and dip of plane given normal vector having components n, e, 265 | and u. 266 | 267 | Adapted from MATLAB script 268 | `bb.m `_ 269 | written by Andy Michael and Oliver Boyd. 270 | """ 271 | r2d = 180 / np.pi 272 | if u < 0: 273 | n = -n 274 | e = -e 275 | u = -u 276 | 277 | strike = np.arctan2(e, n) * r2d 278 | strike = strike - 90 279 | while strike >= 360: 280 | strike = strike - 360 281 | while strike < 0: 282 | strike = strike + 360 283 | x = np.sqrt(np.power(n, 2) + np.power(e, 2)) 284 | dip = np.arctan2(x, u) * r2d 285 | return (strike, dip) 286 | 287 | @classmethod 288 | def aux_plane(cls, s1, d1, r1): 289 | """ 290 | Get Strike and dip of second plane. 291 | 292 | Adapted from MATLAB script 293 | `bb.m `_ 294 | written by Andy Michael and Oliver Boyd. 295 | """ 296 | r2d = 180 / np.pi 297 | 298 | z = (s1 + 90) / r2d 299 | z2 = d1 / r2d 300 | z3 = r1 / r2d 301 | # slick vector in plane 1 302 | sl1 = -np.cos(z3) * np.cos(z) - np.sin(z3) * np.sin(z) * np.cos(z2) 303 | sl2 = np.cos(z3) * np.sin(z) - np.sin(z3) * np.cos(z) * np.cos(z2) 304 | sl3 = np.sin(z3) * np.sin(z2) 305 | (strike, dip) = cls.get_strike_dip(sl2, sl1, sl3) 306 | 307 | n1 = np.sin(z) * np.sin(z2) # normal vector to plane 1 308 | n2 = np.cos(z) * np.sin(z2) 309 | h1 = -sl2 # strike vector of plane 2 310 | h2 = sl1 311 | # note h3=0 always so we leave it out 312 | # n3 = np.cos(z2) 313 | 314 | z = h1 * n1 + h2 * n2 315 | z = z / np.sqrt(h1 * h1 + h2 * h2) 316 | z = np.arccos(z) 317 | rake = 0 318 | if sl3 > 0: 319 | rake = z * r2d 320 | if sl3 <= 0: 321 | rake = -z * r2d 322 | return (strike, dip, rake) 323 | 324 | 325 | -------------------------------------------------------------------------------- /hashpy/io/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | 5 | -------------------------------------------------------------------------------- /hashpy/io/core.py: -------------------------------------------------------------------------------- 1 | # 2 | """ 3 | HASH input/output core module 4 | 5 | Here one can specify and register IO formats for HASH. 6 | 7 | More doc to come, basically, each format is a key in this 8 | module's global dict called "IO_REGISTRY", and each value is 9 | a dict containing a key called "module" with the module name, 10 | and optionally "in" and "out" keys specifying the names of 11 | the input and output functions in the module. The default 12 | function names are "input" and "output". 13 | 14 | 15 | """ 16 | import importlib 17 | 18 | ### Add I/O formats here! #################################################### 19 | # 20 | IO_REGISTRY = { "OBSPY" : { "module" : "obspyIO" , 21 | "in" : "inputOBSPY", 22 | "out" : "outputOBSPY", 23 | }, 24 | 25 | "ANTELOPE" : { "module" : "antelopeIO" }, 26 | 27 | "FPFIT" : { "module" : 'fpfitIO' }, 28 | } 29 | ############################################################################## 30 | 31 | # 32 | # EXAMPLE used as default if an output format can't be determined 33 | # 34 | def outputSTRING(hp): 35 | """ 36 | Simple string line output of best solution 37 | 38 | NOTES 39 | ----- 40 | This is called as a default if hp.output() is called with no format. 41 | 42 | Uses the hp._best_quality_index method, from the original HASH code, 43 | so this is easily modified to a custom quality assessment/output 44 | 45 | """ 46 | x = hp._best_quality_index 47 | s,d,r = hp.str_avg[x], hp.dip_avg[x], hp.rak_avg[x] 48 | return 'Solution:{orid} | STRIKE: {st:0.1f} DIP: {dp:0.1f} RAKE: {rk:0.1f} | Quality:{q}'.format(orid=hp.icusp, 49 | st=float(s), dp=float(d), rk=float(r), q=hp.qual[x]) 50 | 51 | 52 | class Inputter(object): 53 | """ 54 | Class whose instances are input/load/read functions for HASH 55 | 56 | """ 57 | 58 | __input_fxn = None 59 | 60 | @property 61 | def _input(self): 62 | return self.__input_fxn 63 | 64 | @_input.setter 65 | def _input(self, input_function): 66 | self.__input_fxn = input_function 67 | 68 | 69 | def __init__(self, format=None): 70 | """ 71 | Get the input function and return an inputter that calls it 72 | """ 73 | if format is not None and format in IO_REGISTRY: 74 | io_format = IO_REGISTRY[format.upper()] 75 | io_module = importlib.import_module("hashpy.io." + io_format["module"]) # TODO catch keyerror, importerror 76 | input_fxn_name = io_format.get("in", "input") 77 | self._input = getattr(io_module, input_fxn_name) 78 | else: 79 | raise NotImplementedError("Can't determine format, must explicity state") 80 | 81 | def __call__(self, *args, **kwargs): 82 | return self._input(*args, **kwargs) 83 | 84 | 85 | class Outputter(object): 86 | """ 87 | Class whose instances are output/write functions for HASH 88 | 89 | """ 90 | 91 | __output_fxn = None 92 | 93 | @property 94 | def _output(self): 95 | return self.__output_fxn 96 | 97 | @_output.setter 98 | def _output(self, output_function): 99 | self.__output_fxn = output_function 100 | 101 | 102 | def __init__(self, format=None): 103 | """ 104 | Get the input function and return an inputter that calls it 105 | 106 | """ 107 | if format is not None and format in IO_REGISTRY: 108 | io_format = IO_REGISTRY[format.upper()] 109 | io_module = importlib.import_module("hashpy.io." + io_format["module"]) # TODO catch keyerror, importerror 110 | output_fxn_name = io_format.get("out", "output") 111 | self._output = getattr(io_module, output_fxn_name) 112 | else: 113 | self._output = outputSTRING 114 | 115 | def __call__(self, *args, **kwargs): 116 | return self._output(*args, **kwargs) 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /hashpy/io/fpfitIO.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # INPUT FILE: "fpfile" FPFIT-like format - ** YOU MAY NEED TO CHANGE THE INPUT FORMAT ** 4 | # 5 | # event line: 6 | # columns format value 7 | # ------------------------- 8 | # 1-4 i4 origin time, year 9 | # 5-12 4i2 origin time, month, day, hour, minute 10 | # 13-17 f5.2 origin time, seconds 11 | # 18-19 i2 latitude, degrees 12 | # 20 a1 latitude, 'S'=south 13 | # 21-25 f5.2 latitude, minutes 14 | # 26-28 i3 longitude, degrees 15 | # 29 a1 longitude, 'E'=east 16 | # 30-34 f5.2 longitude, minutes 17 | # 35-39 f5.2 depth, km 18 | # 89-93 f5.2 horizontal location uncertainty, km 19 | # 95-99 f5.2 vertical location uncertainty, km 20 | # 140-143 f4.2 magnitude 21 | # 150-165 a16 event ID 22 | # 23 | # polarity line: 24 | # columns format value 25 | # ------------------------- 26 | # 1-4 a4 station name 27 | # 6-7 a2 station network 28 | # 10-12 a3 station component 29 | # 14 a1 P onset, I or E 30 | # 16 a1 P polarity : U, u, +, D, d, or - 31 | # 32 | import numpy as np 33 | import datetime 34 | 35 | degrad = 180. / np.pi 36 | 37 | def get_sta_coords(f_sta): 38 | ''' 39 | Stub which reads in the HASH example station file 40 | 41 | :param f_sta: file handle with station info 42 | 43 | :returns: dict of list of floats -> { 'station_code' : [lat, lon, elv] } 44 | 45 | ''' 46 | coords = {} 47 | for s in f_sta: 48 | sta = s[0:4] 49 | lat = float(s[42:50]) 50 | lon = float(s[51:61]) 51 | elv = float(s[62:67])/1000. 52 | if sta not in coords: 53 | coords[sta] = [lat,lon,elv] 54 | return coords 55 | 56 | def check_polarity_file(polarity_file, sta_name, year, month, day, hour): 57 | """ 58 | Stub for checking polarity file FPFIT style, there's a fortran sub for this, 59 | ideally, rewrite, but this will work for now... 60 | 61 | :param str polarity_file: name of polarity file in rando SC esoteric anti-format 62 | 63 | """ 64 | from hashpy import libhashpy 65 | return libhashpy.check_pol(polarity_file, sta_name, year, month, day, hour) 66 | 67 | def input(hp, files={} ): 68 | """ 69 | Input function for FPFIT-style HASH 70 | 71 | :param dict files: dict of str filenames 72 | 73 | Input dictionary has keys: ('station', 'polarity', 'input') 74 | for station file, polarity reversal file, and main event/phase 75 | input, respectively. 76 | 77 | """ 78 | with open(files['station']) as fs: 79 | sta_coords = get_sta_coords(fs) 80 | 81 | with open(files['input']) as fi: 82 | 83 | while True: 84 | # read in earthquake location, etc SCEDC format 85 | line = fi.readline() 86 | if not line: 87 | break 88 | 89 | iyr = int(line[0:4]) 90 | imon = int(line[4:6]) 91 | idy = int(line[6:8]) 92 | ihr = int(line[8:10]) 93 | imn = int(line[10:12]) 94 | sec = line[12:17] 95 | ilatd = int(line[17:19]) 96 | cns = line[19] 97 | qlatm = float(line[20:25]) 98 | ilond = int(line[25:28]) 99 | cew = line[28] 100 | qlonm = float(line[29:34]) 101 | 102 | hp.qdep = float(line[34:39]) # then 49x 103 | hp.seh = float(line[88:93]) # then 1x 104 | hp.sez = float(line[94:99]) # then 40x 105 | hp.qmag = float(line[139:143]) # then 6x 106 | hp.icusp = int(line[149:165]) 107 | 108 | qsec = float(sec) 109 | secs = sec.split('.') 110 | isec = int(secs[0]) 111 | imsec = int(secs[1]+'0000') 112 | dt = datetime.datetime(iyr,imon,idy,ihr,imn,isec,imsec) 113 | hp.tstamp = (dt - datetime.datetime(1970, 1, 1)).total_seconds() 114 | 115 | hp.qlat = ilatd + (qlatm / 60.0) 116 | if ('S' in cns): 117 | hp.qlat *= -1 118 | hp.qlon = -(ilond + (qlonm / 60.0)) 119 | if ('E' in cew): 120 | hp.qlon *= -1 121 | aspect = np.cos(hp.qlat / degrad) 122 | 123 | # set parameters not given in input file 124 | if not hp.sez: 125 | hp.sez = 1. 126 | terr = -9 127 | rms = -9 128 | nppick = -9 129 | nspick = -9 130 | evtype = 'L' 131 | magtype = 'X' 132 | locqual = 'X' 133 | 134 | # read in polarities - SCEDC format - ** YOU MAY NEED TO CHANGE THE INPUT FORMAT ** 135 | k = 0 136 | while True: 137 | ph = fi.readline() 138 | hp.sname[k] = ph[0:4] 139 | hp.snet[k] = ph[5:7] 140 | hp.scomp[k] = ph[9:12] 141 | hp.pickonset[k] = ph[13] 142 | hp.pickpol[k] = ph[15] 143 | hp.arid[k] = k 144 | 145 | if (hp.sname[k] == ' '): 146 | break 147 | 148 | #flat,flon,felv = getstat_tri(stfile,sname[k],scomp[k],snet[k]) 149 | # SCSN station information - ** YOU MAY NEED TO USE YOUR OWN SUBROUTINE ** 150 | # 151 | #-- the above sucks, I needed to use my own subroutine --# 152 | # 153 | if hp.sname[k] in sta_coords: 154 | hp.flat[k], hp.flon[k], hp.felv[k] = sta_coords[hp.sname[k]] 155 | else: 156 | continue 157 | 158 | dx = (hp.flon[k] - hp.qlon) * 111.2 * aspect 159 | dy = (hp.flat[k] - hp.qlat) * 111.2 160 | hp.dist[k] = np.sqrt(dx**2 + dy**2) 161 | hp.qazi[k] = 90. - np.arctan2(dy,dx) * degrad 162 | 163 | if (hp.qazi[k] < 0.): 164 | hp.qazi[k] += 360. 165 | 166 | if (hp.dist[k] > hp.delmax): 167 | continue 168 | 169 | if (hp.pickpol[k] in 'Uu+'): 170 | hp.p_pol[k] = 1 171 | elif (hp.pickpol[k] in 'Dd-'): 172 | hp.p_pol[k] = -1 173 | else: 174 | continue 175 | 176 | if (hp.pickonset[k] in 'Ii'): 177 | hp.p_qual[k] = 0 178 | else: 179 | hp.p_qual[k] = 1 180 | 181 | # Try to check a polarity file using sub 182 | try: 183 | spol = check_polarity_file(files['polarity'], hp.sname[k], iyr, imon, idy, ihr) 184 | except: 185 | spol = 1 186 | finally: 187 | hp.p_pol[k] *= spol 188 | 189 | k += 1 190 | continue 191 | hp.npol = k - 1 192 | 193 | -------------------------------------------------------------------------------- /hashpy/io/obspyIO.py: -------------------------------------------------------------------------------- 1 | # 2 | # HashPype class which uses ObsPy Event as I/O for focal mech data 3 | # 4 | from hashpy.doublecouple import DoubleCouple 5 | from obspy.core.utcdatetime import UTCDateTime 6 | from obspy.core.event import (Catalog, Event, Origin, CreationInfo, Magnitude, 7 | EventDescription, OriginUncertainty, OriginQuality, CompositeTime, 8 | ConfidenceEllipsoid, StationMagnitude, Comment, WaveformStreamID, Pick, 9 | QuantityError, Arrival, FocalMechanism, MomentTensor, NodalPlanes, 10 | PrincipalAxes, Axis, NodalPlane, SourceTimeFunction, Tensor, DataUsed, 11 | ResourceIdentifier, StationMagnitudeContribution) 12 | 13 | def inputOBSPY(hp, event): 14 | """ 15 | Load Event into HASH 16 | 17 | Takes origin, arrival, pick information from an Event and loads 18 | up the HASH arrays needed for the focal mechanism calculation. 19 | 20 | Input 21 | ----- 22 | event : obspy.core.event.Event instance 23 | 24 | ** event.preferred_origin_id should be set to the origin in 25 | event.origins you want to use 26 | """ 27 | # Takes an obspy event and loads FM data into HASH 28 | _o = event.preferred_origin() 29 | _m = event.preferred_magnitude() 30 | 31 | hp.tstamp = _o.time.timestamp 32 | hp.qlat = _o.latitude 33 | hp.qlon = _o.longitude 34 | hp.qdep = _o.depth 35 | hp.icusp = _o.creation_info.version 36 | hp.seh = _o.origin_uncertainty.confidence_ellipsoid.semi_major_axis_length 37 | hp.sez = _o.origin_uncertainty.confidence_ellipsoid.semi_intermediate_axis_length 38 | if _m: 39 | hp.qmag = _m.mag 40 | 41 | # The index 'k' is deliberately non-Pythonic to deal with the fortran 42 | # subroutines which need to be called and the structure of the original HASH code. 43 | # May be able to update with a rewrite... YMMV 44 | hp.p_index = [] 45 | k = 0 46 | for _i, arrv in enumerate(_o.arrivals): 47 | # load up params 48 | pick = arrv.pick_id.getReferredObject() 49 | hp.sname[k] = pick.waveform_id.station_code 50 | hp.snet[k] = pick.waveform_id.network_code 51 | hp.scomp[k] = pick.waveform_id.channel_code 52 | hp.arid[k] = pick.creation_info.version 53 | 54 | hp.qazi[k] = arrv.azimuth 55 | hp.dist[k] = arrv.distance * 111.2 56 | 57 | if (hp.qazi[k] < 0.): 58 | hp.qazi[k] += 360. 59 | 60 | if (hp.dist[k] > hp.delmax): 61 | continue 62 | 63 | if arrv.phase not in 'Pp': 64 | continue 65 | 66 | if (pick.polarity is 'positive'): 67 | hp.p_pol[k] = 1 68 | elif (pick.polarity is 'negative'): 69 | hp.p_pol[k] = -1 70 | else: 71 | continue 72 | 73 | if (pick.onset is 'impulsive'): 74 | hp.p_qual[k] = 0 75 | elif (pick.onset is 'emergent'): 76 | hp.p_qual[k] = 1 77 | elif (pick.onset is 'questionable'): 78 | hp.p_qual[k] = 1 79 | else: 80 | hp.p_qual[k] = 0 81 | 82 | # polarity check in original code... doesn't work here 83 | #hp.p_pol[k] = hp.p_pol[k] * hp.spol 84 | hp.p_index.append(_i) # indicies of [arrivals] which passed 85 | k += 1 86 | hp.npol = k # k is zero indexed in THIS loop 87 | 88 | def outputOBSPY(hp, event=None, only_fm_picks=False): 89 | """ 90 | Make an Event which includes the current focal mechanism information from HASH 91 | 92 | Use the 'only_fm_picks' flag to only include the picks HASH used for the FocalMechanism. 93 | This flag will replace the 'picks' and 'arrivals' lists of existing events with new ones. 94 | 95 | Inputs 96 | ------- 97 | hp : hashpy.HashPype instance 98 | 99 | event : obspy.core.event.Event 100 | 101 | only_fm_picks : bool of whether to overwrite the picks/arrivals lists 102 | 103 | 104 | Returns 105 | ------- 106 | obspy.core.event.Event 107 | 108 | Event will be new if no event was input, FocalMech added to existing event 109 | """ 110 | # Returns new (or updates existing) Event with HASH solution 111 | n = hp.npol 112 | if event is None: 113 | event = Event(focal_mechanisms=[], picks=[], origins=[]) 114 | origin = Origin(arrivals=[]) 115 | origin.time = UTCDateTime(hp.tstamp) 116 | origin.latitude = hp.qlat 117 | origin.longitude = hp.qlon 118 | origin.depth = hp.qdep 119 | origin.creation_info = CreationInfo(version=hp.icusp) 120 | origin.resource_id = ResourceIdentifier('smi:hash/Origin/{0}'.format(hp.icusp)) 121 | for _i in range(n): 122 | p = Pick() 123 | p.creation_info = CreationInfo(version=hp.arid[_i]) 124 | p.resource_id = ResourceIdentifier('smi:hash/Pick/{0}'.format(p.creation_info.version)) 125 | p.waveform_id = WaveformStreamID(network_code=hp.snet[_i], station_code=hp.sname[_i], channel_code=hp.scomp[_i]) 126 | if hp.p_pol[_i] > 0: 127 | p.polarity = 'positive' 128 | else: 129 | p.polarity = 'negative' 130 | a = Arrival() 131 | a.creation_info = CreationInfo(version=hp.arid[_i]) 132 | a.resource_id = ResourceIdentifier('smi:hash/Arrival/{0}'.format(p.creation_info.version)) 133 | a.azimuth = hp.p_azi_mc[_i,0] 134 | a.takeoff_angle = 180. - hp.p_the_mc[_i,0] 135 | a.pick_id = p.resource_id 136 | origin.arrivals.append(a) 137 | event.picks.append(p) 138 | event.origins.append(origin) 139 | event.preferred_origin_id = str(origin.resource_id) 140 | else: # just update the changes 141 | origin = event.preferred_origin() 142 | picks = [] 143 | arrivals = [] 144 | for _i in range(n): 145 | ind = hp.p_index[_i] 146 | a = origin.arrivals[ind] 147 | p = a.pick_id.getReferredObject() 148 | a.takeoff_angle = hp.p_the_mc[_i,0] 149 | picks.append(p) 150 | arrivals.append(a) 151 | if only_fm_picks: 152 | origin.arrivals = arrivals 153 | event.picks = picks 154 | # Use me double couple calculator and populate planes/axes etc 155 | x = hp._best_quality_index 156 | # Put all the mechanisms into the 'focal_mechanisms' list, mark "best" as preferred 157 | for s in range(hp.nmult): 158 | dc = DoubleCouple([hp.str_avg[s], hp.dip_avg[s], hp.rak_avg[s]]) 159 | ax = dc.axis 160 | focal_mech = FocalMechanism() 161 | focal_mech.creation_info = CreationInfo(creation_time=UTCDateTime(), author=hp.author) 162 | focal_mech.triggering_origin_id = origin.resource_id 163 | focal_mech.resource_id = ResourceIdentifier('smi:hash/FocalMechanism/{0}/{1}'.format(hp.icusp, s+1)) 164 | focal_mech.method_id = ResourceIdentifier('HASH') 165 | focal_mech.nodal_planes = NodalPlanes() 166 | focal_mech.nodal_planes.nodal_plane_1 = NodalPlane(*dc.plane1) 167 | focal_mech.nodal_planes.nodal_plane_2 = NodalPlane(*dc.plane2) 168 | focal_mech.principal_axes = PrincipalAxes() 169 | focal_mech.principal_axes.t_axis = Axis(azimuth=ax['T']['azimuth'], plunge=ax['T']['dip']) 170 | focal_mech.principal_axes.p_axis = Axis(azimuth=ax['P']['azimuth'], plunge=ax['P']['dip']) 171 | focal_mech.station_polarity_count = n 172 | focal_mech.azimuthal_gap = hp.magap 173 | focal_mech.misfit = hp.mfrac[s] 174 | focal_mech.station_distribution_ratio = hp.stdr[s] 175 | focal_mech.comments.append( 176 | Comment(hp.qual[s], resource_id=ResourceIdentifier(str(focal_mech.resource_id) + '/comment/quality')) 177 | ) 178 | #---------------------------------------- 179 | event.focal_mechanisms.append(focal_mech) 180 | if s == x: 181 | event.preferred_focal_mechanism_id = str(focal_mech.resource_id) 182 | return event 183 | 184 | -------------------------------------------------------------------------------- /hashpy/plotting/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | from focalmechplotter import FocalMechPlotter 3 | 4 | -------------------------------------------------------------------------------- /hashpy/plotting/focalmechplotter.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | focalmechplotter.py 4 | 5 | by Mark Williams 2012.313 6 | 7 | Focal Mechanism Plotter using ObsPy Event as I/O 8 | (See docstring for class 'FocalMechPlotter') 9 | 10 | """ 11 | import matplotlib 12 | matplotlib.use('TkAgg') 13 | from matplotlib import pyplot as plt 14 | from matplotlib.gridspec import GridSpec 15 | from matplotlib.backend_bases import NavigationToolbar2 16 | from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg 17 | import mplstereonet 18 | 19 | 20 | class FocalMechPlotter(object): 21 | """ 22 | Class to create stereonet plot of a HASH first motion 23 | 24 | This is a simple, slow, matplotlib script to plot a first motion 25 | focal mechanism using ObsPy object input. Currently supports: 26 | 27 | Event with a FocalMechanism (marked as preferred) 28 | Origin/Arrivals (marked as preferred) 29 | Picks (referred to by each Arrival) 30 | 31 | Notes 32 | ----- 33 | Requires the mplstereonet matplotlib extension. 34 | 35 | """ 36 | fig = None # handle to figure 37 | ax = None # list of axes in the figure 38 | h = None # list of handles of FM picks 39 | gs = None # GridSpec instance of plot figure 40 | h_text = None # handle for text labels 41 | event = None # Event object 42 | focm = None # Current FM plotted 43 | ind = None # indicies of which picks in Origin.arrivals are plotted 44 | _arrv = None # current arrival 45 | _curh = None # current handle 46 | _axis = None # dict of axes for quick ref 47 | save = None # function handle to a 'save' function 48 | source = None # temp string of where to save 49 | 50 | picks_list = ('undecidable', 'positive', 'negative') 51 | wf_color = { 'positive' : 'red', 'negative' : 'blue', 'undecidable' : 'black' } 52 | 53 | @property 54 | def _fm_index(self): 55 | return self.event.focal_mechanisms.index(self.focm) 56 | @property 57 | def _num_fms(self): 58 | return len(self.event.focal_mechanisms) 59 | 60 | @property # preferred origin 61 | def _orig(self): 62 | '''Stub''' 63 | return self.event.preferred_origin() 64 | @property # preferred focal mechanism 65 | def _focm(self): 66 | '''Stub''' 67 | return self.event.preferred_focal_mechanism() 68 | @property # current pick 69 | def _pick(self): 70 | '''Pick pointed to by current arrival''' 71 | return self._arrv.pick_id.getReferredObject() 72 | 73 | def plot_on_stereonet(self, axis=None, fm=None): 74 | '''Plot first motions from an Event instance 75 | 76 | Stored in self.event 77 | ''' 78 | 79 | if axis: 80 | ax = axis 81 | else: 82 | ax = self._axis['stereonet'] 83 | 84 | if fm is None: 85 | self.focm = self._focm 86 | else: 87 | self.focm = self.event.focal_mechanisms[fm] 88 | 89 | ax.clear() 90 | ax.set_title('Origin: {0}'.format(self._orig.creation_info.version)) 91 | tlab = ax.set_azimuth_ticklabels([]) 92 | 93 | h = [] 94 | index = [] 95 | 96 | # Planes 97 | np1 = self.focm.nodal_planes.nodal_plane_1 98 | np2 = self.focm.nodal_planes.nodal_plane_2 99 | strike1,dip1,rake1 = np1.strike, np1.dip, np1.rake 100 | strike2,dip2,rake2 = np2.strike, np2.dip, np2.rake 101 | 102 | # Plotting --------------------------------------# 103 | # plot best fit average plane, aux plane 104 | h_rk = ax.plane(strike1, dip1, color='black', linewidth=3) 105 | h_rk = ax.rake( strike1, dip1, -rake1, 'k^', markersize=8) 106 | h_rk = ax.plane(strike2, dip2, color='black', linewidth=3) 107 | # plot station takeoffs 108 | plot_specs = { 'picker' : 5, 109 | 'markersize' : 8, 110 | 'markeredgewidth' : 2, 111 | } 112 | for ind, a in enumerate(self._orig.arrivals): 113 | p = a.pick_id.getReferredObject() 114 | # Calculate strike azi from direct (dip-pointing) azi 115 | azi = a.azimuth - 90. 116 | #--- HASH takeoffs are 0-180 from vertical UP!! 117 | #--- obspy QuakeML are 0-180 from vertical DOWN 118 | #--- Stereonet angles 0-90 inward (dip) 119 | #--- Classic FM's are toa from center??? 120 | if 0. <= a.takeoff_angle < 90.: 121 | toa = 90. - a.takeoff_angle # complement for downward angles 122 | elif 90. <= a.takeoff_angle <= 180.: 123 | toa = 270. - a.takeoff_angle # project upward angles 124 | else: 125 | raise ValueError("Takeoff angle ({0}) must be in [0, 180]".format(a.azimuth)) 126 | 127 | if p.polarity is 'positive': 128 | #plot_specs.update({'markeredgecolor' : 'black', 'markerfacecolor' : 'red' }) 129 | h += ax.rake(azi, toa, 90, 'o', markeredgecolor='black', markerfacecolor='red', **plot_specs) 130 | if p.polarity is 'negative': 131 | #plot_specs.update({'markeredgecolor' : 'blue', 'markerfacecolor' : 'white' }) 132 | h += ax.rake(azi, toa, 90, 'o', markeredgecolor='blue', markerfacecolor='white', **plot_specs) 133 | index.append(ind) 134 | if True: 135 | h_text = ax.rake(azi, toa+5, 90, marker='$ {0}$'.format(p.waveform_id.station_code), color='black',markersize=20) 136 | 137 | for comm in self.focm.comments: 138 | if 'quality' in comm.resource_id.resource_id: 139 | qual = comm.text 140 | else: 141 | qual = None 142 | plane_str = "STRIKE1:{0: > 7.1f}\nDIP1:{1: > 7.1f}\nRAKE1:{2: > 7.1f}\n\nSTRIKE2:{3: > 7.1f}\nDIP2:{4: > 7.1f}\nRAKE2:{5: > 7.1f}" 143 | h_text = self.fig.text(0.25, 0.88, plane_str.format(strike1, dip1, rake1, strike2, dip2, rake2), ha='right', va='top', family='monospace') 144 | h_text = self.fig.text(0.25, 0.11, 'Quality: {0}\n# of picks: {1}'.format(qual, len(self._orig.arrivals)), ha='right', va='top', family='monospace') 145 | 146 | if not axis: 147 | self.h = h 148 | self.ind = index 149 | 150 | self._set_window_title() 151 | 152 | def draw_stereonet_axis(self, gridspec_slice=None): 153 | # Stereonet axis 154 | if gridspec_slice is None: 155 | gridspec_slice = self.gs_slice 156 | ax = self.fig.add_subplot(gridspec_slice, projection='stereonet') # gs[:-2,:-1] 157 | self.ax.append(ax) 158 | self._axis['stereonet'] = ax 159 | 160 | def _set_window_title(self): 161 | self.fig.canvas.set_window_title('Focal Mechanism: {0} of {1}'.format(self._fm_index+1, self._num_fms)) 162 | 163 | def plot(self, solution=None): 164 | self.fig.clear() 165 | self.draw_stereonet_axis() 166 | self.plot_on_stereonet(fm=solution) 167 | plt.draw() 168 | 169 | def __init__(self, event=None, save=None): 170 | """ 171 | Create a plot for focal mechanisms 172 | 173 | Input 174 | ----- 175 | event : obspy.core.event.Event containing 176 | FocalMechanism 177 | Picks 178 | Origin/Arrivals 179 | 180 | save : function handle, the instance is passed as 1st arg 181 | "save(self)", called on save button press 182 | 183 | """ 184 | self.event = event 185 | self.ax = [] 186 | self._axis = {} 187 | self.save = save 188 | self.gs = GridSpec(8,5) # 8x5 grid of axis space 189 | self.gs_slice = self.gs[:,1:] 190 | 191 | # Hijack buttons 192 | # -------------------------------------------------------------------# 193 | # Make forward plot next solution 194 | forward = NavigationToolbar2.forward 195 | def next_fm(navtb, *args, **kwargs): 196 | m = self._fm_index 197 | n = self._num_fms 198 | if m < n-1: 199 | self.plot(solution=m+1) 200 | forward(navtb, *args, **kwargs) 201 | NavigationToolbar2.forward = next_fm 202 | 203 | # Make back plot previous solution 204 | back = NavigationToolbar2.back 205 | def prev_fm(navtb, *args, **kwargs): 206 | m = self._fm_index 207 | if m > 0: 208 | self.plot(solution=m-1) 209 | back(navtb, *args, **kwargs) 210 | NavigationToolbar2.back = prev_fm 211 | 212 | # Make home plot preferred solution 213 | home = NavigationToolbar2.home 214 | def pref_fm(navtb, *args, **kwargs): 215 | self.plot() 216 | home(navtb, *args, **kwargs) 217 | NavigationToolbar2.home = pref_fm 218 | 219 | # Take a 'save' function passed on creation and try to call it 220 | if self.save: 221 | savefig = NavigationToolbar2TkAgg.save_figure 222 | def save_fm(navtb, *args, **kwargs): 223 | try: 224 | navtb.set_message("Saving...") 225 | self.save(self) 226 | navtb.set_message("DONE") 227 | except Exception as e: 228 | navtb.set_message("FAILED:{0}".format(e.message)) 229 | 230 | NavigationToolbar2TkAgg.save_figure = save_fm 231 | # -------------------------------------------------------------------# 232 | 233 | # Draw figure 234 | self.fig = plt.figure(facecolor='#D9D9EE') 235 | self.plot() 236 | 237 | 238 | plt.show() 239 | 240 | -------------------------------------------------------------------------------- /hashpy/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markcwill/hashpy/d6a334717e603936cf537646955b0c114c9bedf6/hashpy/scripts/__init__.py -------------------------------------------------------------------------------- /hashpy/scripts/dbhash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | # dbhash.py 4 | # 5 | # functions which run HASH using Antelope and hashpy 6 | # 7 | # optionally, can plot by passing ObsPy output to a plotter 8 | """ 9 | #from obspy.core import UTCDateTime 10 | import os 11 | from hashpy.hashpype import HashPype, HashError 12 | from hashpy.io.antelopeIO import ( load_pf, eventfocalmech2db, dbloc_source_db, RowPointerDict ) 13 | 14 | def _dump_bitmap(figure=None, directory='.', uid=None): 15 | """ 16 | Dump mpl figure to a file 17 | 18 | Given a figure & dir, make folder called 'images' and 19 | dump it into a png file called '_focalmech.png' 20 | 21 | """ 22 | filename = 'focalmech.png' 23 | if uid: 24 | filename = '_'.join([str(uid),filename]) 25 | imagedir = os.path.join(directory, 'images') 26 | if not os.path.exists(imagedir): 27 | os.mkdir(imagedir) 28 | fullname = os.path.join(imagedir, filename) 29 | figure.savefig(fullname) 30 | 31 | def dbhash_run(dbname, orid=None, pf=None): 32 | """ 33 | Perform a HASH run using Database input and command line args 34 | 35 | Input 36 | ----- 37 | args : Namespace of command line args 38 | 39 | Returns : hp : a hashpy.HashPype object containing solutions 40 | 41 | """ 42 | hp = HashPype() 43 | 44 | # Load settings data from a pf file... 45 | if pf: 46 | load_pf(hp, pffile=pf) 47 | else: 48 | load_pf(hp) 49 | 50 | # Grab data from the db... 51 | hp.input(dbname, format="ANTELOPE", orid=orid) 52 | 53 | # Run and catch errors from the minimum requirements checks 54 | try: 55 | hp.driver2(check_for_maximum_gap_size=False) 56 | except HashError as e: 57 | print("Failed! " + e.message) 58 | except: 59 | raise 60 | 61 | return hp 62 | 63 | def main(): 64 | from argparse import ArgumentParser 65 | 66 | # Get command line args 67 | parser = ArgumentParser() 68 | parser.add_argument("dbin", help="Input database") 69 | parser.add_argument("dbout", help="Output database", nargs='?') 70 | parser.add_argument("-p", "--plot", help="Plot result", action='store_true') 71 | parser.add_argument("-l", "--loc", help="dbloc2 mode", action='store_true') 72 | parser.add_argument("-i", "--image", help="Save image with db", action='store_true') 73 | parser.add_argument("--pf", help="Parameter file") 74 | group = parser.add_mutually_exclusive_group() #required=True) 75 | group.add_argument("--evid", help="Event ID", type=int) 76 | group.add_argument("--orid", help="Origin ID", type=int) 77 | args = parser.parse_args() 78 | 79 | # Special 'dbloc2' settings 80 | if args.loc: 81 | from antelope.datascope import Dbptr 82 | # alter args b/c dbloc2 passes a db and a row number 83 | args.dbin = args.dbin.rstrip('.origin') 84 | db = Dbptr(args.dbin) 85 | db = db.lookup(table='origin') 86 | db.record = int(args.dbout) 87 | args.orid = db.getv('orid')[0] 88 | args.dbout = dbloc_source_db(args.dbin, pointer=False) 89 | args.plot = True # force plot 90 | args.image = True # force saving image to db folder 91 | 92 | # Now that we have a save location from command line args, 93 | # make a function to save to that database. The plotter is I/O 94 | # agnostic, it will accept a function to save anything anyhow anywhichway 95 | # 96 | def save_plot_to_db(fmplotter, dbname=args.dbout, dump_bitmap=args.image): 97 | focal_mech = fmplotter.event.focal_mechanisms[fmplotter._fm_index] 98 | if focal_mech is not fmplotter.event.preferred_focal_mechanism(): 99 | fmplotter.event.preferred_focal_mechanism_id = focal_mech.resource_id.resource_id 100 | 101 | # Save to db 102 | eventfocalmech2db(event=fmplotter.event, database=dbname) 103 | 104 | if dump_bitmap: 105 | vers = fmplotter.event.preferred_origin().creation_info.version 106 | dbdir = os.path.dirname(dbname) 107 | _dump_bitmap(figure=fmplotter.fig, directory=dbdir, uid=vers) 108 | 109 | # Run HASH 110 | hp = dbhash_run(args.dbin, orid=args.orid, pf=args.pf) 111 | 112 | # Launch plotter or spit out solution 113 | if args.plot: 114 | from hashpy.plotting.focalmechplotter import FocalMechPlotter 115 | ev = hp.output(format="OBSPY") 116 | p = FocalMechPlotter(ev, save=save_plot_to_db) 117 | else: 118 | # quick orid/strike/dip/rake line 119 | print(hp.output()) 120 | p = 0 121 | if args.dbout: 122 | db = hp.output(format="ANTELOPE", dbout=args.dbout) 123 | 124 | # Done, return HashPype and/or FocalMechPlotter for debugging 125 | return hp, p 126 | 127 | 128 | if __name__ == '__main__': 129 | ret = main() 130 | -------------------------------------------------------------------------------- /hashpy/scripts/hash_utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | hash_utils.py 4 | 5 | -by Mark Williams (2013), NSL 6 | 7 | utilities for running HASH using the python version of hash_driver2 8 | (hash_driver2.py) 9 | """ 10 | 11 | def parameter(**kwargs): 12 | '''returns variables inside a fortran 'parameter' call''' 13 | # FUTURE: could just make them all globals and import from namespace 14 | return [kwargs[key] for key in kwargs] 15 | 16 | def fortran_include(fname): 17 | '''functions similar to a fortran include''' 18 | vars = [] 19 | f_inc = open(fname) 20 | for line in f_inc: 21 | if 'c' in line[0]: 22 | pass 23 | elif 'parameter' in line: 24 | vars.extend(eval(line)) 25 | else: 26 | pass 27 | f_inc.close() 28 | return vars 29 | 30 | def get_sta_coords(stfile): 31 | '''Stub which reads in the HASH example station file''' 32 | f = open(stfile) 33 | sta_coords = {} 34 | for s in f: 35 | sta = s[0:4] 36 | lat = float(s[42:50]) 37 | lon = float(s[51:61]) 38 | elv = float(s[62:67])/1000. 39 | if sta in sta_coords: 40 | pass 41 | else: 42 | sta_coords[sta] = [lat,lon,elv] 43 | f.close() 44 | return sta_coords 45 | 46 | def test_stereo(azimuths,takeoffs,polarities,sdr=[]): 47 | ''' 48 | Plots points with given azimuths, takeoff angles, and 49 | polarities on a stereonet. Will also plot both planes 50 | of a double-couple given a strike/dip/rake 51 | ''' 52 | import matplotlib.pyplot as plt 53 | import mplstereonet 54 | from obspy.imaging.beachball import AuxPlane 55 | 56 | fig = plt.figure() 57 | ax = fig.add_subplot(111, projection='stereonet') 58 | up = polarities > 0 59 | dn = polarities < 0 60 | h_rk = ax.rake(azimuths[up]-90.,takeoffs[up],90, 'ro') 61 | h_rk = ax.rake(azimuths[dn]-90.,takeoffs[dn],90, 'b+') 62 | if sdr: 63 | s2,d2,r2 = AuxPlane(*sdr) 64 | h_rk = ax.plane(sdr[0],sdr[1],'g') 65 | h_rk = ax.rake(sdr[0],sdr[1],-sdr[2], 'go') 66 | h_rk = ax.plane(s2,d2, 'g') 67 | plt.show() 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /hashpy/src/Makefile: -------------------------------------------------------------------------------- 1 | # HASHpype Makefile 2 | # 3 | # - Mark Williams 2012.320 4 | # Based on HASH Makefile 5 | 6 | SRC= fmech_subs.f uncert_subs.f util_subs.f \ 7 | pol_subs.f vel_subs.f station_subs.f vel_subs2.f 8 | 9 | # HASHpype library module: 10 | hashpy: libhashpy.so 11 | 12 | libhashpy.so: Makefile $(SRC) 13 | f2py -c -m libhashpy $(SRC) 14 | 15 | #.PHONY : install 16 | #install : libhashpy.so 17 | # @mv libhashpy.so .. 18 | 19 | -------------------------------------------------------------------------------- /hashpy/src/fmamp_subs.f: -------------------------------------------------------------------------------- 1 | c subroutine FOCALAMP_MC performs grid search to find focal mechanisms, using both 2 | c P-polarity and S/P amplitude ratio information 3 | c Inputs: 4 | c p_azi_mc(npsta,nmc) = azimuth to station from event (deg. E of N) 5 | c p_the_mc(npsta,nmc) = takeoff angle (from vert, <90 upgoing, >90 downgoing) 6 | c sp_amp(npsta) = amplitude ratios 7 | c p_pol(nspta) = P polarities 8 | c npsta = number of observations 9 | c nmc = number of trials 10 | c dang = desired angle spacing for grid search 11 | c maxout = maximum number of fault planes to return: 12 | c if more are found, a random selection will be returned 13 | c nextra = number of polarity additional misfits allowed above minimum 14 | c ntotal = total number of allowed polarity misfits 15 | c qextra = additional amplitude misfit allowed above minimum 16 | c qtotal = total allowed amplitude misfit 17 | c Outputs: 18 | c nf = number of fault planes found 19 | c strike(min(maxout,nf)) = strike 20 | c dip(min(maxout,nf)) = dip 21 | c rake(min(maxout,nf)) = rake 22 | c faults(3,min(maxout,nf)) = fault normal vector 23 | c slips(3,min(maxout,nf)) = slip vector 24 | c 25 | 26 | subroutine FOCALAMP_MC(p_azi_mc,p_the_mc,sp_amp,p_pol,npsta,nmc, 27 | & dang,maxout,nextra,ntotal,qextra,qtotal,nf,strike,dip,rake, 28 | & faults,slips) 29 | 30 | include 'param.inc' 31 | include 'rot.inc' 32 | parameter (ntab=180) 33 | 34 | c input and output arrays 35 | dimension p_azi_mc(npick0,nmc0),p_the_mc(npick0,nmc0) 36 | real sp_amp(npsta) 37 | real p_a1(npick0),p_a2(npick0),p_a3(npick0) 38 | real faultnorm(3),slip(3),faults(3,nmax0),slips(3,nmax0) 39 | real strike(nmax0),dip(nmax0),rake(nmax0) 40 | integer p_pol(npsta) 41 | save dangold,nrot,b1,b2,b3 42 | save amptable,phitable,thetable 43 | cf2py intent(in) p_azi_mc 44 | cf2py intent(in) p_the_mc 45 | cf2py intent(in) sp_amp 46 | cf2py intent(in) p_pol 47 | cf2py intent(in) npsta 48 | cf2py intent(in) nmc 49 | cf2py intent(in) dang 50 | cf2py intent(in) maxout 51 | cf2py intent(in) nextra 52 | cf2py intent(in) ntotal 53 | cf2py intent(in) qextra 54 | cf2py intent(in) qtotal 55 | cf2py intent(out) nf 56 | cf2py intent(out) strike 57 | cf2py intent(out) dip 58 | cf2py intent(out) rake 59 | cf2py intent(out) faults 60 | cf2py intent(out) slips 61 | 62 | c coordinate transformation arrays 63 | real b1(3,ncoor),bb1(3) 64 | real b2(3,ncoor),bb2(3) 65 | real b3(3,ncoor),bb3(3) 66 | c P and S amplitude arrays 67 | real amptable(2,ntab,2*ntab) 68 | real phitable(2*ntab+1,2*ntab+1) 69 | real thetable(2*ntab+1) 70 | c misfit arrays 71 | real qmis(ncoor) 72 | integer nmis(ncoor) 73 | integer irotgood(ncoor),irotgood2(ncoor) 74 | 75 | pi=3.1415927 76 | degrad=180./pi 77 | 78 | if (maxout.gt.nmax0) then 79 | maxout=nmax0 80 | end if 81 | 82 | c Set up array with direction cosines for all coordinate transformations 83 | if (dang.eq.dangold) go to 8 84 | irot=0 85 | do 5 ithe=0,int(90.1/dang) 86 | the=real(ithe)*dang 87 | rthe=the/degrad 88 | costhe=cos(rthe) 89 | sinthe=sin(rthe) 90 | fnumang=360./dang 91 | numphi=nint(fnumang*sin(rthe)) 92 | if (numphi.ne.0) then 93 | dphi=360./float(numphi) 94 | else 95 | dphi=10000. 96 | end if 97 | do 4 iphi=0,int(359.9/dphi) 98 | phi=real(iphi)*dphi 99 | rphi=phi/degrad 100 | cosphi=cos(rphi) 101 | sinphi=sin(rphi) 102 | bb3(3)=costhe 103 | bb3(1)=sinthe*cosphi 104 | bb3(2)=sinthe*sinphi 105 | bb1(3)=-sinthe 106 | bb1(1)=costhe*cosphi 107 | bb1(2)=costhe*sinphi 108 | call CROSS(bb3,bb1,bb2) 109 | do 3 izeta=0,int(179.9/dang) 110 | zeta=real(izeta)*dang 111 | rzeta=zeta/degrad 112 | coszeta=cos(rzeta) 113 | sinzeta=sin(rzeta) 114 | irot=irot+1 115 | if (irot.gt.ncoor) then 116 | print *,'***FOCAL error: # of rotations too big' 117 | return 118 | end if 119 | b3(3,irot)=bb3(3) 120 | b3(1,irot)=bb3(1) 121 | b3(2,irot)=bb3(2) 122 | b1(1,irot)=bb1(1)*coszeta+bb2(1)*sinzeta 123 | b1(2,irot)=bb1(2)*coszeta+bb2(2)*sinzeta 124 | b1(3,irot)=bb1(3)*coszeta+bb2(3)*sinzeta 125 | b2(1,irot)=bb2(1)*coszeta-bb1(1)*sinzeta 126 | b2(2,irot)=bb2(2)*coszeta-bb1(2)*sinzeta 127 | b2(3,irot)=bb2(3)*coszeta-bb1(3)*sinzeta 128 | 3 continue 129 | 4 continue 130 | 5 continue 131 | nrot=irot 132 | dangold=dang 133 | 134 | astep=1./real(ntab) 135 | do 150 i=1,2*ntab+1 136 | bbb3=-1.+real(i-1)*astep 137 | thetable(i)=acos(bbb3) 138 | do 140 j=1,2*ntab+1 139 | bbb1=-1.+real(j-1)*astep 140 | phitable(i,j)=atan2(bbb3,bbb1) 141 | if (phitable(i,j).lt.0.) then 142 | phitable(i,j)=phitable(i,j)+2.*pi 143 | end if 144 | 140 continue 145 | 150 continue 146 | 147 | do 250 i=1,2*ntab 148 | phi=real(i-1)*pi*astep 149 | do 240 j=1,ntab 150 | theta=real(j-1)*pi*astep 151 | amptable(1,j,i)=abs(sin(2*theta)*cos(phi)) 152 | s1=cos(2*theta)*cos(phi) 153 | s2=-cos(theta)*sin(phi) 154 | amptable(2,j,i)=sqrt(s1*s1+s2*s2) 155 | 240 continue 156 | 250 continue 157 | 158 | 8 continue 159 | 160 | do irot=1,nrot 161 | irotgood(irot)=0 162 | end do 163 | 164 | c loop over multiple trials 165 | do 430 im=1,nmc 166 | 167 | c Convert data to Cartesian coordinates 168 | do 40 i=1,npsta 169 | call TO_CAR(p_the_mc(i,im),p_azi_mc(i,im),1., 170 | & p_a1(i),p_a2(i),p_a3(i)) 171 | 40 continue 172 | 173 | c find misfit for each solution and minimum misfit 174 | nmis0min=1e5 175 | qmis0min=1.0e5 176 | do 420 irot=1,nrot 177 | qmis(irot)=0. 178 | nmis(irot)=0 179 | do 400 ista=1,npsta 180 | p_b1= b1(1,irot)*p_a1(ista) 181 | & +b1(2,irot)*p_a2(ista) 182 | & +b1(3,irot)*p_a3(ista) 183 | p_b3= b3(1,irot)*p_a1(ista) 184 | & +b3(2,irot)*p_a2(ista) 185 | & +b3(3,irot)*p_a3(ista) 186 | if (sp_amp(ista).ne.0.) then 187 | p_proj1=p_a1(ista)-p_b3*b3(1,irot) 188 | p_proj2=p_a2(ista)-p_b3*b3(2,irot) 189 | p_proj3=p_a3(ista)-p_b3*b3(3,irot) 190 | plen=sqrt(p_proj1*p_proj1+p_proj2*p_proj2+ 191 | & p_proj3*p_proj3) 192 | p_proj1=p_proj1/plen 193 | p_proj2=p_proj2/plen 194 | p_proj3=p_proj3/plen 195 | pp_b1=b1(1,irot)*p_proj1+b1(2,irot)*p_proj2 196 | & +b1(3,irot)*p_proj3 197 | pp_b2=b2(1,irot)*p_proj1+b2(2,irot)*p_proj2 198 | & +b2(3,irot)*p_proj3 199 | i=nint((p_b3+1.)/astep)+1 200 | theta=thetable(i) 201 | i=nint((pp_b2+1.)/astep)+1 202 | j=nint((pp_b1+1.)/astep)+1 203 | phi=phitable(i,j) 204 | i=nint(phi/(pi*astep))+1 205 | if (i.gt.2*ntab) i=1 206 | j=nint(theta/(pi*astep))+1 207 | if (j.gt.ntab) j=1 208 | p_amp=amptable(1,j,i) 209 | s_amp=amptable(2,j,i) 210 | if (p_amp.eq.0.0) then 211 | sp_ratio=4.0 212 | else if (s_amp.eq.0.0) then 213 | sp_ratio=-2.0 214 | else 215 | sp_ratio=log10(4.9*s_amp/p_amp) 216 | end if 217 | qmis(irot)=qmis(irot)+abs(sp_amp(ista)-sp_ratio) 218 | 219 | end if 220 | if (p_pol(ista).ne.0) then 221 | prod=p_b1*p_b3 222 | ipol=-1 223 | if (prod.gt.0.) ipol=1 224 | if (ipol.ne.p_pol(ista)) then 225 | nmis(irot)=nmis(irot)+1 226 | end if 227 | end if 228 | 400 continue 229 | if (nmis(irot).lt.nmis0min) nmis0min=nmis(irot) 230 | if (qmis(irot).lt.qmis0min) qmis0min=qmis(irot) 231 | 420 continue 232 | 233 | nmis0max=ntotal 234 | if (nmis0max.lt.nmis0min+nextra) then 235 | nmis0max=nmis0min+nextra 236 | end if 237 | qmis0max=qtotal 238 | if (qmis0max.lt.qmis0min+qextra) then 239 | qmis0max=qmis0min+qextra 240 | end if 241 | 242 | c loop over rotations - find those meeting fit criteria 243 | 425 nadd=0 244 | do irot=1,nrot 245 | if ((nmis(irot).le.nmis0max).and. 246 | & (qmis(irot).le.qmis0max)) then 247 | irotgood(irot)=1 248 | nadd=nadd+1 249 | end if 250 | end do 251 | 252 | c print *,im,nmis0max,qmis0max,nadd 253 | 254 | if (nadd.eq.0) then ! if there are none that meet criteria 255 | qmis0min=1.0e5 ! loosen the amplitude criteria 256 | do irot=1,nrot 257 | if ((nmis(irot).le.nmis0max).and. 258 | & (qmis(irot).lt.qmis0min)) then 259 | qmis0min=qmis(irot) 260 | end if 261 | end do 262 | qmis0max=qtotal 263 | if (qmis0max.lt.qmis0min+qextra) then 264 | qmis0max=qmis0min+qextra 265 | end if 266 | goto 425 267 | end if 268 | 269 | 430 continue 270 | 271 | nfault=0 272 | do irot=1,nrot 273 | if (irotgood(irot).gt.0) then 274 | nfault=nfault+1 275 | irotgood2(nfault)=irot 276 | end if 277 | end do 278 | 279 | c Select output solutions 280 | nf=0 281 | if (nfault.le.maxout) then 282 | do i=1,nfault 283 | irot=irotgood2(i) 284 | nf=nf+1 285 | faultnorm(1)=b3(1,irot) 286 | faultnorm(2)=b3(2,irot) 287 | faultnorm(3)=b3(3,irot) 288 | slip(1)=b1(1,irot) 289 | slip(2)=b1(2,irot) 290 | slip(3)=b1(3,irot) 291 | do m=1,3 292 | faults(m,nf)=faultnorm(m) 293 | slips(m,nf)=slip(m) 294 | end do 295 | call FPCOOR(s1,d1,r1,faultnorm,slip,2) 296 | strike(nf)=s1 297 | dip(nf)=d1 298 | rake(nf)=r1 299 | end do 300 | else 301 | do 441 i=1,99999 302 | fran=rand(0) 303 | iscr=nint(fran*float(nfault)+0.5) 304 | if (iscr.lt.1) iscr=1 305 | if (iscr.gt.nfault) iscr=nfault 306 | if (irotgood2(iscr).le.0) goto 441 307 | irot=irotgood2(iscr) 308 | irotgood2(iscr)=-1 309 | nf=nf+1 310 | faultnorm(1)=b3(1,irot) 311 | faultnorm(2)=b3(2,irot) 312 | faultnorm(3)=b3(3,irot) 313 | slip(1)=b1(1,irot) 314 | slip(2)=b1(2,irot) 315 | slip(3)=b1(3,irot) 316 | do m=1,3 317 | faults(m,nf)=faultnorm(m) 318 | slips(m,nf)=slip(m) 319 | end do 320 | call FPCOOR(s1,d1,r1,faultnorm,slip,2) 321 | strike(nf)=s1 322 | dip(nf)=d1 323 | rake(nf)=r1 324 | if (nf.eq.maxout) go to 445 325 | 441 continue 326 | 445 continue 327 | end if 328 | 329 | return 330 | end 331 | 332 | c ------------------------------------------------------------------- c 333 | 334 | 335 | c subroutine GET_MISF_AMP finds the percent of misfit polarities and the 336 | c average S/P ratio misfit for a given mechanism 337 | c Inputs: npol = number of polarity observations 338 | c p_azi_mc(npol) = azimuths 339 | c p_the_mc(npol) = takeoff angles 340 | c sp_ratio(npol) = S/P ratio 341 | c p_pol(npol) = polarity observations 342 | c str_avg,dip_avg,rak_avg = mechanism 343 | c Outputs: mfrac = weighted fraction misfit polarities 344 | c mavg = average S/P misfit (log10) 345 | c stdr = station distribution ratio 346 | 347 | subroutine GET_MISF_AMP(npol,p_azi_mc,p_the_mc,sp_ratio,p_pol, 348 | & str_avg,dip_avg,rak_avg,mfrac,mavg,stdr) 349 | cf2py intent(in) npol 350 | cf2py intent(in) p_azi_mc 351 | cf2py intent(in) p_the_mc 352 | cf2py intent(in) sp_ratio 353 | cf2py intent(in) p_pol 354 | cf2py intent(in) str_avg 355 | cf2py intent(in) dip_avg 356 | cf2py intent(in) rak_avg 357 | cf2py intent(out) mfrac 358 | cf2py intent(out) mavg 359 | cf2py intent(out) stdr 360 | 361 | dimension p_azi_mc(npol),p_the_mc(npol) 362 | real str_avg,dip_avg,rak_avg,M(3,3),a(3),b(3),sp_ratio(npol) 363 | real strike,dip,rake,mfrac,mavg,qcount,azi,toff,pol,wt,wo 364 | integer k,npol,p_pol(npol) 365 | real bb1(3),bb2(3),bb3(3) 366 | 367 | rad=3.14159265/180. 368 | 369 | strike=str_avg*rad 370 | dip=dip_avg*rad 371 | rake=rak_avg*rad 372 | 373 | M(1,1)=-sin(dip)*cos(rake)*sin(2*strike)-sin(2*dip)*sin(rake)* 374 | & sin(strike)*sin(strike) 375 | M(2,2)=sin(dip)*cos(rake)*sin(2*strike)-sin(2*dip)*sin(rake)* 376 | & cos(strike)*cos(strike) 377 | M(3,3)=sin(2*dip)*sin(rake) 378 | M(1,2)=sin(dip)*cos(rake)*cos(2*strike)+0.5*sin(2*dip)*sin(rake)* 379 | & sin(2*strike) 380 | M(2,1)=M(1,2) 381 | M(1,3)=-cos(dip)*cos(rake)*cos(strike)-cos(2*dip)*sin(rake)* 382 | & sin(strike) 383 | M(3,1)=M(1,3) 384 | M(2,3)=-cos(dip)*cos(rake)*sin(strike)+cos(2*dip)*sin(rake)* 385 | & cos(strike) 386 | M(3,2)=M(2,3) 387 | call FPCOOR(strike,dip,rake,bb3,bb1,1) 388 | call CROSS(bb3,bb1,bb2) 389 | 390 | mfrac=0. 391 | qcount=0. 392 | stdr=0. 393 | scount=0. 394 | mavg=0. 395 | acount=0. 396 | 397 | do 600 k=1,npol 398 | call TO_CAR(p_the_mc(k),p_azi_mc(k),1.,p_a1, 399 | & p_a2,p_a3) 400 | p_b1= bb1(1)*p_a1 401 | & +bb1(2)*p_a2 402 | & +bb1(3)*p_a3 403 | p_b3= bb3(1)*p_a1 404 | & +bb3(2)*p_a2 405 | & +bb3(3)*p_a3 406 | p_proj1=p_a1-p_b3*bb3(1) 407 | p_proj2=p_a2-p_b3*bb3(2) 408 | p_proj3=p_a3-p_b3*bb3(3) 409 | plen=sqrt(p_proj1*p_proj1+p_proj2*p_proj2+ 410 | & p_proj3*p_proj3) 411 | p_proj1=p_proj1/plen 412 | p_proj2=p_proj2/plen 413 | p_proj3=p_proj3/plen 414 | pp_b1=bb1(1)*p_proj1+bb1(2)*p_proj2 415 | & +bb1(3)*p_proj3 416 | pp_b2=bb2(1)*p_proj1+bb2(2)*p_proj2 417 | & +bb2(3)*p_proj3 418 | phi=atan2(pp_b2,pp_b1) 419 | theta=acos(p_b3) 420 | p_amp=abs(sin(2*theta)*cos(phi)) 421 | wt=sqrt(p_amp) 422 | if (p_pol(k).ne.0) then 423 | azi=rad*p_azi_mc(k) 424 | toff=rad*p_the_mc(k) 425 | a(1)=sin(toff)*cos(azi) 426 | a(2)=sin(toff)*sin(azi) 427 | a(3)=-cos(toff) 428 | do 615 in=1,3 429 | b(in)=0 430 | do 610 jn=1,3 431 | b(in)=b(in)+M(in,jn)*a(jn) 432 | 610 continue 433 | 615 continue 434 | if ((a(1)*b(1)+a(2)*b(2)+a(3)*b(3)).lt.0) then 435 | pol=-1 436 | else 437 | pol=1 438 | end if 439 | if ((pol*p_pol(k)).lt.0) then 440 | mfrac=mfrac+wt 441 | end if 442 | qcount=qcount+wt 443 | stdr=stdr+wt 444 | scount=scount+1.0 445 | end if 446 | if (sp_ratio(k).ne.0.) then 447 | s1=cos(2*theta)*cos(phi) 448 | s2=-cos(theta)*sin(phi) 449 | s_amp=sqrt(s1*s1+s2*s2) 450 | sp_rat=log10(4.9*s_amp/p_amp) 451 | mavg=mavg+abs(sp_ratio(k)-sp_rat) 452 | acount=acount+1.0 453 | stdr=stdr+wt 454 | scount=scount+1.0 455 | end if 456 | 600 continue 457 | mfrac=mfrac/qcount 458 | if (qcount.eq.0.0) mfrac=0.0 459 | mavg=mavg/acount 460 | if (acount.eq.0.0) mavg=0.0 461 | stdr=stdr/scount 462 | if (scount.eq.0.0) stdr=0.0 463 | 464 | return 465 | end 466 | -------------------------------------------------------------------------------- /hashpy/src/fmech_subs.f: -------------------------------------------------------------------------------- 1 | c subroutine FOCALMC performs grid search to find acceptable focal mechanisms, 2 | c for multiple trials of ray azimuths and takeoff angles. 3 | c Acceptable mechanisms are those with less than "ntotal" 4 | c misfit polarities, or the minimum plus "nextra" if this 5 | c is greater. 6 | c 7 | c Inputs: 8 | c p_azi_mc(npsta,nmc) = azimuth to station from event (deg. E of N) 9 | c p_the_mc(npsta,nmc) = takeoff angle (from vert, up=0, <90 upgoing, >90 downgoing) 10 | c p_pol(npsta) = first motion, 1=up, -1=down 11 | c p_qual(npsta) = quality, 0=impulsive, 1=emergent 12 | c npsta = number of first motions 13 | c nmc = number of trials 14 | c dang = desired angle spacing for grid search 15 | c maxout = maximum number of fault planes to return: 16 | c if more are found, a random selection will be returned 17 | c nextra = number of additional misfits allowed above minimum 18 | c ntotal = total number of allowed misfits 19 | c Outputs: 20 | c nf = number of fault planes found 21 | c strike(min(maxout,nf)) = strike 22 | c dip(min(maxout,nf)) = dip 23 | c rake(min(maxout,nf)) = rake 24 | c faults(3,min(maxout,nf)) = fault normal vector 25 | c slips(3,min(maxout,nf)) = slip vector 26 | c 27 | c 28 | subroutine FOCALMC(p_azi_mc,p_the_mc,p_pol,p_qual,npsta,nmc, 29 | & dang,maxout,nextra,ntotal,nf,strike,dip, 30 | & rake,faults,slips) 31 | 32 | include 'param.inc' 33 | include 'rot.inc' 34 | 35 | c input and output arrays 36 | dimension p_azi_mc(npick0,nmc0),p_the_mc(npick0,nmc0) 37 | integer p_pol(npsta),p_qual(npsta) 38 | real p_a1(npick0),p_a2(npick0),p_a3(npick0) 39 | real faultnorm(3),slip(3),faults(3,nmax0),slips(3,nmax0) 40 | real strike(nmax0),dip(nmax0),rake(nmax0) 41 | save dangold,nrot,b1,b2,b3 42 | cf2py intent(in) p_azi_mc 43 | cf2py intent(in) p_the_mc 44 | cf2py intent(in) p_pol 45 | cf2py intent(in) p_qual 46 | cf2py intent(in) npsta 47 | cf2py intent(in) nmc 48 | cf2py intent(in) dang 49 | cf2py intent(in) maxout 50 | cf2py intent(in) nextra 51 | cf2py intent(in) ntotal 52 | cf2py intent(out) nf 53 | cf2py intent(out) strike 54 | cf2py intent(out) dip 55 | cf2py intent(out) rake 56 | cf2py intent(out) faults 57 | cf2py intent(out) slips 58 | 59 | c coordinate transformation arrays 60 | real b1(3,ncoor),bb1(3) 61 | real b2(3,ncoor),bb2(3) 62 | real b3(3,ncoor),bb3(3) 63 | 64 | c fit arrays 65 | integer fit(2,ncoor),nmiss01min(0:npick0) 66 | integer irotgood(ncoor),irotgood2(ncoor) 67 | real fran 68 | 69 | pi=3.1415927 70 | degrad=180./pi 71 | if (maxout.gt.nmax0) then 72 | maxout=nmax0 73 | end if 74 | 75 | c Set up array with direction cosines for all coordinate transformations 76 | if (dang.eq.dangold) go to 8 77 | irot=0 78 | do 5 ithe=0,int(90.1/dang) 79 | the=real(ithe)*dang 80 | rthe=the/degrad 81 | costhe=cos(rthe) 82 | sinthe=sin(rthe) 83 | fnumang=360./dang 84 | numphi=nint(fnumang*sin(rthe)) 85 | if (numphi.ne.0) then 86 | dphi=360./float(numphi) 87 | else 88 | dphi=10000. 89 | end if 90 | do 4 iphi=0,int(359.9/dphi) 91 | phi=real(iphi)*dphi 92 | rphi=phi/degrad 93 | cosphi=cos(rphi) 94 | sinphi=sin(rphi) 95 | bb3(3)=costhe 96 | bb3(1)=sinthe*cosphi 97 | bb3(2)=sinthe*sinphi 98 | bb1(3)=-sinthe 99 | bb1(1)=costhe*cosphi 100 | bb1(2)=costhe*sinphi 101 | call CROSS(bb3,bb1,bb2) 102 | do 3 izeta=0,int(179.9/dang) 103 | zeta=real(izeta)*dang 104 | rzeta=zeta/degrad 105 | coszeta=cos(rzeta) 106 | sinzeta=sin(rzeta) 107 | irot=irot+1 108 | if (irot.gt.ncoor) then 109 | print *,'***FOCAL error: # of rotations too big' 110 | return 111 | end if 112 | b3(3,irot)=bb3(3) 113 | b3(1,irot)=bb3(1) 114 | b3(2,irot)=bb3(2) 115 | b1(1,irot)=bb1(1)*coszeta+bb2(1)*sinzeta 116 | b1(2,irot)=bb1(2)*coszeta+bb2(2)*sinzeta 117 | b1(3,irot)=bb1(3)*coszeta+bb2(3)*sinzeta 118 | b2(1,irot)=bb2(1)*coszeta-bb1(1)*sinzeta 119 | b2(2,irot)=bb2(2)*coszeta-bb1(2)*sinzeta 120 | b2(3,irot)=bb2(3)*coszeta-bb1(3)*sinzeta 121 | 3 continue 122 | 4 continue 123 | 5 continue 124 | nrot=irot 125 | dangold=dang 126 | 8 continue 127 | 128 | do irot=1,nrot 129 | irotgood(irot)=0 130 | end do 131 | 132 | c loop over multiple trials 133 | do 430 im=1,nmc 134 | 135 | c Convert data to Cartesian coordinates 136 | do 40 i=1,npsta 137 | call TO_CAR(p_the_mc(i,im),p_azi_mc(i,im),1., 138 | & p_a1(i),p_a2(i),p_a3(i)) 139 | 40 continue 140 | 141 | c find misfit for each solution and minimum misfit 142 | nmiss0min=999 143 | nmissmin=999 144 | do i=0,npick0 145 | nmiss01min(i)=999 146 | end do 147 | do 420 irot=1,nrot 148 | nmiss=0 149 | nmiss0=0 150 | do 400 ista=1,npsta 151 | p_b1= b1(1,irot)*p_a1(ista) 152 | & +b1(2,irot)*p_a2(ista) 153 | & +b1(3,irot)*p_a3(ista) 154 | p_b3= b3(1,irot)*p_a1(ista) 155 | & +b3(2,irot)*p_a2(ista) 156 | & +b3(3,irot)*p_a3(ista) 157 | prod=p_b1*p_b3 158 | ipol=-1 159 | if (prod.gt.0.) ipol=1 ! predicted polarization 160 | if (ipol.ne.p_pol(ista)) then 161 | nmiss=nmiss+1 162 | if (p_qual(ista).eq.0) nmiss0=nmiss0+1 163 | end if 164 | 400 continue 165 | fit(1,irot)=nmiss0 ! misfit impulsive polarities 166 | fit(2,irot)=nmiss ! total misfit polarities 167 | if (nmiss0.lt.nmiss0min) nmiss0min=nmiss0 168 | if (nmiss.lt.nmissmin) nmissmin=nmiss 169 | if (nmiss.lt.nmiss01min(nmiss0)) then 170 | nmiss01min(nmiss0)=nmiss 171 | end if 172 | 420 continue 173 | 174 | c choose fit criteria 175 | if (nmiss0min.eq.0) then 176 | nmiss0max=ntotal 177 | nmissmax=ntotal 178 | else 179 | nmiss0max=ntotal 180 | nmissmax=npsta 181 | end if 182 | if (nmiss0max.lt.nmiss0min+nextra) then 183 | nmiss0max=nmiss0min+nextra 184 | end if 185 | if (nmissmax.lt.nmiss01min(nmiss0min)+nextra) then 186 | nmissmax=nmiss01min(nmiss0min)+nextra 187 | end if 188 | 189 | c loop over rotations - find those meeting fit criteria 190 | do 440 irot=1,nrot 191 | nmiss0=fit(1,irot) 192 | nmiss=fit(2,irot) 193 | if ((nmiss0.le.nmiss0max).and.(nmiss.le.nmissmax)) then 194 | irotgood(irot)=1 195 | end if 196 | 440 continue 197 | 198 | 430 continue 199 | 200 | nfault=0 201 | do irot=1,nrot 202 | if (irotgood(irot).gt.0) then 203 | nfault=nfault+1 204 | irotgood2(nfault)=irot 205 | end if 206 | end do 207 | 208 | c Select output solutions 209 | nf=0 210 | if (nfault.le.maxout) then 211 | do i=1,nfault 212 | irot=irotgood2(i) 213 | nf=nf+1 214 | faultnorm(1)=b3(1,irot) 215 | faultnorm(2)=b3(2,irot) 216 | faultnorm(3)=b3(3,irot) 217 | slip(1)=b1(1,irot) 218 | slip(2)=b1(2,irot) 219 | slip(3)=b1(3,irot) 220 | do m=1,3 221 | faults(m,nf)=faultnorm(m) 222 | slips(m,nf)=slip(m) 223 | end do 224 | call FPCOOR(s1,d1,r1,faultnorm,slip,2) 225 | strike(nf)=s1 226 | dip(nf)=d1 227 | rake(nf)=r1 228 | end do 229 | else 230 | do 441 i=1,99999 231 | fran=rand(0) 232 | iscr=nint(fran*float(nfault)+0.5) 233 | if (iscr.lt.1) iscr=1 234 | if (iscr.gt.nfault) iscr=nfault 235 | if (irotgood2(iscr).le.0) goto 441 236 | irot=irotgood2(iscr) 237 | irotgood2(iscr)=-1 238 | nf=nf+1 239 | faultnorm(1)=b3(1,irot) 240 | faultnorm(2)=b3(2,irot) 241 | faultnorm(3)=b3(3,irot) 242 | slip(1)=b1(1,irot) 243 | slip(2)=b1(2,irot) 244 | slip(3)=b1(3,irot) 245 | do m=1,3 246 | faults(m,nf)=faultnorm(m) 247 | slips(m,nf)=slip(m) 248 | end do 249 | call FPCOOR(s1,d1,r1,faultnorm,slip,2) 250 | strike(nf)=s1 251 | dip(nf)=d1 252 | rake(nf)=r1 253 | if (nf.eq.maxout) go to 445 254 | 441 continue 255 | 445 continue 256 | end if 257 | 258 | return 259 | end 260 | -------------------------------------------------------------------------------- /hashpy/src/param.inc: -------------------------------------------------------------------------------- 1 | c npick0 = maximum number of picks per event 2 | c nmc0 = maximum number of trials of location/take-off angles 3 | c nmax0 = maximum number of acceptable mechanisms output 4 | parameter (npick0=500,nmc0=500,nmax0=500) 5 | -------------------------------------------------------------------------------- /hashpy/src/pol_subs.f: -------------------------------------------------------------------------------- 1 | c subroutine GET_MISF finds the percent of misfit polarities for a given mechanism 2 | c Inputs: npol = number of polarity observations 3 | c p_azi_mc(npol) = azimuths 4 | c p_the_mc(npol) = takeoff angles 5 | c p_pol(npol) = polarity observations 6 | c p_qual(npol) = quality of polarity observations 7 | c str_avg,dip_avg,rak_avg = mechanism 8 | c Outputs: mfrac = weighted fraction misfit polarities (like FPFIT) 9 | c stdr = station distribution ratio (like FPFIT) 10 | 11 | subroutine GET_MISF(npol,p_azi_mc,p_the_mc,p_pol,p_qual,str_avg, 12 | & dip_avg,rak_avg,mfrac,stdr) 13 | 14 | dimension p_azi_mc(npol),p_the_mc(npol) 15 | real str_avg,dip_avg,rak_avg,M(3,3),a(3),b(3) 16 | real strike,dip,rake,mfrac,qcount,azi,toff,pol,wt,wo 17 | integer k,npol,p_pol(npol),p_qual(npol) 18 | real bb1(3),bb2(3),bb3(3) 19 | 20 | cf2py intent(in) npol 21 | cf2py intent(in) p_azi_mc 22 | cf2py intent(in) p_the_mc 23 | cf2py intent(in) p_pol 24 | cf2py intent(in) p_qual 25 | cf2py intent(in) str_avg 26 | cf2py intent(in) dip_avg 27 | cf2py intent(in) rak_avg 28 | cf2py intent(out) mfrac 29 | cf2py intent(out) stdr 30 | 31 | rad=3.14159265/180. 32 | 33 | strike=str_avg*rad 34 | dip=dip_avg*rad 35 | rake=rak_avg*rad 36 | 37 | M(1,1)=-sin(dip)*cos(rake)*sin(2*strike)-sin(2*dip)*sin(rake)* 38 | & sin(strike)*sin(strike) 39 | M(2,2)=sin(dip)*cos(rake)*sin(2*strike)-sin(2*dip)*sin(rake)* 40 | & cos(strike)*cos(strike) 41 | M(3,3)=sin(2*dip)*sin(rake) 42 | M(1,2)=sin(dip)*cos(rake)*cos(2*strike)+0.5*sin(2*dip)*sin(rake)* 43 | & sin(2*strike) 44 | M(2,1)=M(1,2) 45 | M(1,3)=-cos(dip)*cos(rake)*cos(strike)-cos(2*dip)*sin(rake)* 46 | & sin(strike) 47 | M(3,1)=M(1,3) 48 | M(2,3)=-cos(dip)*cos(rake)*sin(strike)+cos(2*dip)*sin(rake)* 49 | & cos(strike) 50 | M(3,2)=M(2,3) 51 | call FPCOOR(strike,dip,rake,bb3,bb1,1) 52 | call CROSS(bb3,bb1,bb2) 53 | mfrac=0. 54 | qcount=0. 55 | scount=0. 56 | 57 | do 600 k=1,npol 58 | call TO_CAR(p_the_mc(k),p_azi_mc(k),1.,p_a1, 59 | & p_a2,p_a3) 60 | p_b1= bb1(1)*p_a1 61 | & +bb1(2)*p_a2 62 | & +bb1(3)*p_a3 63 | p_b3= bb3(1)*p_a1 64 | & +bb3(2)*p_a2 65 | & +bb3(3)*p_a3 66 | p_proj1=p_a1-p_b3*bb3(1) 67 | p_proj2=p_a2-p_b3*bb3(2) 68 | p_proj3=p_a3-p_b3*bb3(3) 69 | plen=sqrt(p_proj1*p_proj1+p_proj2*p_proj2+ 70 | & p_proj3*p_proj3) 71 | pp_b1=bb1(1)*p_proj1+bb1(2)*p_proj2 72 | & +bb1(3)*p_proj3 73 | pp_b2=bb2(1)*p_proj1+bb2(2)*p_proj2 74 | & +bb2(3)*p_proj3 75 | phi=atan2(pp_b2,pp_b1) 76 | theta=acos(p_b3) 77 | p_amp=abs(sin(2*theta)*cos(phi)) 78 | wt=sqrt(p_amp) 79 | azi=rad*p_azi_mc(k) 80 | toff=rad*p_the_mc(k) 81 | a(1)=sin(toff)*cos(azi) 82 | a(2)=sin(toff)*sin(azi) 83 | a(3)=-cos(toff) 84 | do in=1,3 85 | b(in)=0 86 | do jn=1,3 87 | b(in)=b(in)+M(in,jn)*a(jn) 88 | end do 89 | end do 90 | if ((a(1)*b(1)+a(2)*b(2)+a(3)*b(3)).lt.0) then 91 | pol=-1 92 | else 93 | pol=1 94 | end if 95 | if (p_qual(k).eq.0) then 96 | wo=1 97 | else 98 | wo=0.5 99 | end if 100 | if ((pol*p_pol(k)).lt.0) then 101 | mfrac=mfrac+wt*wo 102 | end if 103 | qcount=qcount+wt*wo 104 | scount=scount+wo 105 | 600 continue 106 | mfrac=mfrac/qcount 107 | stdr=qcount/scount 108 | 109 | return 110 | end 111 | 112 | c --------------------------------------------------------------- c 113 | 114 | 115 | c subroutine GET_GAP finds the maximum azimuthal and takeoff angle gaps 116 | c Inputs: npol = number of polarity observations 117 | c p_azi_mc(npol) = azimuths 118 | c p_the_mc(npol) = takeoff angles 119 | c Outputs: magap = maximum azimuthal gap 120 | c mpgap = maximum takeoff angle gap 121 | 122 | subroutine GET_GAP(npol,p_azi_mc,p_the_mc,magap,mpgap) 123 | 124 | include 'param.inc' 125 | dimension p_azi_mc(npol),p_the_mc(npol) 126 | real p2_azi(npick0),p2_the(npick0) 127 | 128 | cf2py intent(in) npol 129 | cf2py intent(in) p_azi_mc 130 | cf2py intent(in) p_the_mc 131 | cf2py intent(out) magap 132 | cf2py intent(out) mpgap 133 | 134 | do 403 k=1,npol 135 | if (p_the_mc(k).gt.90) then 136 | p2_the(k)=180.-p_the_mc(k) 137 | p2_azi(k)=p_azi_mc(k)-180. 138 | if (p2_azi(k).lt.0) p2_azi(k)=p2_azi(k)+360. 139 | else 140 | p2_the(k)=p_the_mc(k) 141 | p2_azi(k)=p_azi_mc(k) 142 | end if 143 | 403 continue 144 | call sort(npol,p2_azi) 145 | call sort(npol,p2_the) 146 | magap=0 147 | mpgap=0 148 | do 405 k=2,npol 149 | if (p2_azi(k)-p2_azi(k-1).gt.magap) then 150 | magap=p2_azi(k)-p2_azi(k-1) 151 | end if 152 | if (p2_the(k)-p2_the(k-1).gt.mpgap) then 153 | mpgap=p2_the(k)-p2_the(k-1) 154 | end if 155 | 405 continue 156 | if (p2_azi(1)-p2_azi(npol)+360.gt.magap) then 157 | magap=p2_azi(1)-p2_azi(npol)+360 158 | end if 159 | if (90.-p2_the(npol).gt.mpgap) then 160 | mpgap=90.-p2_the(npol) 161 | end if 162 | if (p2_the(1).gt.mpgap) then 163 | mpgap=p2_the(1) 164 | end if 165 | 166 | return 167 | end 168 | 169 | c --------------------------------------------------------------- c 170 | 171 | subroutine sort(N,RA) 172 | 173 | dimension RA(N) 174 | 175 | if (n.eq.0) then 176 | print *,'***n=0 in SORT' 177 | return 178 | end if 179 | L=N/2+1 180 | IR=N 181 | 10 CONTINUE 182 | IF(L.GT.1)THEN 183 | L=L-1 184 | RRA=RA(L) 185 | ELSE 186 | RRA=RA(IR) 187 | RA(IR)=RA(1) 188 | IR=IR-1 189 | IF(IR.EQ.1)THEN 190 | RA(1)=RRA 191 | RETURN 192 | ENDIF 193 | ENDIF 194 | I=L 195 | J=L+L 196 | 20 IF(J.LE.IR)THEN 197 | IF(J.LT.IR)THEN 198 | IF(RA(J).LT.RA(J+1))J=J+1 199 | ENDIF 200 | IF(RRA.LT.RA(J))THEN 201 | RA(I)=RA(J) 202 | I=J 203 | J=J+J 204 | ELSE 205 | J=IR+1 206 | ENDIF 207 | GO TO 20 208 | ENDIF 209 | RA(I)=RRA 210 | GO TO 10 211 | END 212 | -------------------------------------------------------------------------------- /hashpy/src/rot.inc: -------------------------------------------------------------------------------- 1 | c dang0 : minimum grid spacing (degrees) 2 | c ncoor : number of test mechanisms 3 | 4 | c choose one, based on your computer's memory and speed 5 | c parameter (dang0=10.0,ncoor=4032) 6 | c parameter (dang0=7.0,ncoor=10426) 7 | parameter (dang0=5.0,ncoor=31032) 8 | c parameter (dang0=3.0,ncoor=141180) 9 | c parameter (dang0=2.0,ncoor=472410) 10 | -------------------------------------------------------------------------------- /hashpy/src/station_subs.f: -------------------------------------------------------------------------------- 1 | 2 | c GETSTAT_TRI finds station locations for TriNet stations 3 | c 4 | c inputs: 5 | c stlfile - file with the stations and locations, in alphabetical order! 6 | c snam - name of the station of interest, 4 characters 7 | c scom - station component, 3 characters 8 | c snet - network, 2 characters 9 | c outputs: 10 | c flat,flon,felev - station lat, lon, and elevation 11 | c 12 | c input file "stlfile" format: 13 | c columns format value 14 | c ------------------------- 15 | c 1-4 a4 station name 16 | c 6-8 a3 station component 17 | c 42-50 f9.5 station latitude (degrees, signed) 18 | c 52-61 f10.5 station longitude (degrees, signed) 19 | c 63-67 i5 station elevation (meters) 20 | c 91-92 a2 network code 21 | c 22 | c 23 | subroutine GETSTAT_TRI(stlfile,snam,scom,snet,flat, 24 | & flon,felev) 25 | parameter(nsta0=20000) 26 | character stlfile*100 27 | character*4 snam,stname(nsta0) 28 | character*3 scom,scompt(nsta0),scom2 29 | character*2 snet,snetwk(nsta0) 30 | real slat(nsta0),slon(nsta0),selev(nsta0) 31 | logical firstcall 32 | save firstcall,stname,slat,slon,selev,nsta,scompt,snetwk 33 | data firstcall/.true./ 34 | 35 | cf2py intent(in) stlfile 36 | cf2py intent(in) snam 37 | cf2py intent(in) scom 38 | cf2py intent(in) snet 39 | cf2py intent(out) flat 40 | cf2py intent(out) flon 41 | cf2py intent(out) felev 42 | 43 | c read in station list - in alphabetical order! 44 | if (firstcall) then 45 | firstcall=.false. 46 | open (19,file=stlfile) 47 | do i=1,nsta0 48 | read (19,11,end=12) stname(i),scompt(i),slat(i), 49 | & slon(i),ntemp,snetwk(i) 50 | selev(i)=real(ntemp)/1000.0 51 | end do 52 | 11 format (a4,1x,a3,33x,f9.5,1x,f10.5,1x,i5,23x,a2) 53 | 12 nsta=i-1 54 | close (19) 55 | end if 56 | 57 | scom2=scom ! short-period stations are 58 | if (scom(1:1).eq."V") scom2(1:1)="E" ! interchangably called V and E 59 | if (scom(1:1).eq."E") scom2(1:1)="V" 60 | 61 | c binary search for station name 62 | i1=1 63 | i2=nsta 64 | do 30 it=1,30 65 | i=(i1+i2)/2 66 | if (snam.eq.stname(i)) then 67 | goto 40 68 | else if (i1.eq.i2) then 69 | goto 999 70 | else if (snam.lt.stname(i)) then 71 | i2=i-1 72 | else 73 | i1=i+1 74 | end if 75 | 30 continue 76 | goto 999 77 | 78 | c search for proper component/network 79 | 40 i1=i 80 | 45 continue 81 | if (i1.gt.nsta) goto 50 82 | if (snam.ne.stname(i1)) goto 50 83 | if ((scom(1:2).eq.scompt(i1)(1:2)).and. 84 | & snet.eq.snetwk(i1)) goto 900 85 | if ((scom2(1:2).eq.scompt(i1)(1:2)).and. 86 | & snet.eq.snetwk(i1)) goto 900 87 | if ((scom(1:2).eq.'XX').and. 88 | & (snet.eq.'XX')) goto 900 89 | i1=i1+1 90 | goto 45 91 | 50 i1=i-1 92 | 55 continue 93 | if (i1.lt.1) goto 999 94 | if (snam.ne.stname(i1)) goto 999 95 | if ((scom(1:2).eq.scompt(i1)(1:2)).and. 96 | & snet.eq.snetwk(i1)) goto 900 97 | if ((scom2(1:2).eq.scompt(i1)(1:2)).and. 98 | & snet.eq.snetwk(i1)) goto 900 99 | if ((scom(1:2).eq.'XX').and. 100 | & (snet.eq.'XX')) goto 900 101 | i1=i1-1 102 | goto 55 103 | 104 | 900 flat=slat(i1) 105 | flon=slon(i1) 106 | felev=selev(i1) 107 | return 108 | 999 print *,'***station not found ',snam,' ',scom,' ',snet 109 | flat=999. 110 | flon=999. 111 | felev=999. 112 | return 113 | end 114 | 115 | c --------------------------------------------------------------- c 116 | 117 | 118 | c CHECK_POL determines whether the polarity of a given station 119 | c was reversed at a given time. 120 | c 121 | c inputs: 122 | c polfile - file with the stations and times of reversal; 123 | c must be in alphabetical order; if a station is 124 | c reversed during multiple time periods, it is 125 | c listed on multiple lines (same as FPFIT) 126 | c snam - name of the station of interest, 4 characters 127 | c evyr - year of interest, 4 digits 128 | c evmon - month of interest 129 | c evdy - day of interest 130 | c evhr - hour of interest (not implemented) 131 | c output: 132 | c stpol - station polarity: 1=correct, -1=reversed 133 | c 134 | c input file "polfile" format: 135 | c columns format value 136 | c ------------------------- 137 | c 1-4 a4 station name 138 | c 6-9 i4 begining of reversal: year 139 | c 10-11 i2 month 140 | c 12-13 i2 day 141 | c 15-18 i4 end of reversal: year 142 | c 19-20 i2 month 143 | c 21-22 i2 day 144 | 145 | subroutine CHECK_POL(polfile,snam,evyr,evmon,evdy,evhr,stpol) 146 | parameter(nsta0=300) 147 | character polfile*100,polfileold*100 148 | character*4 snam,statname(nsta0) 149 | integer begtime(nsta0),endtime(nsta0) 150 | integer evyr,evmon,evdy,evhr,stpol,nstat(nsta0),nth(nsta0) 151 | integer i,i1,i2,count,itemp,nrev,evtime 152 | save polfileold,statname,begtime,endtime,nrev,nstat,nth 153 | 154 | cf2py intent(in) polfile 155 | cf2py intent(in) snam 156 | cf2py intent(in) evyr 157 | cf2py intent(in) evmon 158 | cf2py intent(in) evday 159 | cf2py intent(in) evhr 160 | cf2py intent(out) stpol 161 | 162 | c read in polarity reversal file - in alphabetical order 163 | if (polfile.ne.polfileold) then 164 | print *,'Reading polarity reversal file ',polfile 165 | open (19,file=polfile) 166 | do i=1,300 167 | read (19,11,end=12) statname(i),begtime(i),endtime(i) 168 | if (endtime(i).eq.0) then 169 | endtime(i)=99999999 170 | end if 171 | end do 172 | 11 format (a4,1x,i8,1x,i8) 173 | 12 nrev=i-1 174 | close (19) 175 | polfileold=polfile 176 | nth(1)=1 177 | nstat(1)=1 178 | count=1 179 | do 17 i=2,nrev 180 | if (statname(i).eq.statname(i-1)) then 181 | count=count+1 182 | else 183 | count=1 184 | end if 185 | nth(i)=count 186 | do itemp=i-count+1,i 187 | nstat(itemp)=count 188 | end do 189 | 17 continue 190 | end if 191 | 192 | evtime=evyr*10000+evmon*100+evdy 193 | stpol=1 194 | 195 | c binary search for a station 196 | i1=1 197 | i2=nrev 198 | 20 continue 199 | i=(i1+i2)/2 200 | if (snam.eq.statname(i)) then 201 | do 25 itemp=i-nth(i)+1,i+nstat(i)-nth(i) 202 | if ((evtime.ge.begtime(itemp)).and. 203 | & (evtime.le.endtime(itemp))) then 204 | stpol=-1 205 | goto 30 206 | end if 207 | 25 continue 208 | goto 30 209 | else if (i1.ge.i2) then 210 | goto 30 211 | else if (snam.lt.statname(i)) then 212 | i2=i-1 213 | else 214 | i1=i+1 215 | end if 216 | goto 20 217 | 30 continue 218 | return 219 | end 220 | 221 | c ------------------------------------------------------------------- c 222 | 223 | c GET_COR reads a file of station amplitude corrections 224 | c 225 | c inputs: 226 | c stlfile - file with the stations and locations 227 | c snam - name of the station of interest, 4 characters 228 | c scom - station component, 3 characters 229 | c snet - network, 2 characters 230 | c outputs: 231 | c qcor - corrections to be subtracted from log(S/P) 232 | c 233 | c input file format: 234 | c columns format variable 235 | c ------------------------- 236 | c 1-4 a4 station name 237 | c 7-9 a3 station component (vertical - Z optional) 238 | c 11-12 a2 network code 239 | c 14-20 f7.4 correction to be subtracted from log(S/P) 240 | c 241 | c 242 | subroutine GET_COR(stlfile,snam,scom,snet,qcor) 243 | parameter(nsta0=10000) 244 | character stlfile*100 245 | character*4 snam,stname(nsta0) 246 | character*3 scom,scom2,scompt(nsta0) 247 | character*2 snet,snetwk(nsta0) 248 | real corr_val(nsta0) 249 | logical firstcall 250 | save firstcall,stname,corr_val,nsta,scompt,snetwk 251 | data firstcall/.true./ 252 | cf2py intent(in) stlfile 253 | cf2py intent(in) snam 254 | cf2py intent(in) scom 255 | cf2py intent(in) snet 256 | cf2py intent(out) qcor 257 | 258 | c read in station list - in alphabetical order! 259 | if (firstcall) then 260 | firstcall=.false. 261 | open (19,file=stlfile) 262 | do 10 i=1,nsta0 263 | read (19,11,end=12) stname(i),scompt(i),snetwk(i), 264 | & corr_val(i) 265 | 10 continue 266 | 11 format (a4,2x,a3,a2,1x,f7.4) 267 | 12 nsta=i-1 268 | close (19) 269 | end if 270 | 271 | scom2=scom ! short-period stations are 272 | if (scom(1:1).eq."V") scom2(1:1)="E" ! called both V and E 273 | if (scom(1:1).eq."E") scom2(1:1)="V" 274 | 275 | c binary search for station name 276 | i1=1 277 | i2=nsta 278 | do 30 it=1,30 279 | i=(i1+i2)/2 280 | if (snam.eq.stname(i)) then 281 | goto 40 282 | else if (i1.eq.i2) then 283 | goto 999 284 | else if (snam.lt.stname(i)) then 285 | i2=i-1 286 | else 287 | i1=i+1 288 | end if 289 | 30 continue 290 | print *,'station not found' 291 | goto 999 292 | 293 | c search for proper component/network 294 | 40 i1=i 295 | 45 continue 296 | if (i1.gt.nsta) goto 50 297 | if (snam.ne.stname(i1)) goto 50 298 | if (scom(1:2).eq.scompt(i1)(1:2)) goto 900 299 | if (scom2(1:2).eq.scompt(i1)(1:2)) goto 900 300 | i1=i1+1 301 | goto 45 302 | 50 i1=i-1 303 | 55 continue 304 | if (i1.lt.1) goto 999 305 | if (snam.ne.stname(i1)) goto 999 306 | if (scom(1:2).eq.scompt(i1)(1:2)) goto 900 307 | if (scom2(1:2).eq.scompt(i1)(1:2)) goto 900 308 | i1=i1-1 309 | goto 55 310 | 311 | 900 qcor=corr_val(i1) 312 | return 313 | 999 print *,'GET_COR ***station not found ',snam,' ',scom,' ',snet, 314 | & ' in file ',stlfile 315 | qcor=-999. 316 | return 317 | end 318 | 319 | -------------------------------------------------------------------------------- /hashpy/src/station_subs_5char.f: -------------------------------------------------------------------------------- 1 | 2 | c GETSTAT_SCSN finds station locations for SCSN stations 3 | c 4 | c inputs: 5 | c stlfile - file with the stations and locations, in alphabetical order! 6 | c snam - name of the station of interest, 4 characters 7 | c scom - station component, 3 characters 8 | c snet - network, 2 characters 9 | c outputs: 10 | c flat,flon,felev - station lat, lon, and elevation 11 | c 12 | c input file "stlfile" format = SCEDC format 13 | c columns format value 14 | c ------------------------- 15 | c 1-2 a2 network code 16 | c 5-9 a5 station name 17 | c 11-13 a3 station component 18 | c 61-69 f9.5 station latitude (degrees, signed) 19 | c 71-80 f10.5 station longitude (degrees, signed) 20 | c 82-86 i5 station elevation (meters) 21 | c 22 | c 23 | subroutine GETSTAT_SCSN(stlfile,snam,scom,snet,flat, 24 | & flon,felev) 25 | parameter(nsta0=20000) 26 | character stlfile*100 27 | character*5 snam,stname(nsta0) 28 | character*3 scom,scompt(nsta0),scom2 29 | character*2 snet,snetwk(nsta0) 30 | real slat(nsta0),slon(nsta0),selev(nsta0) 31 | logical firstcall 32 | save firstcall,stname,slat,slon,selev,nsta,scompt,snetwk 33 | data firstcall/.true./ 34 | 35 | c read in station list - in alphabetical order! 36 | if (firstcall) then 37 | firstcall=.false. 38 | open (19,file=stlfile) 39 | do i=1,nsta0 40 | read (19,11,end=12) snetwk(i),stname(i),scompt(i), 41 | & slat(i),slon(i),ntemp 42 | selev(i)=real(ntemp)/1000.0 43 | end do 44 | 11 format (a2,2x,a5,1x,a3,37x,f9.5,1x,f10.5,1x,i5) 45 | 12 nsta=i-1 46 | close (19) 47 | end if 48 | 49 | scom2=scom ! short-period stations are 50 | if (scom(1:1).eq."V") scom2(1:1)="E" ! interchangably called V and E 51 | if (scom(1:1).eq."E") scom2(1:1)="V" 52 | 53 | c binary search for station name 54 | i1=1 55 | i2=nsta 56 | do 30 it=1,30 57 | i=(i1+i2)/2 58 | if (snam.eq.stname(i)) then 59 | goto 40 60 | else if (i1.eq.i2) then 61 | goto 999 62 | else if (snam.lt.stname(i)) then 63 | i2=i-1 64 | else 65 | i1=i+1 66 | end if 67 | 30 continue 68 | goto 999 69 | 70 | c search for proper component/network 71 | 40 i1=i 72 | 45 continue 73 | if (i1.gt.nsta) goto 50 74 | if (snam.ne.stname(i1)) goto 50 75 | if ((scom(1:2).eq.scompt(i1)(1:2)).and. 76 | & snet.eq.snetwk(i1)) goto 900 77 | if ((scom2(1:2).eq.scompt(i1)(1:2)).and. 78 | & snet.eq.snetwk(i1)) goto 900 79 | if ((scom(1:2).eq.'XX').and. 80 | & (snet.eq.'XX')) goto 900 81 | i1=i1+1 82 | goto 45 83 | 50 i1=i-1 84 | 55 continue 85 | if (i1.lt.1) goto 999 86 | if (snam.ne.stname(i1)) goto 999 87 | if ((scom(1:2).eq.scompt(i1)(1:2)).and. 88 | & snet.eq.snetwk(i1)) goto 900 89 | if ((scom2(1:2).eq.scompt(i1)(1:2)).and. 90 | & snet.eq.snetwk(i1)) goto 900 91 | if ((scom(1:2).eq.'XX').and. 92 | & (snet.eq.'XX')) goto 900 93 | i1=i1-1 94 | goto 55 95 | 96 | 900 flat=slat(i1) 97 | flon=slon(i1) 98 | felev=selev(i1) 99 | return 100 | 999 print *,'***station not found ',snam,' ',scom,' ',snet 101 | flat=999. 102 | flon=999. 103 | felev=999. 104 | return 105 | end 106 | 107 | c --------------------------------------------------------------- c 108 | 109 | 110 | c CHECK_POL determines whether the polarity of a given station 111 | c was reversed at a given time. 112 | c 113 | c inputs: 114 | c polfile - file with the stations and times of reversal; 115 | c must be in alphabetical order; if a station is 116 | c reversed during multiple time periods, it is 117 | c listed on multiple lines (same as FPFIT) 118 | c snam - name of the station of interest, 4 characters 119 | c evyr - year of interest, 4 digits 120 | c evmon - month of interest 121 | c evdy - day of interest 122 | c evhr - hour of interest (not implemented) 123 | c output: 124 | c stpol - station polarity: 1=correct, -1=reversed 125 | c 126 | c input file "polfile" format: 127 | c columns format value 128 | c ------------------------- 129 | c 1-5 a5 station name 130 | c 6-9 i4 begining of reversal: year 131 | c 10-11 i2 month 132 | c 12-13 i2 day 133 | c 15-18 i4 end of reversal: year 134 | c 19-20 i2 month 135 | c 21-22 i2 day 136 | 137 | subroutine CHECK_POL(polfile,snam,evyr,evmon,evdy,evhr,stpol) 138 | parameter(nsta0=300) 139 | character polfile*100,polfileold*100 140 | character*5 snam,statname(nsta0) 141 | integer begtime(nsta0),endtime(nsta0) 142 | integer evyr,evmon,evdy,evhr,stpol,nstat(nsta0),nth(nsta0) 143 | integer i,i1,i2,count,itemp,nrev,evtime 144 | save polfileold,statname,begtime,endtime,nrev,nstat,nth 145 | 146 | c read in polarity reversal file - in alphabetical order 147 | if (polfile.ne.polfileold) then 148 | print *,'Reading polarity reversal file ',polfile 149 | open (19,file=polfile) 150 | do i=1,300 151 | read (19,11,end=12) statname(i),begtime(i),endtime(i) 152 | if (endtime(i).eq.0) then 153 | endtime(i)=99999999 154 | end if 155 | end do 156 | 11 format (a5,i8,1x,i8) 157 | 12 nrev=i-1 158 | close (19) 159 | polfileold=polfile 160 | nth(1)=1 161 | nstat(1)=1 162 | count=1 163 | do 17 i=2,nrev 164 | if (statname(i).eq.statname(i-1)) then 165 | count=count+1 166 | else 167 | count=1 168 | end if 169 | nth(i)=count 170 | do itemp=i-count+1,i 171 | nstat(itemp)=count 172 | end do 173 | 17 continue 174 | end if 175 | 176 | evtime=evyr*10000+evmon*100+evdy 177 | stpol=1 178 | 179 | c binary search for a station 180 | i1=1 181 | i2=nrev 182 | 20 continue 183 | i=(i1+i2)/2 184 | if (snam.eq.statname(i)) then 185 | do 25 itemp=i-nth(i)+1,i+nstat(i)-nth(i) 186 | if ((evtime.ge.begtime(itemp)).and. 187 | & (evtime.le.endtime(itemp))) then 188 | stpol=-1 189 | goto 30 190 | end if 191 | 25 continue 192 | goto 30 193 | else if (i1.ge.i2) then 194 | goto 30 195 | else if (snam.lt.statname(i)) then 196 | i2=i-1 197 | else 198 | i1=i+1 199 | end if 200 | goto 20 201 | 30 continue 202 | return 203 | end 204 | 205 | c ------------------------------------------------------------------- c 206 | 207 | c GET_COR reads a file of station amplitude corrections 208 | c 209 | c inputs: 210 | c stlfile - file with the stations and locations 211 | c snam - name of the station of interest, 4 characters 212 | c scom - station component, 3 characters 213 | c snet - network, 2 characters 214 | c outputs: 215 | c qcor - corrections to be subtracted from log(S/P) 216 | c 217 | c input file format: 218 | c columns format variable 219 | c ------------------------- 220 | c 1-5 a5 station name 221 | c 7-9 a3 station component (vertical - Z optional) 222 | c 11-12 a2 network code 223 | c 14-20 f7.4 correction to be subtracted from log(S/P) 224 | c 225 | c 226 | subroutine GET_COR(stlfile,snam,scom,snet,qcor) 227 | parameter(nsta0=10000) 228 | character stlfile*100 229 | character*5 snam,stname(nsta0) 230 | character*3 scom,scom2,scompt(nsta0) 231 | character*2 snet,snetwk(nsta0) 232 | real corr_val(nsta0) 233 | logical firstcall 234 | save firstcall,stname,corr_val,nsta,scompt,snetwk 235 | data firstcall/.true./ 236 | 237 | c read in station list - in alphabetical order! 238 | if (firstcall) then 239 | firstcall=.false. 240 | open (19,file=stlfile) 241 | do 10 i=1,nsta0 242 | read (19,11,end=12) stname(i),scompt(i),snetwk(i), 243 | & corr_val(i) 244 | 10 continue 245 | 11 format (a5,1x,a3,a2,1x,f7.4) 246 | 12 nsta=i-1 247 | close (19) 248 | end if 249 | 250 | scom2=scom ! short-period stations are 251 | if (scom(1:1).eq."V") scom2(1:1)="E" ! called both V and E 252 | if (scom(1:1).eq."E") scom2(1:1)="V" 253 | 254 | c binary search for station name 255 | i1=1 256 | i2=nsta 257 | do 30 it=1,30 258 | i=(i1+i2)/2 259 | if (snam.eq.stname(i)) then 260 | goto 40 261 | else if (i1.eq.i2) then 262 | goto 999 263 | else if (snam.lt.stname(i)) then 264 | i2=i-1 265 | else 266 | i1=i+1 267 | end if 268 | 30 continue 269 | print *,'station not found' 270 | goto 999 271 | 272 | c search for proper component/network 273 | 40 i1=i 274 | 45 continue 275 | if (i1.gt.nsta) goto 50 276 | if (snam.ne.stname(i1)) goto 50 277 | if (scom(1:2).eq.scompt(i1)(1:2)) goto 900 278 | if (scom2(1:2).eq.scompt(i1)(1:2)) goto 900 279 | i1=i1+1 280 | goto 45 281 | 50 i1=i-1 282 | 55 continue 283 | if (i1.lt.1) goto 999 284 | if (snam.ne.stname(i1)) goto 999 285 | if (scom(1:2).eq.scompt(i1)(1:2)) goto 900 286 | if (scom2(1:2).eq.scompt(i1)(1:2)) goto 900 287 | i1=i1-1 288 | goto 55 289 | 290 | 900 qcor=corr_val(i1) 291 | return 292 | 999 print *,'GET_COR ***station not found ',snam,' ',scom,' ',snet, 293 | & ' in file ',stlfile 294 | qcor=-999. 295 | return 296 | end 297 | 298 | -------------------------------------------------------------------------------- /hashpy/src/uncert_subs.f: -------------------------------------------------------------------------------- 1 | c subroutine MECH_PROB determines the average focal mechanism of a set 2 | c of mechanisms, after removing outliers, and returns the probability 3 | c of the mechanism being within a given cutoff angle of the result, 4 | c also checks outliers for multiple solutions and returns any 5 | c 6 | c Inputs: nf = number of fault planes 7 | c norm1(3,nf) = normal to fault plane 8 | c norm2(3,nf) = slip vector 9 | c cangle = cutoff angle 10 | c prob_max = cutoff percent for multiples 11 | c Output: nsltn = number of solutions, up to 5 12 | c str_avg(5) = average strike 13 | c dip_avg(5) = average dip 14 | c rak_avg(5) = average rake 15 | c prob(5) = percent of mechs within cutoff angle 16 | c of average mechanism 17 | c rms_diff(2,5) = RMS angular difference of all planes to average 18 | c plane (1=fault plane, 2=auxiliary plane) 19 | c 20 | 21 | subroutine MECH_PROB(nf,norm1in,norm2in,cangle,prob_max,nsltn, 22 | & str_avg,dip_avg,rak_avg,prob,rms_diff) 23 | 24 | include 'param.inc' 25 | 26 | integer nf 27 | real str_avg(5),dip_avg(5),rak_avg(5),rota(nmax0) 28 | real norm1(3,nmax0),norm2(3,nmax0),temp1(3),temp2(3) 29 | real norm1in(3,nf),norm2in(3,nf),ln_norm1,ln_norm2 30 | real norm1_avg(3),norm2_avg(3),slipol,rms_diff(2,5) 31 | real stv(2),udv(3),dd_rad,di_rad,a,b,prob(5) 32 | 33 | pi=3.1415927 34 | degrad=180./3.1415927 35 | 36 | cf2py intent(in) nf 37 | cf2py intent(in) norm1 38 | cf2py intent(in) norm2 39 | cf2py intent(in) cangle 40 | cf2py intent(in) prob_max 41 | cf2py intent(out) nsltn 42 | cf2py intent(out) str_avg 43 | cf2py intent(out) dip_avg 44 | cf2py intent(out) rak_avg 45 | cf2py intent(out) prob 46 | cf2py intent(out) rms_diff 47 | 48 | c if there is only one mechanism, return that mechanism 49 | 50 | if (nf.le.1) then 51 | do i=1,3 52 | norm1_avg(i)=norm1in(i,1) 53 | norm2_avg(i)=norm2in(i,1) 54 | end do 55 | call fpcoor(str_avg(1),dip_avg(1),rak_avg(1), 56 | & norm1_avg,norm2_avg,2) 57 | prob(1)=1. 58 | rms_diff(1,1)=0. 59 | rms_diff(2,1)=0. 60 | nsltn=1 61 | return 62 | end if 63 | 64 | c otherwise find the prefered mechanism and any multiples 65 | 66 | do j=1,nf 67 | do i=1,3 68 | norm1(i,j)=norm1in(i,j) 69 | norm2(i,j)=norm2in(i,j) 70 | end do 71 | end do 72 | 73 | nfault=nf 74 | nc=nf 75 | do 380 imult=1,5 76 | if (nc.lt.1) goto 385 77 | 78 | c find the average mechanism by repeatedly throwing out the mechanism 79 | c with the largest angular difference from the average, and finding the average of 80 | c the remaining mechanisms - stop when all mechanisms are within cangle of average 81 | 82 | do 77 icount=1,nf 83 | call MECH_AVG(nc,norm1,norm2,norm1_avg,norm2_avg) 84 | do i=1,nc 85 | do j=1,3 86 | temp1(j)=norm1(j,i) 87 | temp2(j)=norm2(j,i) 88 | end do 89 | call MECH_ROT(norm1_avg,temp1,norm2_avg,temp2,rota(i)) 90 | end do 91 | maxrot=0. 92 | do i=1,nc 93 | if (abs(rota(i)).gt.maxrot) then 94 | maxrot=abs(rota(i)) 95 | imax=i 96 | end if 97 | end do 98 | if (maxrot.le.cangle) goto 78 99 | nc=nc-1 100 | do i=1,3 101 | temp1(i)=norm1(i,imax) 102 | temp2(i)=norm2(i,imax) 103 | end do 104 | do j=imax,nc 105 | do i=1,3 106 | norm1(i,j)=norm1(i,j+1) 107 | norm2(i,j)=norm2(i,j+1) 108 | end do 109 | end do 110 | do i=1,3 111 | norm1(i,nc+1)=temp1(i) 112 | norm2(i,nc+1)=temp2(i) 113 | end do 114 | 77 continue 115 | 116 | 78 continue 117 | a=nc 118 | b=nfault 119 | prob(imult)=a/b 120 | 121 | if ((imult.gt.1).and.(prob(imult).lt.prob_max)) goto 385 122 | 123 | do j=1,nf-nc ! set up for next round 124 | do i=1,3 125 | norm1(i,j)=norm1(i,j+nc) 126 | norm2(i,j)=norm2(i,j+nc) 127 | end do 128 | end do 129 | nc=nf-nc 130 | nf=nc 131 | 132 | c determine the RMS observed angular difference between the average 133 | c normal vectors and the normal vectors of each mechanism 134 | 135 | rms_diff(1,imult)=0. 136 | rms_diff(2,imult)=0. 137 | do 80 i=1,nfault 138 | do j=1,3 139 | temp1(j)=norm1in(j,i) 140 | temp2(j)=norm2in(j,i) 141 | end do 142 | call MECH_ROT(norm1_avg,temp1,norm2_avg,temp2,rota) 143 | d11=temp1(1)*norm1_avg(1)+temp1(2)*norm1_avg(2)+ 144 | & temp1(3)*norm1_avg(3) 145 | d22=temp2(1)*norm2_avg(1)+temp2(2)*norm2_avg(2)+ 146 | & temp2(3)*norm2_avg(3) 147 | if (d11.ge.1.) d11=1. 148 | if (d11.le.-1.) d11=-1. 149 | if (d22.ge.1.) d22=1. 150 | if (d22.le.-1.) d22=-1. 151 | a11=acos(d11) 152 | a22=acos(d22) 153 | rms_diff(1,imult)=rms_diff(1,imult)+a11*a11 154 | rms_diff(2,imult)=rms_diff(2,imult)+a22*a22 155 | 80 continue 156 | rms_diff(1,imult)=degrad*sqrt(rms_diff(1,imult)/nfault) 157 | rms_diff(2,imult)=degrad*sqrt(rms_diff(2,imult)/nfault) 158 | 159 | call fpcoor(str_avg(imult),dip_avg(imult),rak_avg(imult), 160 | & norm1_avg,norm2_avg,2) 161 | 162 | 380 continue 163 | 164 | 385 nsltn=imult-1 ! only use ones with certain probability 165 | 166 | return 167 | end 168 | 169 | c ------------------------------------------------------------ c 170 | 171 | c subroutine MECH_AVG determines the average focal mechanism of a set 172 | c of mechanisms 173 | c 174 | c Inputs: nf = number of fault planes 175 | c norm1(3,nf) = normal to fault plane 176 | c norm2(3,nf) = slip vector 177 | c Output: norm1_avg(3) = normal to avg plane 1 178 | c norm2_avg(3) = normal to avg plane 2 179 | c 180 | c Written 10/4/2000 by Jeanne Hardebeck 181 | c Modified 5/14/2001 by Jeanne Hardebeck 182 | c 183 | subroutine MECH_AVG(nf,norm1,norm2,norm1_avg,norm2_avg) 184 | 185 | real dot1,fract1 186 | real misf,maxmisf,avang1,avang2 187 | real norm1(3,nf),norm2(3,nf),temp1(3),temp2(3) 188 | real norm1_avg(3),norm2_avg(3),ln_norm1,ln_norm2 189 | real theta1,theta2,ref1(3),ref2(3) 190 | integer nf 191 | 192 | cf2py intent(in) nf 193 | cf2py intent(in) norm1 194 | cf2py intent(in) norm2 195 | cf2py intent(out) norm1_avg 196 | cf2py intent(out) norm2_avg 197 | 198 | pi=3.1415927 199 | degrad=180./3.1415927 200 | 201 | c if there is only one mechanism, return that mechanism 202 | 203 | if (nf.le.1) then 204 | do 5 i=1,3 205 | norm1_avg(i)=norm1(i,1) 206 | norm2_avg(i)=norm2(i,1) 207 | 5 continue 208 | goto 120 209 | end if 210 | 211 | c find the average normal vector for each plane - determine which 212 | c nodal plane of each event corresponds to which by finding the 213 | c minimum focal mechanism rotation 214 | 215 | do j=1,3 216 | norm1_avg(j)=norm1(j,1) 217 | norm2_avg(j)=norm2(j,1) 218 | ref1(j)=norm1(j,1) 219 | ref2(j)=norm2(j,1) 220 | end do 221 | do 50 i=2,nf 222 | do j=1,3 223 | temp1(j)=norm1(j,i) 224 | temp2(j)=norm2(j,i) 225 | end do 226 | call MECH_ROT(ref1,temp1,ref2,temp2,rota) 227 | do j=1,3 228 | norm1_avg(j)=norm1_avg(j)+temp1(j) 229 | norm2_avg(j)=norm2_avg(j)+temp2(j) 230 | end do 231 | 50 continue 232 | ln_norm1=0 233 | ln_norm2=0 234 | do 60 j=1,3 235 | ln_norm1=ln_norm1+norm1_avg(j)*norm1_avg(j) 236 | ln_norm2=ln_norm2+norm2_avg(j)*norm2_avg(j) 237 | 60 continue 238 | ln_norm1=sqrt(ln_norm1) 239 | ln_norm2=sqrt(ln_norm2) 240 | do 70 i=1,3 241 | norm1_avg(i)=norm1_avg(i)/ln_norm1 242 | norm2_avg(i)=norm2_avg(i)/ln_norm2 243 | 70 continue 244 | 245 | c determine the RMS observed angular difference between the average 246 | c normal vectors and the normal vectors of each mechanism 247 | 248 | avang1=0. 249 | avang2=0. 250 | do 80 i=1,nf 251 | do j=1,3 252 | temp1(j)=norm1(j,i) 253 | temp2(j)=norm2(j,i) 254 | end do 255 | call MECH_ROT(norm1_avg,temp1,norm2_avg,temp2,rota) 256 | d11=temp1(1)*norm1_avg(1)+temp1(2)*norm1_avg(2)+ 257 | & temp1(3)*norm1_avg(3) 258 | d22=temp2(1)*norm2_avg(1)+temp2(2)*norm2_avg(2)+ 259 | & temp2(3)*norm2_avg(3) 260 | if (d11.ge.1.) d11=1. 261 | if (d11.le.-1.) d11=-1. 262 | if (d22.ge.1.) d22=1. 263 | if (d22.le.-1.) d22=-1. 264 | a11=acos(d11) 265 | a22=acos(d22) 266 | avang1=avang1+a11*a11 267 | avang2=avang2+a22*a22 268 | 80 continue 269 | avang1=sqrt(avang1/nf) 270 | avang2=sqrt(avang2/nf) 271 | 272 | c the average normal vectors may not be exactly orthogonal (although 273 | c usually they are very close) - find the misfit from orthogonal and 274 | c adjust the vectors to make them orthogonal - adjust the more poorly 275 | c constrained plane more 276 | 277 | if ((avang1+avang2).lt.0.0001) goto 120 278 | 279 | maxmisf=0.01 280 | fract1=avang1/(avang1+avang2) 281 | 90 do 115 icount=1,100 282 | dot1=norm1_avg(1)*norm2_avg(1)+norm1_avg(2) 283 | & *norm2_avg(2)+norm1_avg(3)*norm2_avg(3) 284 | misf=90.-acos(dot1)*degrad 285 | if (abs(misf).le.maxmisf) goto 120 286 | theta1=misf*fract1/degrad 287 | theta2=misf*(1.-fract1)/degrad 288 | do j=1,3 289 | temp=norm1_avg(j) 290 | norm1_avg(j)=norm1_avg(j)-norm2_avg(j)*sin(theta1) 291 | norm2_avg(j)=norm2_avg(j)-temp*sin(theta2) 292 | end do 293 | ln_norm1=0 294 | ln_norm2=0 295 | do j=1,3 296 | ln_norm1=ln_norm1+norm1_avg(j)*norm1_avg(j) 297 | ln_norm2=ln_norm2+norm2_avg(j)*norm2_avg(j) 298 | end do 299 | ln_norm1=sqrt(ln_norm1) 300 | ln_norm2=sqrt(ln_norm2) 301 | do i=1,3 302 | norm1_avg(i)=norm1_avg(i)/ln_norm1 303 | norm2_avg(i)=norm2_avg(i)/ln_norm2 304 | end do 305 | 115 continue 306 | 307 | 120 continue 308 | return 309 | end 310 | 311 | 312 | c ------------------------------------------------------------ c 313 | 314 | 315 | c subroutine MECH_ROT finds the minimum rotation angle between two 316 | c mechanisms, given NORMAL and SLIP (doesn't work for P & T axes!) 317 | c 318 | c Inputs: norm1(3) = normal to fault plane 1 319 | c slip1(3) = slip vector 1 320 | c norm2(3) = normal to fault plane 2 321 | c slip2(3) = slip vector 2 322 | c Output: rota = rotation angle 323 | c 324 | c Edited 10/23/07 JLH - Does NOT assume that the normal and slip vectors 325 | c have been matched! 326 | c Tries 4 different combinations, then CHANGES norm2 & slip2 to the best combo 327 | c (1) norm1 & slip1 <=> norm2 & slip2 328 | c (2) norm1 & slip1 <=> -norm2 & -slip2 329 | c (3) norm1 & slip1 <=> slip2 & norm2 330 | c (4) norm1 & slip1 <=> -slip2 & -norm2 331 | c 332 | c 333 | subroutine MECH_ROT(norm1,norm2,slip1,slip2,rota) 334 | 335 | real norm1(3),norm2(3),slip1(3),slip2(3),B1(3),B2(3) 336 | real norm2_temp(3),slip2_temp(3),rotemp(4) 337 | real rota,phi(3),n(3,3),scale(3),R(3),qdot(3) 338 | real theta(3),n1(3),n2(3),phi1 339 | 340 | cf2py intent(in) norm1 341 | cf2py intent(in) slip1 342 | cf2py intent(in) norm2 343 | cf2py intent(in) slip2 344 | cf2py intent(out) rota 345 | 346 | pi=3.1415927 347 | degrad=180./3.1415927 348 | 349 | do 200 iter=1,4 ! iteration over the 4 possibilities 350 | 351 | if (iter.lt.3) then 352 | do i=1,3 353 | norm2_temp(i)=norm2(i) 354 | slip2_temp(i)=slip2(i) 355 | end do 356 | else 357 | do i=1,3 358 | norm2_temp(i)=slip2(i) 359 | slip2_temp(i)=norm2(i) 360 | end do 361 | end if 362 | if ((iter.eq.2).or.(iter.eq.4)) then 363 | do i=1,3 364 | norm2_temp(i)=-norm2_temp(i) 365 | slip2_temp(i)=-slip2_temp(i) 366 | end do 367 | end if 368 | 369 | call cross(norm1,slip1,B1) 370 | call cross(norm2_temp,slip2_temp,B2) 371 | 372 | phi1=norm1(1)*norm2_temp(1)+norm1(2)*norm2_temp(2)+ 373 | & norm1(3)*norm2_temp(3) 374 | phi(1)=acos(phi1) 375 | phi1=slip1(1)*slip2_temp(1)+slip1(2)*slip2_temp(2)+ 376 | & slip1(3)*slip2_temp(3) 377 | phi(2)=acos(phi1) 378 | phi1=B1(1)*B2(1)+B1(2)*B2(2)+B1(3)*B2(3) 379 | phi(3)=acos(phi1) 380 | 381 | c if the mechanisms are very close, rotation = 0 382 | if ((phi(1).lt.1e-4).and.(phi(2).lt.1e-4).and. 383 | & (phi(3).lt.1e-4)) then 384 | rotemp(iter)=0.0 385 | c if one vector is the same, it is the rotation axis 386 | else if (phi(1).lt.1e-4) then 387 | rotemp(iter)=degrad*phi(2) 388 | else if (phi(2).lt.1e-4) then 389 | rotemp(iter)=degrad*phi(3) 390 | else if (phi(3).lt.1e-4) then 391 | rotemp(iter)=degrad*phi(1) 392 | else 393 | c find difference vectors - the rotation axis must be orthogonal 394 | c to all three of these vectors 395 | do i=1,3 396 | n(i,1)=norm1(i)-norm2_temp(i) 397 | n(i,2)=slip1(i)-slip2_temp(i) 398 | n(i,3)=B1(i)-B2(i) 399 | end do 400 | do j=1,3 401 | scale(j)=sqrt(n(1,j)*n(1,j)+n(2,j)*n(2,j)+n(3,j)*n(3,j)) 402 | do i=1,3 403 | n(i,j)=n(i,j)/scale(j) 404 | end do 405 | end do 406 | qdot(3)=n(1,1)*n(1,2)+n(2,1)*n(2,2)+n(3,1)*n(3,2) 407 | qdot(2)=n(1,1)*n(1,3)+n(2,1)*n(2,3)+n(3,1)*n(3,3) 408 | qdot(1)=n(1,2)*n(1,3)+n(2,2)*n(2,3)+n(3,2)*n(3,3) 409 | c use the two largest difference vectors, as long as they aren't orthogonal 410 | iout=0 411 | do i=1,3 412 | if (qdot(i).gt.0.9999) iout=i 413 | end do 414 | if (iout.eq.0) then 415 | qmins=10000. 416 | do i=1,3 417 | if (scale(i).lt.qmins) then 418 | qmins=scale(i) 419 | iout=i 420 | end if 421 | end do 422 | end if 423 | k=1 424 | do j=1,3 425 | if (j.ne.iout) then 426 | if (k.eq.1) then 427 | do i=1,3 428 | n1(i)=n(i,j) 429 | end do 430 | k=2 431 | else 432 | do i=1,3 433 | n2(i)=n(i,j) 434 | end do 435 | end if 436 | end if 437 | end do 438 | c find rotation axis by taking cross product 439 | call CROSS(n1,n2,R) 440 | scaleR=sqrt(R(1)*R(1)+R(2)*R(2)+R(3)*R(3)) 441 | do i=1,3 442 | R(i)=R(i)/scaleR 443 | end do 444 | c find rotation using axis furthest from rotation axis 445 | theta(1)=acos(norm1(1)*R(1)+norm1(2)*R(2)+norm1(3)*R(3)) 446 | theta(2)=acos(slip1(1)*R(1)+slip1(2)*R(2)+slip1(3)*R(3)) 447 | theta(3)=acos(B1(1)*R(1)+B1(2)*R(2)+B1(3)*R(3)) 448 | qmindif=1000. 449 | do i=1,3 450 | if (abs(theta(i)-pi/2.0).lt.qmindif) then 451 | qmindif=abs(theta(i)-pi/2.0) 452 | iuse=i 453 | end if 454 | end do 455 | rotemp(iter)=(cos(phi(iuse))-cos(theta(iuse))* 456 | & cos(theta(iuse)))/(sin(theta(iuse))*sin(theta(iuse))) 457 | if (rotemp(iter).gt.1.0) then 458 | rotemp(iter)=1.0 459 | end if 460 | if (rotemp(iter).lt.-1.0) then 461 | rotemp(iter)=-1.0 462 | end if 463 | rotemp(iter)=degrad*acos(rotemp(iter)) 464 | end if 465 | 466 | 200 continue 467 | 468 | c find the minimum rotation for the 4 combos, and change norm2 and slip2 469 | rota=180.0 470 | do iter=1,4 471 | if (abs(rotemp(iter)).lt.rota) then 472 | rota=abs(rotemp(iter)) 473 | irot=iter 474 | end if 475 | end do 476 | if (irot.ge.3) then 477 | do i=1,3 478 | qtemp=slip2(i) 479 | slip2(i)=norm2(i) 480 | norm2(i)=qtemp 481 | end do 482 | end if 483 | if ((irot.eq.2).or.(irot.eq.4)) then 484 | do i=1,3 485 | norm2(i)=-norm2(i) 486 | slip2(i)=-slip2(i) 487 | end do 488 | end if 489 | 490 | return 491 | end 492 | 493 | -------------------------------------------------------------------------------- /hashpy/src/util_subs.f: -------------------------------------------------------------------------------- 1 | c 2 | c cross product of two vectors, sets v3 = v1 x v2 3 | c 4 | subroutine CROSS(v1,v2,v3) 5 | real v1(3),v2(3),v3(3) 6 | 7 | cf2py intent(in) v1 8 | cf2py intent(in) v2 9 | cf2py intent(out) v3 10 | 11 | v3(1)=v1(2)*v2(3)-v1(3)*v2(2) 12 | v3(2)=v1(3)*v2(1)-v1(1)*v2(3) 13 | v3(3)=v1(1)*v2(2)-v1(2)*v2(1) 14 | return 15 | end 16 | 17 | c ------------------------------------------------------------ c 18 | 19 | c 20 | c transforms spherical co-ordinates to cartesian 21 | c 22 | subroutine TO_CAR(the,phi,r,x,y,z) 23 | degrad=3.1415927/180. 24 | z=-r*cos(the*degrad) 25 | x=r*sin(the*degrad)*cos(phi*degrad) 26 | y=r*sin(the*degrad)*sin(phi*degrad) 27 | return 28 | end 29 | 30 | 31 | c ------------------------------------------------------------ c 32 | 33 | c subroutine FPCOOR gets fault normal vector,fnorm, and slip 34 | c vector, slip, from (strike,dip,rake) or vice versa. 35 | c idir = 1 compute fnorm,slip 36 | c idir = c compute strike,dip,rake 37 | c Reference: Aki and Richards, p. 115 38 | c uses (x,y,z) coordinate system with x=north, y=east, z=down 39 | subroutine FPCOOR(strike,dip,rake,fnorm,slip,idir) 40 | real fnorm(3),slip(3),phi,del,lam,a,clam,slam 41 | degrad=180./3.1415927 42 | pi=3.1415927 43 | phi=strike/degrad 44 | del=dip/degrad 45 | lam=rake/degrad 46 | if (idir.eq.1) then 47 | fnorm(1)=-sin(del)*sin(phi) 48 | fnorm(2)= sin(del)*cos(phi) 49 | fnorm(3)=-cos(del) 50 | slip(1)= cos(lam)*cos(phi)+cos(del)*sin(lam)*sin(phi) 51 | slip(2)= cos(lam)*sin(phi)-cos(del)*sin(lam)*cos(phi) 52 | slip(3)=-sin(lam)*sin(del) 53 | else 54 | if ((1.-abs(fnorm(3))).le.1e-7) then 55 | c print *,'***FPCOOR warning, horz fault, strike undefined' 56 | del=0. 57 | phi=atan2(-slip(1),slip(2)) 58 | clam=cos(phi)*slip(1)+sin(phi)*slip(2) 59 | slam=sin(phi)*slip(1)-cos(phi)*slip(2) 60 | lam=atan2(slam,clam) 61 | else 62 | phi=atan2(-fnorm(1),fnorm(2)) 63 | a=sqrt(fnorm(1)*fnorm(1)+fnorm(2)*fnorm(2)) 64 | del=atan2(a,-fnorm(3)) 65 | clam=cos(phi)*slip(1)+sin(phi)*slip(2) 66 | slam=-slip(3)/sin(del) 67 | lam=atan2(slam,clam) 68 | if (del.gt.(0.5*pi)) then 69 | del=pi-del 70 | phi=phi+pi 71 | lam=-lam 72 | end if 73 | end if 74 | strike=phi*degrad 75 | if (strike.lt.0.) strike=strike+360. 76 | dip=del*degrad 77 | rake=lam*degrad 78 | if (rake.le.-180.) rake=rake+360. 79 | if (rake.gt.180.) rake=rake-360. 80 | end if 81 | return 82 | end 83 | 84 | 85 | c ------------------------------------------------------------ c 86 | 87 | c normally-distributed random numbers, from numerical recipes 88 | subroutine RAN_NORM(fran) 89 | save jran,ifirst 90 | cf2py intent(out) fran 91 | im=120050 !overflow at 2**28 92 | ia=2311 93 | ic=25367 94 | if (ifirst.ne.12345) then 95 | jran=314159 96 | ifirst=12345 97 | end if 98 | fran=0 99 | do 10 i=1,12 100 | jran=mod(jran*ia+ic,im) 101 | fran=fran+(float(jran)/float(im)) 102 | 10 continue 103 | fran=fran-6. 104 | return 105 | end 106 | 107 | -------------------------------------------------------------------------------- /hashpy/src/vel.inc: -------------------------------------------------------------------------------- 1 | c nx0 = maximum source-station distance bins for look-up tables 2 | c nd0 = maximum source depth bins for look-up tables 3 | c nindex = maximum number of velocity model look-up tables 4 | c dep1,dep2,dep3 = minimum source depth, maximum, and interval 5 | c del1,del2,del3 = minimum source-station distance, maximum, and interval 6 | c pmin = minimum ray parameter for ray tracing 7 | c nump = number of rays traced 8 | parameter(nx0=101,nd0=14,nindex=10) 9 | parameter(dep1=0,dep2=39,dep3=3) 10 | parameter(del1=0,del2=200,del3=2) 11 | parameter(pmin=0,nump=9000) 12 | -------------------------------------------------------------------------------- /hashpy/src/vel_subs.f: -------------------------------------------------------------------------------- 1 | c MK_TABLES creates tables of takeoff angles given 1D velocity models. 2 | 3 | c output: 4 | c ntab - number of tables (max nindex) 5 | c 6 | c you are prompted for the names of the 1D velocity model files, 7 | c velocity file format (free format): 8 | c depth(km) P_velocity(km/s) 9 | 10 | subroutine MK_TABLE(ntab) 11 | 12 | include 'vel.inc' 13 | real table(nx0,nd0,nindex),delttab(nx0),deptab(nd0) 14 | integer ndel,ndep 15 | 16 | cf2py intent(in,out) ntab 17 | 18 | common /angtable/ table,delttab,deptab,ndel,ndep 19 | c common block: 20 | c table(nx0,nd0,nindex) = takeoff angle table 21 | c delttab(nx0) = list of ranges for tables 22 | c deptab(nd0) = list of source depths for tables 23 | c ndel = number of distance points in table 24 | c ndep = number of source depths in table 25 | 26 | parameter (nray0=10001) 27 | real z(1000),alpha(1000),slow(1000) 28 | character vmodel*100 29 | real deltab(nray0),tttab(nray0),ptab(nray0),tt(nray0,nd0) 30 | real depxcor(nray0,nd0),depucor(nray0,nd0),deptcor(nray0,nd0) 31 | real xsave(20000),tsave(20000),psave(20000),usave(20000) 32 | c 33 | degrad=180./3.14159265 34 | 35 | if (ntab.ne.1) then 36 | print *,'Enter number of velocity models (max ',nindex,')' 37 | read *,ntab 38 | end if 39 | 40 | do 300 itab=1,ntab 41 | 42 | print *,'Enter file name for velocity model ',itab 43 | read (*,'(a)') vmodel 44 | 45 | c set up table 46 | qtempdep2=dep2+dep3/20. 47 | ndep=int((qtempdep2-dep1)/dep3)+1 48 | do idep=1,ndep 49 | dep=dep1+dep3*real(idep-1) 50 | deptab(idep)=dep 51 | end do 52 | 53 | c read velocity model 54 | open (7,file=vmodel,status='old') 55 | do i=1,1000 56 | read (7,*,end=30) z(i),alpha(i) 57 | end do 58 | print *,'***1000 point maximum exceeded in model' 59 | 30 close (7) 60 | 38 z(i)=z(i-1) 61 | alpha(i)=alpha(i-1) 62 | npts=i 63 | npts_old=npts 64 | do i=npts_old,2,-1 65 | do idep=ndep,1,-1 66 | if ((z(i-1).le.(deptab(idep)-0.1)).and. 67 | & (z(i).ge.(deptab(idep)+0.1))) then 68 | npts=npts+1 69 | do j=npts,i+1,-1 70 | z(j)=z(j-1) 71 | alpha(j)=alpha(j-1) 72 | end do 73 | z(i)=deptab(idep) 74 | frac=(z(i)-z(i-1))/(z(i+1)-z(i-1)) 75 | alpha(i)=alpha(i-1)+frac*(alpha(i+1)-alpha(i-1)) 76 | end if 77 | end do 78 | end do 79 | do i=1,npts 80 | slow(i)=1./alpha(i) 81 | end do 82 | pmax=slow(1) 83 | plongcut=slow(npts) 84 | pstep=(pmax-pmin)/float(nump) 85 | 86 | 87 | c do P-wave ray tracing 88 | npmax=int((pmax+pstep/2.-pmin)/pstep)+1 89 | do 200 np=1,npmax 90 | p=pmin+pstep*real(np-1) 91 | ptab(np)=p 92 | x=0. 93 | t=0. 94 | imth=3 95 | do 70 idep=1,ndep 96 | if (deptab(idep).eq.0.) then 97 | depxcor(np,idep)=0. 98 | deptcor(np,idep)=0. 99 | depucor(np,idep)=slow(1) 100 | else 101 | depxcor(np,idep)=-999. 102 | deptcor(np,idep)=-999. 103 | depucor(np,idep)=-999. 104 | end if 105 | 70 continue 106 | do 100 i=1,npts-1 107 | if (z(i).ge.9999) then 108 | deltab(np)=-999. 109 | tttab(np)=-999. 110 | go to 200 111 | end if 112 | h=z(i+1)-z(i) 113 | if (h.eq.0.) go to 100 !skip if interface 114 | call LAYERTRACE(p,h,slow(i),slow(i+1),imth,dx,dt,irtr) 115 | x=x+dx 116 | t=t+dt 117 | if (irtr.eq.0.or.irtr.eq.2) go to 105 !ray has turned 118 | xdeg=x ! actually in km 119 | tmin=t ! actually in s 120 | do 80 idep=1,ndep 121 | if (abs(z(i+1)-deptab(idep)).lt.0.1) then 122 | depxcor(np,idep)=xdeg 123 | deptcor(np,idep)=tmin 124 | depucor(np,idep)=slow(i+1) 125 | end if 126 | 80 continue 127 | 100 continue 128 | 105 xdeg=2.*x ! actually in km 129 | tmin=2.*t ! actually in s 130 | 110 deltab(np)=xdeg 131 | tttab(np)=tmin 132 | 200 continue ! end loop on ray parameter p 133 | 134 | c create table 135 | do 250 idep=1,ndep 136 | icount=0 137 | xold=-999. 138 | if (deptab(idep).eq.0.) then 139 | i2=np 140 | go to 223 141 | end if 142 | do 220 i=1,np !upgoing rays from source 143 | x2=depxcor(i,idep) 144 | if (x2.eq.-999.) go to 221 145 | if (x2.le.xold) go to 221 !stop when heads inward 146 | t2=deptcor(i,idep) 147 | icount=icount+1 148 | xsave(icount)=x2 149 | tsave(icount)=t2 150 | psave(icount)=-ptab(i) 151 | usave(icount)=depucor(i,idep) 152 | xold=x2 153 | 220 continue 154 | 221 continue 155 | i2=i-1 156 | 223 do 225 i=i2,1,-1 !downgoing rays from source 157 | if (depxcor(i,idep).eq.-999.) go to 225 158 | if (deltab(i).eq.-999.) go to 225 159 | x2=deltab(i)-depxcor(i,idep) 160 | t2=tttab(i)-deptcor(i,idep) 161 | icount=icount+1 162 | xsave(icount)=x2 163 | tsave(icount)=t2 164 | psave(icount)=ptab(i) 165 | usave(icount)=depucor(i,idep) 166 | xold=x2 167 | 225 continue 168 | 226 ncount=icount 169 | 170 | ndel=int((del2-del1)/del3)+1 171 | do 240 idel=1,ndel 172 | del=del1+del3*real(idel-1) 173 | delttab(idel)=del 174 | tt(idel,idep)=999. 175 | do 230 i=2,ncount 176 | x1=xsave(i-1) 177 | x2=xsave(i) 178 | if (x1.gt.del.or.x2.lt.del) go to 230 179 | if (psave(i).gt.0..and.psave(i).lt.plongcut) go to 230 180 | frac=(del-x1)/(x2-x1) 181 | t1=tsave(i-1)+frac*(tsave(i)-tsave(i-1)) 182 | if (t1.lt.tt(idel,idep)) then 183 | tt(idel,idep)=t1 184 | scr1=psave(i)/usave(i) 185 | angle=asin(scr1)*degrad 186 | if (angle.lt.0.) then 187 | angle=-angle 188 | else 189 | angle=180.-angle 190 | end if 191 | table(idel,idep,itab)=angle 192 | end if 193 | 230 continue 194 | 240 continue 195 | 196 | 197 | 250 continue 198 | if (delttab(1).eq.0.) then 199 | do idep=1,ndep 200 | table(1,idep,itab)=0. !straight up at zero range 201 | end do 202 | end if 203 | 300 continue 204 | 205 | c do idel=1,ndel 206 | c do idep=1,ndep 207 | c print *,idel,delttab(idel),idep,deptab(idep), 208 | c & table(idel,idep,1) 209 | c end do 210 | c end do 211 | 212 | 999 return 213 | end 214 | 215 | 216 | c ------------------------------------------------------------ c 217 | 218 | 219 | c subroutine GET_TTS obtains the takeoff angle for a velocity model 220 | c at a specified range and earthquake depth by interpolating 221 | c from a table of takeoff angles. 222 | c Inputs: ip = index number for model (up to nindex) 223 | c del = range 224 | c qdep = earthquake depth 225 | c Returns: tt = takeoff angle (degrees) 226 | c iflag = -1 if outside depth range 227 | c = 0 for interpolation 228 | c = 1 for extrapolation in range 229 | c 230 | subroutine GET_TTS(ip,del,qdep,tt,iflag) 231 | 232 | include 'vel.inc' 233 | real t(nx0,nd0,nindex),x(nx0),d(nd0) 234 | integer nx,nd 235 | 236 | cf2py intent(in) ip 237 | cf2py intent(in) del 238 | cf2py intent(in) qdep 239 | cf2py intent(out) tt 240 | cf2py intent(out) iflag 241 | 242 | common /angtable/ t,x,d,nx,nd 243 | c common block: 244 | c t(nx0,nd0,nindex) = takeoff angle tables 245 | c x(nx0) = list of ranges for tables 246 | c d(nd0) = list of source depths for tables 247 | c nx = number of distance points in table 248 | c nd = number of source depths in table 249 | 250 | c 251 | c check if outside depth range 252 | if (qdep.lt.d(1).or.qdep.gt.d(nd0)) then 253 | iflag=-1 254 | tt=999 255 | print *,'*** event outside of velocity table depth range, 256 | & event depth=',qdep,' table range=',d(1),d(nd0) 257 | return 258 | end if 259 | c first check to see if interpolation alone will work 260 | do 30 id=2,nd 261 | if (d(id).lt.qdep) go to 30 262 | id1=id-1 263 | id2=id 264 | go to 32 265 | 30 continue 266 | id1=nd-1 267 | id2=nd 268 | 32 do 35 ix=2,nx 269 | if (x(ix).lt.del) go to 35 270 | ix1=ix-1 271 | ix2=ix 272 | go to 37 273 | 35 continue 274 | ix1=nx-1 275 | ix2=nx 276 | 37 if (t(ix1,id1,ip).eq.0.) go to 50 277 | if (t(ix1,id2,ip).eq.0.) go to 50 278 | if (t(ix2,id1,ip).eq.0.) go to 50 279 | if (t(ix2,id2,ip).eq.0.) go to 50 280 | if (x(ix2).lt.del) go to 50 281 | iflag=0 282 | xfrac=(del-x(ix1))/(x(ix2)-x(ix1)) 283 | t1=t(ix1,id1,ip)+xfrac*(t(ix2,id1,ip)-t(ix1,id1,ip)) 284 | t2=t(ix1,id2,ip)+xfrac*(t(ix2,id2,ip)-t(ix1,id2,ip)) 285 | dfrac=(qdep-d(id1))/(d(id2)-d(id1)) 286 | tt=t1+dfrac*(t2-t1) 287 | return 288 | c extrapolate to get tt 289 | 50 iflag=1 290 | xoffmin1=999. 291 | xoffmin2=999. 292 | ixbest1=999 293 | ixbest2=999 294 | do 60 ix=2,nx 295 | if (t(ix-1,id1,ip).eq.0) go to 55 296 | if (t(ix,id1,ip).eq.0) go to 55 297 | xoff=abs((x(ix-1)+x(ix))/2.-del) 298 | if (xoff.lt.xoffmin1) then 299 | xoffmin1=xoff 300 | ixbest1=ix 301 | end if 302 | 55 if (t(ix-1,id2,ip).eq.0) go to 60 303 | if (t(ix,id2,ip).eq.0) go to 60 304 | xoff=abs((x(ix-1)+x(ix))/2.-del) 305 | if (xoff.lt.xoffmin2) then 306 | xoffmin2=xoff 307 | ixbest2=ix 308 | end if 309 | 60 continue 310 | if (ixbest1.eq.999.or.ixbest2.eq.999) then 311 | iflag=-1 312 | tt=999 313 | return 314 | end if 315 | xfrac1=(del-x(ixbest1-1))/(x(ixbest1)-x(ixbest1-1)) 316 | t1=t(ixbest1-1,id1,ip) 317 | t2=t(ixbest1,id1,ip) 318 | tt1=t1+xfrac1*(t2-t1) 319 | xfrac2=(del-x(ixbest2-1))/(x(ixbest2)-x(ixbest2-1)) 320 | t1=t(ixbest2-1,id2,ip) 321 | t2=t(ixbest2,id2,ip) 322 | tt2=t1+xfrac2*(t2-t1) 323 | dfrac=(qdep-d(id1))/(d(id2)-d(id1)) 324 | tt=tt1+dfrac*(tt2-tt1) 325 | 999 return 326 | end 327 | 328 | 329 | c ------------------------------------------------------------ c 330 | 331 | c LAYERTRACE calculates the travel time and range offset 332 | c for ray tracing through a single layer. 333 | c 334 | c Input: p = horizontal slowness 335 | c h = layer thickness 336 | c utop = slowness at top of layer 337 | c ubot = slowness at bottom of layer 338 | c imth = interpolation method 339 | c imth = 1, v(z) = 1/sqrt(a - 2*b*z) 340 | c = 2, v(z) = a - b*z 341 | c = 3, v(z) = a*exp(-b*z) 342 | c 343 | c Returns: dx = range offset 344 | c dt = travel time 345 | c irtr = return code 346 | c = -1, zero thickness layer 347 | c = 0, ray turned above layer 348 | c = 1, ray passed through layer 349 | c = 2, ray turned within layer, 1 segment counted 350 | c 351 | c Note: This version does calculation in double precision, 352 | c but all i/o is still single precision 353 | c 354 | subroutine LAYERTRACE(p1,h1,utop1,ubot1,imth,dx1,dt1,irtr) 355 | implicit real*8 (a-h,o-z) 356 | real*4 p1,h1,utop1,ubot1,dx1,dt1 357 | p=dble(p1) 358 | h=dble(h1) 359 | utop=dble(utop1) 360 | ubot=dble(ubot1) 361 | c 362 | if (h.eq.0.) then !check for zero thickness layer 363 | dx1=0. 364 | dt1=0. 365 | irtr=-1 366 | return 367 | end if 368 | c 369 | u=utop 370 | y=u-p 371 | if (y.le.0.) then !complex vertical slowness 372 | dx1=0. 373 | dt1=0. 374 | irtr=0 375 | return 376 | end if 377 | c 378 | q=y*(u+p) 379 | qs=dsqrt(q) 380 | c 381 | c special function needed for integral at top of layer 382 | if (imth.eq.2) then 383 | y=u+qs 384 | if (p.ne.0.) y=y/p 385 | qr=dlog(y) 386 | else if (imth.eq.3) then 387 | qr=atan2(qs,p) 388 | end if 389 | c 390 | if (imth.eq.1) then 391 | b=-(utop**2-ubot**2)/(2.*h) 392 | else if (imth.eq.2) then 393 | vtop=1./utop 394 | vbot=1./ubot 395 | b=-(vtop-vbot)/h 396 | else 397 | b=-dlog(ubot/utop)/h 398 | end if 399 | c 400 | if (b.eq.0.) then !constant velocity layer 401 | b=1./h 402 | etau=qs 403 | ex=p/qs 404 | irtr=1 405 | go to 160 406 | end if 407 | c 408 | c integral at upper limit, 1/b factor omitted until end 409 | if (imth.eq.1) then 410 | etau=-q*qs/3. 411 | ex=-qs*p 412 | else if (imth.eq.2) then 413 | ex=qs/u !*** - in some versions (wrongly) 414 | etau=qr-ex 415 | if (p.ne.0.) ex=ex/p 416 | else 417 | etau=qs-p*qr 418 | ex=qr 419 | end if 420 | c 421 | c check lower limit to see if we have turning point 422 | u=ubot 423 | if (u.le.p) then !if turning point, 424 | irtr=2 !then no contribution 425 | go to 160 !from bottom point 426 | end if 427 | irtr=1 428 | q=(u-p)*(u+p) 429 | qs=dsqrt(q) 430 | c 431 | if (imth.eq.1) then 432 | etau=etau+q*qs/3. 433 | ex=ex+qs*p 434 | else if (imth.eq.2) then 435 | y=u+qs 436 | z=qs/u 437 | etau=etau+z 438 | if (p.ne.0.) then 439 | y=y/p 440 | z=z/p 441 | end if 442 | qr=dlog(y) 443 | etau=etau-qr 444 | ex=ex-z 445 | else 446 | qr=atan2(qs,p) 447 | etau=etau-qs+p*qr 448 | ex=ex-qr 449 | end if 450 | c 451 | 160 dx=ex/b 452 | dtau=etau/b 453 | dt=dtau+p*dx !convert tau to t 454 | c 455 | dx1=sngl(dx) 456 | dt1=sngl(dt) 457 | return 458 | end 459 | -------------------------------------------------------------------------------- /hashpy/src/vel_subs2.f: -------------------------------------------------------------------------------- 1 | c MK_TABLES creates tables of takeoff angles given 1D velocity models. 2 | c 3 | c input: 4 | c ind - index of the table to add 5 | c vmodel - filename of the velocity model file 6 | c output: 7 | c ntab - number of tables (max nindex) 8 | c 9 | c add a velocity model to the table, 10 | c velocity file format (free format): 11 | c depth(km) P_velocity(km/s) 12 | 13 | subroutine MK_TABLE_ADD(ind,ntab,vmodel) 14 | 15 | include 'vel.inc' 16 | real table(nx0,nd0,nindex),delttab(nx0),deptab(nd0) 17 | integer ndel,ndep 18 | 19 | cf2py intent(in) ind 20 | cf2py intent(in) vmodel 21 | cf2py intent(out) ntab 22 | 23 | common /angtable/ table,delttab,deptab,ndel,ndep 24 | c common block: 25 | c table(nx0,nd0,nindex) = takeoff angle table 26 | c delttab(nx0) = list of ranges for tables 27 | c deptab(nd0) = list of source depths for tables 28 | c ndel = number of distance points in table 29 | c ndep = number of source depths in table 30 | 31 | parameter (nray0=10001) 32 | real z(1000),alpha(1000),slow(1000) 33 | character vmodel*100 34 | real deltab(nray0),tttab(nray0),ptab(nray0),tt(nray0,nd0) 35 | real depxcor(nray0,nd0),depucor(nray0,nd0),deptcor(nray0,nd0) 36 | real xsave(20000),tsave(20000),psave(20000),usave(20000) 37 | c 38 | degrad=180./3.14159265 39 | 40 | c if (ntab.ne.1) then 41 | c print *,'Enter number of velocity models (max ',nindex,')' 42 | c read *,ntab 43 | c end if 44 | ntab=ind 45 | 46 | do 300 itab=ind,ntab 47 | 48 | c print *,'Enter file name for velocity model ',itab 49 | c read (*,'(a)') vmodel 50 | 51 | c set up table 52 | qtempdep2=dep2+dep3/20. 53 | ndep=int((qtempdep2-dep1)/dep3)+1 54 | do idep=1,ndep 55 | dep=dep1+dep3*real(idep-1) 56 | deptab(idep)=dep 57 | end do 58 | 59 | c read velocity model 60 | open (7,file=vmodel,status='old') 61 | do i=1,1000 62 | read (7,*,end=30) z(i),alpha(i) 63 | end do 64 | print *,'***1000 point maximum exceeded in model' 65 | 30 close (7) 66 | 38 z(i)=z(i-1) 67 | alpha(i)=alpha(i-1) 68 | npts=i 69 | npts_old=npts 70 | do i=npts_old,2,-1 71 | do idep=ndep,1,-1 72 | if ((z(i-1).le.(deptab(idep)-0.1)).and. 73 | & (z(i).ge.(deptab(idep)+0.1))) then 74 | npts=npts+1 75 | do j=npts,i+1,-1 76 | z(j)=z(j-1) 77 | alpha(j)=alpha(j-1) 78 | end do 79 | z(i)=deptab(idep) 80 | frac=(z(i)-z(i-1))/(z(i+1)-z(i-1)) 81 | alpha(i)=alpha(i-1)+frac*(alpha(i+1)-alpha(i-1)) 82 | end if 83 | end do 84 | end do 85 | do i=1,npts 86 | slow(i)=1./alpha(i) 87 | end do 88 | pmax=slow(1) 89 | plongcut=slow(npts) 90 | pstep=(pmax-pmin)/float(nump) 91 | 92 | 93 | c do P-wave ray tracing 94 | npmax=int((pmax+pstep/2.-pmin)/pstep)+1 95 | do 200 np=1,npmax 96 | p=pmin+pstep*real(np-1) 97 | ptab(np)=p 98 | x=0. 99 | t=0. 100 | imth=3 101 | do 70 idep=1,ndep 102 | if (deptab(idep).eq.0.) then 103 | depxcor(np,idep)=0. 104 | deptcor(np,idep)=0. 105 | depucor(np,idep)=slow(1) 106 | else 107 | depxcor(np,idep)=-999. 108 | deptcor(np,idep)=-999. 109 | depucor(np,idep)=-999. 110 | end if 111 | 70 continue 112 | do 100 i=1,npts-1 113 | if (z(i).ge.9999) then 114 | deltab(np)=-999. 115 | tttab(np)=-999. 116 | go to 200 117 | end if 118 | h=z(i+1)-z(i) 119 | if (h.eq.0.) go to 100 !skip if interface 120 | call LAYERTRACE(p,h,slow(i),slow(i+1),imth,dx,dt,irtr) 121 | x=x+dx 122 | t=t+dt 123 | if (irtr.eq.0.or.irtr.eq.2) go to 105 !ray has turned 124 | xdeg=x ! actually in km 125 | tmin=t ! actually in s 126 | do 80 idep=1,ndep 127 | if (abs(z(i+1)-deptab(idep)).lt.0.1) then 128 | depxcor(np,idep)=xdeg 129 | deptcor(np,idep)=tmin 130 | depucor(np,idep)=slow(i+1) 131 | end if 132 | 80 continue 133 | 100 continue 134 | 105 xdeg=2.*x ! actually in km 135 | tmin=2.*t ! actually in s 136 | 110 deltab(np)=xdeg 137 | tttab(np)=tmin 138 | 200 continue ! end loop on ray parameter p 139 | 140 | c create table 141 | do 250 idep=1,ndep 142 | icount=0 143 | xold=-999. 144 | if (deptab(idep).eq.0.) then 145 | i2=np 146 | go to 223 147 | end if 148 | do 220 i=1,np !upgoing rays from source 149 | x2=depxcor(i,idep) 150 | if (x2.eq.-999.) go to 221 151 | if (x2.le.xold) go to 221 !stop when heads inward 152 | t2=deptcor(i,idep) 153 | icount=icount+1 154 | xsave(icount)=x2 155 | tsave(icount)=t2 156 | psave(icount)=-ptab(i) 157 | usave(icount)=depucor(i,idep) 158 | xold=x2 159 | 220 continue 160 | 221 continue 161 | i2=i-1 162 | 223 do 225 i=i2,1,-1 !downgoing rays from source 163 | if (depxcor(i,idep).eq.-999.) go to 225 164 | if (deltab(i).eq.-999.) go to 225 165 | x2=deltab(i)-depxcor(i,idep) 166 | t2=tttab(i)-deptcor(i,idep) 167 | icount=icount+1 168 | xsave(icount)=x2 169 | tsave(icount)=t2 170 | psave(icount)=ptab(i) 171 | usave(icount)=depucor(i,idep) 172 | xold=x2 173 | 225 continue 174 | 226 ncount=icount 175 | 176 | ndel=int((del2-del1)/del3)+1 177 | do 240 idel=1,ndel 178 | del=del1+del3*real(idel-1) 179 | delttab(idel)=del 180 | tt(idel,idep)=999. 181 | do 230 i=2,ncount 182 | x1=xsave(i-1) 183 | x2=xsave(i) 184 | if (x1.gt.del.or.x2.lt.del) go to 230 185 | if (psave(i).gt.0..and.psave(i).lt.plongcut) go to 230 186 | frac=(del-x1)/(x2-x1) 187 | t1=tsave(i-1)+frac*(tsave(i)-tsave(i-1)) 188 | if (t1.lt.tt(idel,idep)) then 189 | tt(idel,idep)=t1 190 | scr1=psave(i)/usave(i) 191 | angle=asin(scr1)*degrad 192 | if (angle.lt.0.) then 193 | angle=-angle 194 | else 195 | angle=180.-angle 196 | end if 197 | table(idel,idep,itab)=angle 198 | end if 199 | 230 continue 200 | 240 continue 201 | 202 | 203 | 250 continue 204 | if (delttab(1).eq.0.) then 205 | do idep=1,ndep 206 | table(1,idep,itab)=0. !straight up at zero range 207 | end do 208 | end if 209 | 300 continue 210 | 211 | c do idel=1,ndel 212 | c do idep=1,ndep 213 | c print *,idel,delttab(idel),idep,deptab(idep), 214 | c & table(idel,idep,1) 215 | c end do 216 | c end do 217 | 218 | 999 return 219 | end 220 | 221 | 222 | c ------------------------------------------------------------ c 223 | -------------------------------------------------------------------------------- /hashpy/tests/data/example1.inp: -------------------------------------------------------------------------------- 1 | scsn.reverse 2 | north1.phase 3 | test1.out 4 | test1.out2 5 | 8 6 | 90 7 | 60 8 | 5 9 | 30 10 | 300 11 | 0.1 12 | 120 13 | 45 14 | 0.25 15 | -------------------------------------------------------------------------------- /hashpy/tests/data/example1.out: -------------------------------------------------------------------------------- 1 | 3143312 1994 1 21 11 4 15.500 L 2.300 X 34.24250 -118.61767 18.130 X -9.000 0.070 0.100 -9.000 -18 -9 -9 254 60 46 26 23 30 9 B 79 66 2 | 3145744 1994 1 25 10 5 22.020 L 2.400 X 34.24117 -118.62117 18.540 X -9.000 0.030 0.090 -9.000 -18 -9 -9 155 62 140 29 37 33 12 C 54 64 * 3 | 3145744 1994 1 25 10 5 22.020 L 2.400 X 34.24117 -118.62117 18.540 X -9.000 0.030 0.090 -9.000 -18 -9 -9 123 55 72 35 44 33 16 D 26 64 * 4 | 3146815 1994 1 28 7 44 46.320 L 3.400 X 34.23917 -118.62150 18.960 X -9.000 0.090 0.180 -9.000 -18 -9 -9 138 46 131 18 20 73 13 A 98 51 5 | 3146907 1994 1 28 15 47 20.680 L 2.000 X 34.23817 -118.61050 17.790 X -9.000 0.060 0.090 -9.000 -18 -9 -9 105 53 83 35 34 23 7 B 63 62 6 | 3147167 1994 1 29 7 52 21.520 L 2.600 X 34.23833 -118.62466 19.200 X -9.000 0.090 0.120 -9.000 -18 -9 -9 140 55 107 20 27 55 10 A 88 57 7 | 3148047 1994 1 31 7 13 16.730 L 2.200 X 34.24183 -118.61550 17.920 X -9.000 0.050 0.100 -9.000 -18 -9 -9 142 51 110 25 27 39 6 B 81 61 8 | 3149674 1994 2 5 7 11 45.110 L 2.400 X 34.24017 -118.61667 18.200 X -9.000 0.040 0.060 -9.000 -18 -9 -9 129 48 110 27 32 50 16 B 80 59 9 | 3150936 1994 2 10 4 19 26.080 L 2.500 X 34.24217 -118.62016 18.310 X -9.000 0.050 0.060 -9.000 -18 -9 -9 142 57 131 22 26 57 5 B 85 49 10 | 3150947 1994 2 10 4 46 40.730 L 2.300 X 34.24117 -118.62016 18.450 X -9.000 0.050 0.100 -9.000 -18 -9 -9 144 56 132 23 26 50 8 A 91 54 11 | 3151649 1994 2 13 9 4 56.640 L 2.100 X 34.23783 -118.61283 17.740 X -9.000 0.030 0.030 -9.000 -18 -9 -9 132 48 114 23 28 33 5 B 85 55 12 | 3152142 1994 2 14 13 19 47.650 L 2.300 X 34.24166 -118.61716 17.960 X -9.000 0.070 0.130 -9.000 -18 -9 -9 133 48 113 20 22 48 4 A 97 52 13 | 2148509 1994 2 15 1 59 47.430 L 2.500 X 34.24166 -118.61900 18.190 X -9.000 0.010 0.060 -9.000 -18 -9 -9 123 49 102 20 23 60 16 B 97 52 14 | 3152388 1994 2 15 4 10 52.050 L 2.000 X 34.23983 -118.62133 18.390 X -9.000 0.070 0.060 -9.000 -18 -9 -9 147 50 131 25 28 34 8 B 84 57 15 | 3152559 1994 2 15 21 13 54.090 L 2.300 X 34.23967 -118.61584 17.910 X -9.000 0.030 0.130 -9.000 -18 -9 -9 144 49 120 19 22 42 8 A 98 53 16 | 3153955 1994 2 20 19 35 21.170 L 1.900 X 34.23783 -118.61183 17.830 X -9.000 0.060 0.070 -9.000 -18 -9 -9 312 35 119 30 28 32 7 B 78 61 17 | 3158361 1994 3 14 10 2 19.320 L 2.200 X 34.23933 -118.61833 18.350 X -9.000 0.060 0.030 -9.000 -18 -9 -9 136 49 116 21 23 46 11 A 96 51 18 | 3159027 1994 3 18 8 27 27.080 L 2.200 X 34.24050 -118.61767 18.280 X -9.000 0.030 0.040 -9.000 -18 -9 -9 276 38 69 34 31 39 6 B 66 55 19 | 3159267 1994 3 20 0 11 12.920 L 2.500 X 34.24117 -118.61584 18.000 X -9.000 0.050 0.070 -9.000 -18 -9 -9 134 58 114 24 28 44 5 B 88 54 20 | 2155068 1994 3 22 13 7 33.690 L 2.300 X 34.23933 -118.61567 18.170 X -9.000 0.040 0.040 -9.000 -18 -9 -9 150 53 130 22 23 34 0 A 97 53 21 | 3160206 1994 3 24 11 23 51.600 L 1.700 X 34.24017 -118.61833 18.040 X -9.000 0.050 0.050 -9.000 -18 -9 -9 144 51 123 26 31 31 3 B 78 56 22 | 3177685 1994 7 26 2 58 20.640 L 2.600 X 34.23900 -118.61150 17.780 X -9.000 0.050 0.140 -9.000 -18 -9 -9 124 46 123 26 31 51 9 B 78 54 23 | 3148018 1994 1 31 4 53 39.250 L 2.100 X 34.23817 -118.61066 17.440 X -9.000 0.090 0.130 -9.000 -18 -9 -9 293 45 62 24 15 46 18 B 98 53 24 | 3150301 1994 2 7 5 23 49.910 L 1.800 X 34.23734 -118.61300 17.700 X -9.000 0.060 0.110 -9.000 -18 -9 -9 299 48 101 28 22 32 17 B 83 65 25 | 3150490 1994 2 8 2 7 8.790 L 2.600 X 34.23817 -118.60633 17.750 X -9.000 0.070 0.160 -9.000 -18 -9 -9 308 40 109 23 19 57 15 B 93 56 26 | -------------------------------------------------------------------------------- /hashpy/tests/data/example2.inp: -------------------------------------------------------------------------------- 1 | scsn.stations 2 | scsn.reverse 3 | north2.phase 4 | test2.out 5 | test2.out2 6 | 8 7 | 90 8 | 60 9 | 5 10 | 30 11 | 500 12 | 0.1 13 | 120 14 | 45 15 | 0.25 16 | 5 17 | vz.socal 18 | vz.north 19 | vz.lab1 20 | vz.sgm1 21 | vz.vb1 22 | 23 | -------------------------------------------------------------------------------- /hashpy/tests/data/example2.out: -------------------------------------------------------------------------------- 1 | 3143312 1994 1 21 11 4 15.500 L 2.300 X 34.24250 -118.61767 18.130 X -9.000 0.070 0.100 -9.000 -18 -9 -9 137 49 141 14 19 30 7 A 100 67 2 | 3145744 1994 1 25 10 5 22.020 L 2.400 X 34.24117 -118.62117 18.540 X -9.000 0.030 0.090 -9.000 -18 -9 -9 286 43 61 31 22 33 14 B 84 64 3 | 3146815 1994 1 28 7 44 46.320 L 3.400 X 34.23917 -118.62150 18.960 X -9.000 0.090 0.180 -9.000 -18 -9 -9 138 41 131 15 13 73 9 A 100 52 4 | 3146907 1994 1 28 15 47 20.680 L 2.000 X 34.23817 -118.61050 17.790 X -9.000 0.060 0.090 -9.000 -18 -9 -9 305 42 101 25 25 23 12 A 88 62 5 | 3147167 1994 1 29 7 52 21.510 L 2.600 X 34.23833 -118.62466 19.200 X -9.000 0.090 0.120 -9.000 -18 -9 -9 144 51 111 18 23 55 13 A 97 58 6 | 3148047 1994 1 31 7 13 16.730 L 2.200 X 34.24183 -118.61550 17.920 X -9.000 0.050 0.100 -9.000 -18 -9 -9 291 46 65 23 23 39 10 A 93 61 7 | 3149674 1994 2 5 7 11 45.110 L 2.400 X 34.24017 -118.61667 18.200 X -9.000 0.040 0.060 -9.000 -18 -9 -9 132 44 109 21 25 50 15 A 93 60 8 | 3150936 1994 2 10 4 19 26.080 L 2.500 X 34.24217 -118.62016 18.310 X -9.000 0.050 0.060 -9.000 -18 -9 -9 144 53 133 14 17 57 11 B 99 50 9 | 3150947 1994 2 10 4 46 40.730 L 2.300 X 34.24117 -118.62016 18.450 X -9.000 0.050 0.100 -9.000 -18 -9 -9 143 46 130 15 13 50 12 A 100 55 10 | 3151649 1994 2 13 9 4 56.640 L 2.100 X 34.23783 -118.61283 17.740 X -9.000 0.030 0.030 -9.000 -18 -9 -9 129 43 112 19 20 33 5 A 100 55 11 | 3152142 1994 2 14 13 19 47.650 L 2.300 X 34.24166 -118.61716 17.960 X -9.000 0.070 0.130 -9.000 -18 -9 -9 133 43 117 18 19 48 6 A 99 52 12 | 2148509 1994 2 15 1 59 47.430 L 2.500 X 34.24166 -118.61900 18.190 X -9.000 0.010 0.060 -9.000 -18 -9 -9 122 45 100 15 17 60 21 C 100 52 13 | 3152388 1994 2 15 4 10 52.050 L 2.000 X 34.23983 -118.62133 18.390 X -9.000 0.070 0.060 -9.000 -18 -9 -9 144 44 125 25 26 34 8 B 84 57 14 | 3152559 1994 2 15 21 13 54.090 L 2.300 X 34.23967 -118.61584 17.910 X -9.000 0.030 0.130 -9.000 -18 -9 -9 143 42 118 19 21 42 11 A 97 54 15 | 3153955 1994 2 20 19 35 21.170 L 1.900 X 34.23783 -118.61183 17.830 X -9.000 0.060 0.070 -9.000 -18 -9 -9 102 56 68 19 20 32 11 A 98 61 16 | 3158361 1994 3 14 10 2 19.320 L 2.200 X 34.23933 -118.61833 18.350 X -9.000 0.060 0.030 -9.000 -18 -9 -9 135 46 115 19 21 46 11 A 98 52 17 | 3159027 1994 3 18 8 27 27.080 L 2.200 X 34.24050 -118.61767 18.280 X -9.000 0.030 0.040 -9.000 -18 -9 -9 123 49 99 22 26 39 6 A 90 55 18 | 3159267 1994 3 20 0 11 12.920 L 2.500 X 34.24117 -118.61584 18.000 X -9.000 0.050 0.070 -9.000 -18 -9 -9 135 53 113 18 20 44 1 A 98 55 19 | 2155068 1994 3 22 13 7 33.690 L 2.300 X 34.23933 -118.61567 18.170 X -9.000 0.040 0.040 -9.000 -18 -9 -9 151 48 134 21 19 34 0 A 100 54 20 | 3160206 1994 3 24 11 23 51.600 L 1.700 X 34.24017 -118.61833 18.040 X -9.000 0.050 0.050 -9.000 -18 -9 -9 146 45 128 21 19 31 7 A 97 56 21 | 3177685 1994 7 26 2 58 20.640 L 2.600 X 34.23900 -118.61150 17.780 X -9.000 0.050 0.140 -9.000 -18 -9 -9 131 43 117 20 26 51 8 A 93 54 22 | 3148018 1994 1 31 4 53 39.250 L 2.100 X 34.23817 -118.61066 17.440 X -9.000 0.090 0.130 -9.000 -18 -9 -9 295 51 63 23 18 46 14 A 96 53 23 | 3150301 1994 2 7 5 23 49.910 L 1.800 X 34.23734 -118.61300 17.700 X -9.000 0.060 0.110 -9.000 -18 -9 -9 108 43 89 24 29 32 16 B 79 64 24 | 3150490 1994 2 8 2 7 8.790 L 2.600 X 34.23817 -118.60633 17.750 X -9.000 0.070 0.160 -9.000 -18 -9 -9 105 48 77 24 24 57 12 A 90 57 25 | -------------------------------------------------------------------------------- /hashpy/tests/data/example3.inp: -------------------------------------------------------------------------------- 1 | scsn.stations 2 | scsn.reverse 3 | north3.statcor 4 | north3.amp 5 | north2.phase 6 | test3.out 7 | 8 8 | 5 9 | 30 10 | 300 11 | 3.0 12 | 0.1 13 | 0.3 14 | 120 15 | 45 16 | 0.25 17 | 5 18 | vz.socal 19 | vz.north 20 | vz.lab1 21 | vz.sgm1 22 | vz.vb1 23 | 24 | -------------------------------------------------------------------------------- /hashpy/tests/data/example3.out: -------------------------------------------------------------------------------- 1 | 3143312 1994 1 21 11 4 15.500 L 2.300 X 34.24250 -118.61767 18.130 X -9.000 0.070 0.100 -9.000 -18 -9 -9 134 46 141 13 16 27 9 A 100 69 7 64 2 | 3145744 1994 1 25 10 5 22.020 L 2.400 X 34.24117 -118.62117 18.540 X -9.000 0.030 0.090 -9.000 -18 -9 -9 286 43 59 30 21 26 15 B 85 69 10 58 3 | 3146815 1994 1 28 7 44 46.320 L 3.400 X 34.23917 -118.62150 18.960 X -9.000 0.090 0.180 -9.000 -18 -9 -9 140 43 132 13 12 82 8 A 100 59 11 55 4 | 3146907 1994 1 28 15 47 20.680 L 2.000 X 34.23817 -118.61050 17.790 X -9.000 0.060 0.090 -9.000 -18 -9 -9 110 50 80 24 23 23 12 A 90 64 2 73 5 | 3147167 1994 1 29 7 52 21.510 L 2.600 X 34.23833 -118.62466 19.200 X -9.000 0.090 0.120 -9.000 -18 -9 -9 291 41 66 19 15 45 11 A 100 61 17 74 6 | 3148047 1994 1 31 7 13 16.730 L 2.200 X 34.24183 -118.61550 17.920 X -9.000 0.050 0.100 -9.000 -18 -9 -9 151 52 122 19 19 28 5 A 99 62 11 78 7 | 3149674 1994 2 5 7 11 45.110 L 2.400 X 34.24017 -118.61667 18.200 X -9.000 0.040 0.060 -9.000 -18 -9 -9 138 45 113 17 20 46 15 A 88 59 12 67 8 | 3150936 1994 2 10 4 19 26.080 L 2.500 X 34.24217 -118.62016 18.310 X -9.000 0.050 0.060 -9.000 -18 -9 -9 144 54 132 13 14 56 11 A 100 53 12 38 9 | 3150947 1994 2 10 4 46 40.730 L 2.300 X 34.24117 -118.62016 18.450 X -9.000 0.050 0.100 -9.000 -18 -9 -9 142 45 130 15 13 51 15 A 100 56 9 48 10 | 3151649 1994 2 13 9 4 56.640 L 2.100 X 34.23783 -118.61283 17.740 X -9.000 0.030 0.030 -9.000 -18 -9 -9 128 43 110 19 19 33 5 A 100 56 6 61 11 | 3152142 1994 2 14 13 19 47.650 L 2.300 X 34.24166 -118.61716 17.960 X -9.000 0.070 0.130 -9.000 -18 -9 -9 131 41 116 17 16 48 6 A 100 55 10 67 12 | 2148509 1994 2 15 1 59 47.430 L 2.500 X 34.24166 -118.61900 18.190 X -9.000 0.010 0.060 -9.000 -18 -9 -9 121 43 99 16 17 61 23 A 100 55 12 62 13 | 3152388 1994 2 15 4 10 52.050 L 2.000 X 34.23983 -118.62133 18.390 X -9.000 0.070 0.060 -9.000 -18 -9 -9 141 47 115 24 26 36 16 B 86 62 8 67 14 | 3152559 1994 2 15 21 13 54.090 L 2.300 X 34.23967 -118.61584 17.910 X -9.000 0.030 0.130 -9.000 -18 -9 -9 140 39 120 17 18 44 14 A 100 56 6 67 15 | 3153955 1994 2 20 19 35 21.170 L 1.900 X 34.23783 -118.61183 17.830 X -9.000 0.060 0.070 -9.000 -18 -9 -9 318 40 119 21 18 32 11 A 98 62 5 72 16 | 3158361 1994 3 14 10 2 19.320 L 2.200 X 34.23933 -118.61833 18.350 X -9.000 0.060 0.030 -9.000 -18 -9 -9 137 45 117 18 20 47 9 A 97 55 3 90 17 | 3159027 1994 3 18 8 27 27.080 L 2.200 X 34.24050 -118.61767 18.280 X -9.000 0.030 0.040 -9.000 -18 -9 -9 118 50 99 26 29 25 7 B 84 59 1 34 18 | 3159267 1994 3 20 0 11 12.920 L 2.500 X 34.24117 -118.61584 18.000 X -9.000 0.050 0.070 -9.000 -18 -9 -9 281 41 66 18 18 32 5 A 100 61 4 98 19 | 2155068 1994 3 22 13 7 33.690 L 2.300 X 34.23933 -118.61567 18.170 X -9.000 0.040 0.040 -9.000 -18 -9 -9 152 49 133 21 18 34 0 A 100 56 2 109 20 | 3160206 1994 3 24 11 23 51.600 L 1.700 X 34.24017 -118.61833 18.040 X -9.000 0.050 0.050 -9.000 -18 -9 -9 147 46 130 20 18 31 7 A 98 57 1 62 21 | 3177685 1994 7 26 2 58 20.640 L 2.600 X 34.23900 -118.61150 17.780 X -9.000 0.050 0.140 -9.000 -18 -9 -9 131 43 116 17 18 37 6 A 99 61 3 94 22 | 3148018 1994 1 31 4 53 39.250 L 2.100 X 34.23817 -118.61066 17.440 X -9.000 0.090 0.130 -9.000 -18 -9 -9 154 45 121 18 22 47 14 A 95 55 12 57 23 | 3150301 1994 2 7 5 23 49.910 L 1.800 X 34.23734 -118.61300 17.700 X -9.000 0.060 0.110 -9.000 -18 -9 -9 290 48 89 30 24 25 18 B 78 66 9 61 24 | 3150490 1994 2 8 2 7 8.790 L 2.600 X 34.23817 -118.60633 17.750 X -9.000 0.070 0.160 -9.000 -18 -9 -9 307 45 110 21 21 44 11 A 92 61 16 68 25 | -------------------------------------------------------------------------------- /hashpy/tests/data/example4.inp: -------------------------------------------------------------------------------- 1 | scsn.stations_5char 2 | scsn.reverse 3 | north4.phase 4 | test4.out 5 | test4.out2 6 | 8 7 | 90 8 | 60 9 | 5 10 | 30 11 | 500 12 | 0.1 13 | 120 14 | 45 15 | 0.25 16 | 5 17 | vz.socal 18 | vz.north 19 | vz.lab1 20 | vz.sgm1 21 | vz.vb1 22 | 23 | -------------------------------------------------------------------------------- /hashpy/tests/data/example4.out: -------------------------------------------------------------------------------- 1 | 3143312 1994 1 21 11 4 15.470 L 2.300 X 34.24100 -118.60100 21.320 X -9.000 0.000 1.000 -9.000 -18 -9 -9 138 55 146 15 19 30 8 A 100 70 2 | 3145744 1994 1 25 10 5 21.960 L 2.350 X 34.22600 -118.60500 19.950 X -9.000 0.000 1.000 -9.000 -18 -9 -9 141 54 107 21 30 32 9 B 84 65 3 | 3146815 1994 1 28 7 44 46.300 L 3.430 X 34.23300 -118.61500 20.880 X -9.000 0.000 1.000 -9.000 -18 -9 -9 147 54 134 15 15 75 17 B 100 55 4 | 3146907 1994 1 28 15 47 20.400 L 2.050 X 34.22200 -118.60200 21.210 X -9.000 0.000 1.000 -9.000 -18 -9 -9 110 51 84 25 27 23 11 B 86 66 5 | 3147167 1994 1 29 7 52 21.490 L 2.600 X 34.23400 -118.61700 20.900 X -9.000 0.000 1.000 -9.000 -18 -9 -9 146 54 111 19 25 55 18 B 92 60 6 | 3148047 1994 1 31 7 13 16.510 L 2.190 X 34.22800 -118.60900 21.110 X -9.000 0.000 1.000 -9.000 -18 -9 -9 136 48 97 26 27 38 8 B 82 62 7 | 3149674 1994 2 5 7 11 45.120 L 2.440 X 34.23500 -118.60700 19.700 X -9.000 0.000 1.000 -9.000 -18 -9 -9 136 48 101 17 22 49 18 B 97 60 8 | 3150936 1994 2 10 4 19 26.020 L 2.500 X 34.23700 -118.62000 20.440 X -9.000 0.000 1.000 -9.000 -18 -9 -9 271 51 52 22 17 57 11 A 95 53 9 | 3150947 1994 2 10 4 46 40.660 L 2.270 X 34.22600 -118.61000 19.780 X -9.000 0.000 1.000 -9.000 -18 -9 -9 144 46 132 13 13 48 12 A 100 57 10 | 3151649 1994 2 13 9 4 56.410 L 2.070 X 34.22300 -118.61300 20.590 X -9.000 0.000 1.000 -9.000 -18 -9 -9 292 46 82 25 20 32 9 A 91 58 11 | 3152142 1994 2 14 13 19 47.530 L 2.330 X 34.22700 -118.60800 19.860 X -9.000 0.000 1.000 -9.000 -18 -9 -9 285 48 71 23 20 47 6 A 96 55 12 | 2148509 1994 2 15 1 59 47.350 L 2.480 X 34.23200 -118.61500 20.600 X -9.000 0.000 1.000 -9.000 -18 -9 -9 121 48 98 18 21 62 23 C 98 54 13 | 3152388 1994 2 15 4 10 52.010 L 1.960 X 34.22700 -118.60800 19.630 X -9.000 0.000 1.000 -9.000 -18 -9 -9 292 45 74 27 25 32 13 B 69 60 14 | 3152559 1994 2 15 21 13 53.960 L 2.320 X 34.22700 -118.61100 20.070 X -9.000 0.000 1.000 -9.000 -18 -9 -9 145 44 117 18 24 41 11 A 96 56 15 | 3153955 1994 2 20 19 35 21.040 L 1.890 X 34.22200 -118.60000 19.510 X -9.000 0.000 1.000 -9.000 -18 -9 -9 317 40 119 26 24 31 7 A 92 62 16 | 3158361 1994 3 14 10 2 19.320 L 2.180 X 34.23300 -118.61300 20.090 X -9.000 0.000 1.000 -9.000 -18 -9 -9 136 44 120 18 19 47 9 A 100 56 17 | 3159027 1994 3 18 8 27 27.010 L 2.210 X 34.22600 -118.60800 19.860 X -9.000 0.000 1.000 -9.000 -18 -9 -9 126 49 103 22 26 39 8 A 90 59 18 | 3159267 1994 3 20 0 11 12.920 L 2.450 X 34.23500 -118.60800 19.220 X -9.000 0.000 1.000 -9.000 -18 -9 -9 133 54 112 19 22 43 5 A 97 57 19 | 2155068 1994 3 22 13 7 33.580 L 2.300 X 34.22400 -118.60300 19.910 X -9.000 0.000 1.000 -9.000 -18 -9 -9 151 50 130 22 22 33 0 A 97 55 20 | 3160206 1994 3 24 11 23 51.510 L 1.740 X 34.22400 -118.60700 19.990 X -9.000 0.000 1.000 -9.000 -18 -9 -9 143 48 121 21 23 29 7 A 96 60 21 | 3177685 1994 7 26 2 58 20.670 L 2.630 X 34.23200 -118.60400 18.820 X -9.000 0.000 1.000 -9.000 -18 -9 -9 132 38 132 23 32 49 12 B 73 55 22 | 3148018 1994 1 31 4 53 39.200 L 2.130 X 34.23100 -118.60600 18.940 X -9.000 0.000 1.000 -9.000 -18 -9 -9 152 48 113 18 24 46 15 B 94 52 23 | 3150301 1994 2 7 5 23 49.730 L 1.760 X 34.21800 -118.60500 19.870 X -9.000 0.000 1.000 -9.000 -18 -9 -9 116 46 86 25 33 32 21 C 82 67 24 | 3150490 1994 2 8 2 7 8.810 L 2.610 X 34.23100 -118.59800 18.750 X -9.000 0.000 1.000 -9.000 -18 -9 -9 311 44 109 24 23 58 13 A 92 57 25 | -------------------------------------------------------------------------------- /hashpy/tests/data/example5.inp: -------------------------------------------------------------------------------- 1 | scsn.reverse 2 | north5.simul 3 | north2.phase 4 | test5.out 5 | test5.out2 6 | 8 7 | 90 8 | 60 9 | 5 10 | 30 11 | 500 12 | 0.1 13 | 120 14 | 45 15 | 0.25 16 | 5 17 | -------------------------------------------------------------------------------- /hashpy/tests/data/example5.out: -------------------------------------------------------------------------------- 1 | 3143312 1994 1 21 11 4 14.750 L 2.300 X 34.23150 -118.60883 19.690 X 0.220 0.000 0.000 -9.000 -18 -9 -9 135 49 144 28 30 25 11 B 77 65 2 | 3145744 1994 1 25 10 5 21.380 L 2.400 X 34.20867 -118.62750 19.300 X 0.210 0.000 0.000 -9.000 -18 -9 -9 162 49 142 31 39 27 19 B 62 57 * 3 | 3145744 1994 1 25 10 5 21.380 L 2.400 X 34.20867 -118.62750 19.300 X 0.210 0.000 0.000 -9.000 -18 -9 -9 340 76 140 43 46 27 16 D 28 57 * 4 | 3146815 1994 1 28 7 44 45.640 L 3.400 X 34.20950 -118.61850 21.080 X 0.220 0.000 0.000 -9.000 -18 -9 -9 149 35 144 18 19 42 11 A 100 55 5 | 3146907 1994 1 28 15 47 20.270 L 2.000 X 34.20683 -118.61916 15.810 X 0.130 0.000 0.000 -9.000 -18 -9 -9 287 53 81 40 37 19 6 C 50 61 * 6 | 3146907 1994 1 28 15 47 20.270 L 2.000 X 34.20683 -118.61916 15.810 X 0.130 0.000 0.000 -9.000 -18 -9 -9 152 89 -153 42 45 19 21 D 33 61 * 7 | 3147167 1994 1 29 7 52 20.860 L 2.600 X 34.20650 -118.62817 19.610 X 0.190 0.000 0.000 -9.000 -18 -9 -9 142 41 117 15 18 47 9 A 100 54 8 | 3148047 1994 1 31 7 13 16.400 L 2.200 X 34.20733 -118.62700 15.960 X 0.160 0.000 0.000 -9.000 -18 -9 -9 160 44 133 21 20 32 3 A 100 53 9 | 3149674 1994 2 5 7 11 44.590 L 2.400 X 34.22383 -118.59883 17.500 X 0.200 0.000 0.000 -9.000 -18 -9 -9 140 40 112 23 23 41 14 A 95 58 10 | 3150936 1994 2 10 4 19 25.560 L 2.500 X 34.21283 -118.62617 17.790 X 0.180 0.000 0.000 -9.000 -18 -9 -9 274 59 63 19 20 38 7 A 99 60 11 | 3150947 1994 2 10 4 46 40.310 L 2.300 X 34.21417 -118.62600 17.450 X 0.200 0.000 0.000 -9.000 -18 -9 -9 158 49 139 20 19 39 9 A 99 53 12 | 3151649 1994 2 13 9 4 56.150 L 2.100 X 34.21050 -118.63467 17.540 X 0.170 0.000 0.000 -9.000 -18 -9 -9 120 35 94 26 29 26 0 B 79 56 13 | 3152142 1994 2 14 13 19 47.140 L 2.300 X 34.21150 -118.63050 17.650 X 0.210 0.000 0.000 -9.000 -18 -9 -9 146 35 126 22 23 39 7 A 94 60 14 | 2148509 1994 2 15 1 59 46.790 L 2.500 X 34.21967 -118.62383 19.240 X 0.220 0.000 0.000 -9.000 -18 -9 -9 300 50 96 23 21 42 18 B 97 53 15 | 3152388 1994 2 15 4 10 51.410 L 2.000 X 34.21450 -118.58850 17.690 X 0.200 0.000 0.000 -9.000 -18 -9 -9 160 51 140 35 35 26 10 C 57 58 * 16 | 3152388 1994 2 15 4 10 51.410 L 2.000 X 34.21450 -118.58850 17.690 X 0.200 0.000 0.000 -9.000 -18 -9 -9 327 66 124 41 43 26 5 D 33 58 * 17 | 3152559 1994 2 15 21 13 53.640 L 2.300 X 34.21633 -118.63100 17.410 X 0.180 0.000 0.000 -9.000 -18 -9 -9 159 42 130 21 21 32 8 A 97 53 18 | 3153955 1994 2 20 19 35 20.790 L 1.900 X 34.21750 -118.62933 16.530 X 0.170 0.000 0.000 -9.000 -18 -9 -9 317 48 120 30 28 27 0 B 79 60 19 | 3158361 1994 3 14 10 2 18.580 L 2.200 X 34.21517 -118.59383 18.560 X 0.190 0.000 0.000 -9.000 -18 -9 -9 145 42 125 24 22 34 10 A 91 51 20 | 3159267 1994 3 20 0 11 12.040 L 2.500 X 34.21833 -118.59917 18.840 X 0.180 0.000 0.000 -9.000 -18 -9 -9 133 46 115 22 23 35 6 A 95 51 21 | 2155068 1994 3 22 13 7 32.760 L 2.300 X 34.21733 -118.59917 20.010 X 0.190 0.000 0.000 -9.000 -18 -9 -9 157 47 138 29 29 28 0 B 74 48 22 | 3177685 1994 7 26 2 58 19.590 L 2.600 X 34.22817 -118.59967 20.170 X 0.220 0.000 0.000 -9.000 -18 -9 -9 135 46 120 22 22 31 6 B 92 47 23 | 3148018 1994 1 31 4 53 38.980 L 2.100 X 34.20550 -118.62583 15.080 X 0.160 0.000 0.000 -9.000 -18 -9 -9 293 63 65 25 20 36 10 A 93 53 24 | 3150301 1994 2 7 5 23 49.550 L 1.800 X 34.20600 -118.61450 15.450 X 0.160 0.000 0.000 -9.000 -18 -9 -9 136 34 119 29 32 28 22 C 70 59 25 | 3150490 1994 2 8 2 7 8.290 L 2.600 X 34.22800 -118.56017 18.240 X 0.170 0.000 0.000 -9.000 -18 -9 -9 104 45 76 23 23 41 14 A 93 54 26 | -------------------------------------------------------------------------------- /hashpy/tests/data/north3.amp: -------------------------------------------------------------------------------- 1 | 2148509 12 2 | GRH EHZ CI 36.53 28.30 0.715 35.705 16.989 124.245 3 | NHL ELZ CI 6.16 45.41 0.265 1.731 1.234 31.955 4 | SYL ELZ CI 51.13 50.76 0.111 0.159 -0.757 61.141 5 | BRCY EHZ NO 10.89 23.49 0.075 0.102 8.449 78.074 6 | BRCY ELZ NO 10.89 23.49 0.007 0.023 -0.131 1.128 7 | LA00 EHZ NO 134.84 53.09 0.114 3.271 -1.458 38.552 8 | LA01 EHZ NO 126.52 51.85 1.794 13.294 6.943 294.453 9 | MPKP EHZ NO 281.82 57.60 2.906 30.658 11.073 235.186 10 | MPKP ELZ NO 281.82 57.60 0.045 0.692 0.291 7.384 11 | PIRU EHZ NO 319.41 58.08 0.407 2.754 -1.977 34.166 12 | SSAP EHZ NO 262.16 27.18 0.250 0.383 48.930 291.579 13 | SSAP ELZ NO 262.16 27.18 0.023 0.041 1.543 9.161 14 | 2155068 2 15 | GRH EHZ CI 34.04 28.42 0.543 14.456 7.918 118.515 16 | NHL ELZ CI 5.03 45.86 0.343 0.931 1.034 17.428 17 | 3143312 8 18 | NHL ELZ CI 5.77 45.31 0.620 2.068 1.937 16.295 19 | SMF ELZ CI 147.40 62.82 0.472 0.473 1.545 0.834 20 | BRCY EHZ NO 10.09 23.22 2.328 2.901 26.992 54.247 21 | CPCP EHZ NO 165.73 11.72 0.712 3.756 -2.314 13.117 22 | LA00 EHZ NO 135.25 53.15 0.163 1.749 -1.248 15.408 23 | LA01 EHZ NO 126.94 51.88 0.871 8.648 2.875 97.636 24 | SMIP EHZ NO 296.77 16.57 0.396 0.447 -6.291 19.795 25 | SMIP ELZ NO 296.77 16.57 0.086 0.123 -0.865 2.477 26 | 3145744 10 27 | CALB HHZ CI 183.38 33.14 4.423 17.526 -219.985 1382.174 28 | GRH EHZ CI 37.31 28.31 1.325 13.925 4.735 127.654 29 | NHL ELZ CI 6.81 45.01 0.202 2.162 0.787 19.098 30 | SYL ELZ CI 51.37 50.53 0.184 0.239 -0.854 35.766 31 | CPCP EHZ NO 160.05 11.34 0.537 0.676 -2.718 22.879 32 | CPCP ELZ NO 160.05 11.34 0.073 0.097 -0.307 2.842 33 | CWHP EHZ NO 66.00 15.45 3.638 3.547 20.307 36.982 34 | LA00 EHZ NO 134.36 52.70 0.166 1.435 0.972 13.771 35 | LA01 EHZ NO 126.07 51.50 0.513 7.369 -1.587 66.936 36 | SFPW HLZ NO 74.06 48.50 0.916 6.870 -6.650 48.242 37 | 3146815 13 38 | CALB HHZ CI 183.29 32.02 10.379 1843.873 -6777.792 33854.555 39 | GRH EHZ CI 36.64 28.31 1.561 1.666 51.887 107.754 40 | NHL ELZ CI 6.82 44.77 0.289 14.058 -2.831 139.052 41 | SMF ELZ CI 146.42 61.50 0.431 11.618 -3.759 40.031 42 | SYL ELZ CI 50.93 50.12 0.232 69.780 -12.093 157.242 43 | BRCY EHZ NO 12.17 23.58 0.627 0.700 393.454 805.069 44 | CPCP EHZ NO 158.26 10.50 0.507 0.528 -35.156 274.551 45 | CPCP ELZ NO 158.26 10.50 0.069 0.067 -4.383 34.160 46 | CWHP ELZ NO 63.80 15.51 0.004 0.030 -0.024 0.809 47 | LA00 EHZ NO 133.87 51.85 0.144 12.326 -3.461 204.011 48 | PIRU EHZ NO 320.21 57.00 0.587 0.699 92.208 396.953 49 | PIRU ELZ NO 320.21 57.00 0.018 1.113 -0.127 3.086 50 | SFPW HLZ NO 73.43 47.99 1.005 107.015 -78.501 704.651 51 | 3146907 2 52 | BRCY EHZ NO 4.64 24.78 0.214 0.578 0.681 36.319 53 | LA00 EHZ NO 135.61 52.50 0.081 2.021 1.081 12.727 54 | 3147167 17 55 | GRH EHZ CI 37.68 28.66 0.994 23.980 10.147 132.441 56 | NHL ELZ CI 7.75 44.64 0.264 1.748 1.498 31.535 57 | SYL ELZ CI 51.24 50.18 0.163 0.236 -1.107 7.234 58 | BRCY ELZ NO 14.08 23.76 0.000 0.010 0.008 0.263 59 | CPCP EHZ NO 153.06 10.48 0.436 0.459 -6.988 35.204 60 | CPCP ELZ NO 153.06 10.48 0.061 0.068 -0.851 4.401 61 | CWHP EHZ NO 64.28 16.23 1.075 1.468 43.753 80.909 62 | LA00 EHZ NO 133.16 51.70 0.088 2.120 0.951 34.823 63 | LA01 EHZ NO 124.85 50.59 1.039 12.181 9.203 107.997 64 | MPKP EHZ NO 282.93 55.53 4.178 105.974 55.996 378.136 65 | MPKP ELZ NO 282.93 55.53 0.098 3.339 1.737 11.898 66 | PIRU EHZ NO 320.86 56.49 0.476 49.225 10.355 167.182 67 | SFPW HLZ NO 73.41 48.13 0.701 11.081 -9.171 97.652 68 | SMIP EHZ NO 305.20 14.82 0.268 0.298 -39.666 74.994 69 | SMIP ELZ NO 305.20 14.82 0.031 0.044 -1.260 2.351 70 | SSAP EHZ NO 264.22 24.53 0.254 0.299 122.270 354.448 71 | SSAP ELZ NO 264.22 24.53 0.027 0.050 3.849 11.184 72 | 3148018 13 73 | CALB HHZ CI 188.50 34.18 5.779 7.946 17.879 988.342 74 | SYL ELZ CI 48.83 51.47 0.209 1.601 0.708 17.616 75 | BRCY EHZ NO 4.75 25.24 0.488 0.713 24.476 148.837 76 | CWHP EHZ NO 56.34 14.15 1.122 1.674 10.346 101.199 77 | LA00 EHZ NO 135.58 53.12 0.093 1.041 -0.449 9.112 78 | LA01 EHZ NO 126.94 51.80 0.570 4.053 -1.777 44.894 79 | MPKP EHZ NO 282.32 59.83 0.975 10.271 -6.426 52.722 80 | PIRU EHZ NO 318.67 60.26 0.175 17.573 1.583 36.074 81 | SFPW HLZ NO 72.19 48.94 0.594 2.507 -2.674 29.390 82 | SMIP EHZ NO 298.12 19.75 0.711 0.853 50.415 245.065 83 | SMIP ELZ NO 298.12 19.75 0.033 0.043 1.574 7.685 84 | SSAP EHZ NO 265.11 30.18 0.180 0.272 23.578 140.572 85 | SSAP ELZ NO 265.11 30.18 0.014 0.032 0.720 4.438 86 | 3148047 11 87 | GRH EHZ CI 34.95 28.09 1.000 13.664 6.662 92.934 88 | CWHP EHZ NO 64.09 14.34 1.563 2.479 18.972 128.961 89 | LA00 EHZ NO 135.49 53.20 0.087 1.860 -0.344 16.208 90 | LA01 EHZ NO 127.11 51.92 0.541 7.566 3.288 108.927 91 | MPKP EHZ NO 281.63 58.40 0.550 12.824 9.272 68.169 92 | MPKP ELZ NO 281.63 58.40 0.008 0.309 0.209 2.143 93 | PIRU EHZ NO 318.82 58.74 0.330 10.165 1.123 106.646 94 | SMIP EHZ NO 296.52 17.41 0.441 0.671 68.456 180.341 95 | SMIP ELZ NO 296.52 17.41 0.035 0.039 2.152 5.669 96 | SSAP EHZ NO 262.32 28.39 0.169 0.198 33.660 119.100 97 | SSAP ELZ NO 262.32 28.39 0.030 0.038 1.072 3.749 98 | 3149674 12 99 | GRH EHZ CI 34.84 28.31 1.069 25.898 11.651 123.206 100 | NHL ELZ CI 5.37 45.66 0.343 1.421 1.271 21.521 101 | BRCY EHZ NO 9.06 23.85 0.477 0.504 31.939 297.161 102 | CWHP EHZ NO 62.58 14.70 2.209 4.655 29.308 269.917 103 | LA00 EHZ NO 134.93 52.67 0.090 1.466 -0.594 26.194 104 | MPKP EHZ NO 282.09 57.89 1.650 27.803 16.678 239.703 105 | MPKP ELZ NO 282.09 57.89 0.010 0.690 0.377 7.553 106 | PIRU EHZ NO 319.28 58.39 1.269 18.310 5.321 126.873 107 | SMIP EHZ NO 298.82 17.14 0.824 1.355 54.055 230.911 108 | SMIP ELZ NO 298.82 17.14 0.031 0.068 1.684 7.232 109 | SSAP EHZ NO 263.39 27.69 0.204 0.215 40.581 197.278 110 | SSAP ELZ NO 263.39 27.69 0.028 0.038 1.302 6.212 111 | 3150301 9 112 | GRH EHZ CI 32.01 29.20 0.709 6.672 2.942 58.867 113 | BRCY EHZ NO 6.26 25.24 0.445 0.450 12.764 72.352 114 | CWHP EHZ NO 56.90 14.67 1.112 2.346 8.757 36.228 115 | LA00 EHZ NO 134.97 52.80 0.039 0.491 -0.195 6.156 116 | PIRU EHZ NO 319.17 59.75 0.123 2.291 -2.501 37.993 117 | SMIP EHZ NO 299.95 19.02 0.890 1.382 23.734 64.565 118 | SMIP ELZ NO 299.95 19.02 0.017 0.045 -0.055 2.051 119 | SSAP EHZ NO 265.57 29.19 0.139 0.187 12.385 55.485 120 | SSAP ELZ NO 265.57 29.19 0.012 0.033 0.357 1.752 121 | 3150490 17 122 | CALB HHZ CI 190.53 33.85 12.676 625.670 -1033.778 7318.258 123 | GRH EHZ CI 28.97 28.06 1.697 52.590 21.224 150.840 124 | NHL ELZ CI 2.12 46.70 0.338 3.171 3.264 33.531 125 | SYL ELZ CI 48.05 50.44 0.661 6.175 2.630 61.955 126 | BRCY EHZ NO 1.80 24.77 0.441 0.677 103.059 739.123 127 | BRCY ELZ NO 1.80 24.77 0.015 0.024 -0.202 1.351 128 | CPCP EHZ NO 183.13 10.03 0.755 1.505 -10.524 30.663 129 | CPCP ELZ NO 183.13 10.03 0.093 0.192 -1.260 3.814 130 | CWHP EHZ NO 53.05 12.85 2.896 4.730 74.805 93.640 131 | LA00 EHZ NO 136.38 52.17 0.147 8.146 3.266 57.099 132 | MPKP EHZ NO 282.13 59.80 2.429 33.005 30.195 194.848 133 | MPKP ELZ NO 282.13 59.80 0.039 0.794 0.712 6.137 134 | PIRU EHZ NO 318.02 60.07 2.153 2.141 -12.080 26.216 135 | SMIP EHZ NO 296.41 20.49 1.247 2.761 243.429 696.656 136 | SMIP ELZ NO 296.41 20.49 0.041 0.092 7.584 21.958 137 | SSAP EHZ NO 265.31 30.81 0.301 0.356 145.906 510.328 138 | SSAP ELZ NO 265.31 30.81 0.028 0.048 4.618 16.062 139 | 3150936 12 140 | CALB HHZ CI 183.81 33.74 15.016 129.618 395.901 3170.389 141 | GRH EHZ CI 37.27 28.20 0.769 15.872 2.811 177.394 142 | SMF ELZ CI 146.98 62.66 0.628 0.836 -2.085 2.799 143 | SYL ELZ CI 51.45 50.65 0.180 2.723 -0.666 39.193 144 | BRCY EHZ NO 11.79 23.26 0.320 0.528 22.310 506.779 145 | CWHP EHZ NO 66.77 15.22 1.664 1.842 8.060 307.105 146 | MPKP EHZ NO 281.74 57.27 1.711 83.657 24.413 464.720 147 | MPKP ELZ NO 281.74 57.27 0.029 2.157 0.633 14.616 148 | PIRU EHZ NO 319.51 57.76 0.609 0.753 12.244 49.834 149 | SFPW HLZ NO 74.31 48.66 0.780 8.970 -6.477 50.573 150 | SSAP EHZ NO 261.69 26.78 0.178 0.208 27.986 321.195 151 | SSAP ELZ NO 261.69 26.78 0.013 0.030 0.848 10.141 152 | 3150947 9 153 | GRH EHZ CI 36.85 28.27 1.011 9.813 4.198 120.769 154 | SYL ELZ CI 51.20 50.55 0.159 0.245 -0.629 29.879 155 | BRCY EHZ NO 11.61 23.43 0.270 0.388 21.616 301.397 156 | CWHP EHZ NO 65.55 15.26 1.654 2.415 14.127 210.688 157 | MPKP ELZ NO 282.00 57.09 0.026 1.144 -0.093 6.701 158 | PIRU EHZ NO 319.67 57.65 1.514 51.306 -40.098 178.121 159 | SFPW HLZ NO 73.98 48.49 0.872 6.233 -4.053 37.627 160 | SSAP EHZ NO 262.42 26.57 0.152 0.185 32.608 195.746 161 | SSAP ELZ NO 262.42 26.57 0.017 0.034 1.015 6.184 162 | 3151649 6 163 | GRH EHZ CI 32.11 28.99 3.253 13.462 -12.269 82.271 164 | BRCY EHZ NO 6.19 25.02 0.467 0.599 2.810 14.986 165 | LA00 EHZ NO 135.11 52.78 0.105 0.723 -0.414 9.476 166 | LA01 EHZ NO 126.51 51.51 0.326 3.671 2.275 71.131 167 | SSAP EHZ NO 265.24 29.19 0.108 0.255 19.610 87.717 168 | SSAP ELZ NO 265.24 29.19 0.013 0.038 0.572 2.776 169 | 3152142 10 170 | GRH EHZ CI 35.67 28.32 3.725 27.196 13.164 143.828 171 | NHL ELZ CI 5.58 45.74 0.287 0.307 -0.988 5.378 172 | SYL ELZ CI 50.83 50.91 0.181 0.222 -0.703 48.934 173 | BRCY EHZ NO 9.61 23.65 0.074 0.103 5.121 54.647 174 | LA00 EHZ NO 135.16 53.27 0.078 1.359 -0.551 18.956 175 | MPKP EHZ NO 281.74 58.16 2.222 34.324 21.403 215.437 176 | MPKP ELZ NO 281.74 58.16 0.035 0.839 0.528 6.789 177 | PIRU EHZ NO 319.11 58.57 0.177 5.395 0.550 35.856 178 | SSAP EHZ NO 262.31 27.92 0.153 0.214 34.217 309.015 179 | SSAP ELZ NO 262.31 27.92 0.013 0.029 1.017 9.731 180 | 3152388 9 181 | CALB HHZ CI 183.35 32.97 20.028 73.363 123.791 1059.895 182 | GRH EHZ CI 36.83 28.84 0.544 6.471 2.618 81.676 183 | SMF ELZ CI 146.52 62.38 0.618 0.725 -1.979 1.735 184 | SYL ELZ CI 51.07 50.92 0.188 0.213 0.723 12.793 185 | BRCY EHZ NO 12.17 23.98 0.079 0.143 1.867 20.339 186 | LA00 EHZ NO 134.04 52.79 0.142 0.611 -0.458 7.343 187 | PIRU EHZ NO 320.08 57.80 0.012 1.590 0.211 5.780 188 | SSAP EHZ NO 263.32 26.31 0.087 0.233 24.342 78.125 189 | SSAP ELZ NO 263.32 26.31 0.014 0.038 0.710 2.451 190 | 3152559 6 191 | GRH EHZ CI 34.25 28.69 1.804 19.420 8.586 135.576 192 | SYL ELZ CI 50.11 51.08 0.153 3.058 -0.609 37.744 193 | BRCY EHZ NO 8.43 24.30 0.079 0.112 4.485 31.173 194 | LA00 EHZ NO 134.97 52.99 0.181 1.917 -0.642 21.995 195 | SSAP EHZ NO 263.80 28.24 0.514 0.734 33.401 239.915 196 | SSAP ELZ NO 263.80 28.24 0.016 0.048 1.003 7.549 197 | 3153955 5 198 | GRH EHZ CI 31.63 28.73 1.007 7.407 3.588 81.246 199 | NHL ELZ CI 3.81 46.68 0.239 0.775 0.815 5.069 200 | BRCY EHZ NO 5.52 24.87 0.073 0.076 1.406 13.814 201 | SSAP EHZ NO 265.29 29.30 0.130 0.291 15.620 44.924 202 | SSAP ELZ NO 265.29 29.30 0.009 0.032 -0.038 1.401 203 | 3158361 4 204 | GRH EHZ CI 35.28 28.57 1.857 14.702 8.382 122.796 205 | NHL ELZ CI 5.86 45.63 0.292 1.324 1.015 18.768 206 | SMF ELZ CI 146.92 62.23 0.451 0.782 -1.762 2.252 207 | SYL ELZ CI 50.44 50.71 0.166 0.227 0.969 31.369 208 | 3159027 1 209 | GRH EHZ CI 35.44 28.28 0.639 15.804 7.929 103.790 210 | 3159267 4 211 | CALB HHZ CI 185.86 33.97 23.951 313.289 -188.548 4583.825 212 | GRH EHZ CI 34.84 28.19 1.297 20.935 9.711 139.084 213 | NHL ELZ CI 5.15 45.75 0.276 2.267 1.971 23.831 214 | SYL ELZ CI 50.48 50.74 0.184 0.231 -0.851 46.376 215 | 3160206 1 216 | GRH EHZ CI 35.61 28.74 0.389 4.169 2.374 57.747 217 | 3177685 3 218 | GRH EHZ CI 31.89 28.46 0.825 48.831 22.494 160.374 219 | NHL ELZ CI 3.74 46.53 0.255 1.862 -1.717 34.065 220 | SYL ELZ CI 49.19 50.88 0.168 4.137 -0.841 67.377 221 | -------------------------------------------------------------------------------- /hashpy/tests/data/north3.statcor: -------------------------------------------------------------------------------- 1 | BRCY EHZ XX -0.0550 2 | BRCY ELZ XX -0.3102 3 | CALB BHZ XX 0.1338 4 | CALB HHZ XX 0.2692 5 | CALB HLZ XX 0.3478 6 | CPCP EHZ XX -0.2575 7 | CPCP ELZ XX -0.1798 8 | CWHP EHZ XX -0.0798 9 | CWHP ELZ XX -0.6717 10 | GRH VHZ XX 0.0940 11 | GRH VLZ XX 0.0163 12 | LA00 EHZ XX 0.2662 13 | LA00 ELZ XX -0.3327 14 | LA01 EHZ XX 0.3672 15 | LA01 ELZ XX 0.1062 16 | MPKP EHZ XX 0.1867 17 | MPKP ELZ XX 0.2766 18 | NHL VLZ XX 0.0210 19 | NHL VHZ XX -0.2288 20 | PIRU EHZ XX 0.1011 21 | PIRU ELZ XX -0.6712 22 | SFPW ELZ XX -0.3949 23 | SFPW HLZ XX -0.1880 24 | SMF VHZ XX -0.4455 25 | SMF VLZ XX -0.5512 26 | SMIP EHZ XX 0.1305 27 | SMIP ELZ XX 0.1412 28 | SSAP EHZ XX 0.0835 29 | SSAP ELZ XX 0.0835 30 | SYL VHZ XX -0.2889 31 | SYL VLZ XX 0.3917 32 | -------------------------------------------------------------------------------- /hashpy/tests/data/north5.simul: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markcwill/hashpy/d6a334717e603936cf537646955b0c114c9bedf6/hashpy/tests/data/north5.simul -------------------------------------------------------------------------------- /hashpy/tests/data/scsn.reverse: -------------------------------------------------------------------------------- 1 | AQUA 19920101 19921231 2 | BAC 19950624 19960124 3 | BAHA 19940101 0 4 | BAR 19780124 19780328 5 | BCPP 19940101 0 6 | BLU 19790605 19790628 7 | BRCJ 19920101 19921231 8 | CFL 19861114 19880801 9 | CFT 19870224 19880523 10 | CHIM 19940101 0 11 | CIS 19771109 19780819 12 | CIW 19850725 19851111 13 | COVF 19920101 19921231 14 | CPCP 19940101 0 15 | CPE 19840501 19880810 16 | CSP 0 19960628 17 | CTW 19930101 19931231 18 | DHB 0 19871231 19 | DHB 19920101 0 20 | DWSR 19920101 19921231 21 | EDC1 19920101 19921231 22 | EDCY 19920101 19921231 23 | EDOM 19920101 19921231 24 | EFRN 19940101 0 25 | ESG 0 0 26 | ETHY 19940101 0 27 | EWC9 19831229 19890727 28 | EWCV 19831229 19890727 29 | FIL 19970401 0 30 | FIRN 19940101 0 31 | FLA 19860209 19870204 32 | FLA 19880101 19880624 33 | FMA 19840101 19861231 34 | FRI 0 0 35 | FRK 19870522 19880607 36 | GAV 19821210 19831216 37 | GFP 19840104 19841231 38 | GFP 19860608 19871231 39 | GFP 19920701 19920731 40 | GLA 19920101 0 41 | GRAC 19920601 19921231 42 | GRTT 19940101 0 43 | GSC 19880719 19890201 44 | HAY 19840301 19840725 45 | HAY 19900101 19930131 46 | HERK 19940101 0 47 | HOT 19770907 19780825 48 | IKP 19841113 19880810 49 | IKP 19920101 19960101 50 | IPC 19840101 19850816 51 | IPC 19881101 0 52 | IRC 19771008 19780420 53 | IRC 19801023 19820425 54 | ISA 19870620 19880712 55 | JAS 0 0 56 | JFPP 19940101 0 57 | JNH 19960101 19960303 58 | KEYV 19920101 19961231 59 | KMCH 19940101 0 60 | KMNP 19940101 0 61 | KMSF 19940101 0 62 | KSRG 19940101 0 63 | LCL 19850515 19850816 64 | LCL 19870101 19880624 65 | LCM 19841126 19841231 66 | LCM 19861126 19871231 67 | LMVR 19920101 19921231 68 | LNA 19840101 19850816 69 | LNA 19860101 19860624 70 | LNA 19870101 19880624 71 | LNA 19920101 0 72 | LOM 19940101 0 73 | LTM 19780101 19780907 74 | MGUY 19940101 0 75 | MNP 19920101 0 76 | MTC 19880701 0 77 | MTCZ 19880701 0 78 | MWC 19940101 19940509 79 | ORV 0 0 80 | PAG 19850327 19850808 81 | PBW 19850426 19850807 82 | PCA 19820628 19820902 83 | PCA 19850411 0 84 | PEC 19770101 19800426 85 | PEC 19820805 19840806 86 | PEC 19850402 19851205 87 | PEC 19860422 19860930 88 | PEC 19870211 0 89 | PGH 19850502 19850808 90 | PHA 19850328 19850808 91 | PHC 19850429 19850807 92 | PHS 19850524 19850809 93 | PLS 19930101 19930527 94 | PMC 19850328 19850808 95 | PMCV 19850328 19850808 96 | PMCZ 19850328 19850808 97 | PMP 19801022 19820827 98 | PMPV 19850425 19850808 99 | PMR 19850326 19850808 100 | PPF 19850306 19850808 101 | PPT 19810513 19820901 102 | PRI 0 0 103 | PSE 19820527 19820831 104 | PSH 19850410 19850808 105 | PSR 19850411 19850808 106 | PST 19850329 19850809 107 | PTD 19800423 19850910 108 | PTR 19850520 19850808 109 | PTR 19860930 0 110 | PVP 19840101 19850320 111 | PWK 19850306 19850809 112 | PYR 19820805 19901215 113 | PYR 19920101 0 114 | RCP 19840101 19840612 115 | RCP 19870210 19880624 116 | SAT 19890413 19911231 117 | SAT9 19890413 0 118 | SATM 19890413 0 119 | SBLG 19780405 19800801 120 | SCY 19940101 0 121 | SDCE 19920101 19921231 122 | SIM 19890101 19940101 123 | SLG 19780405 19800801 124 | SMIP 19940101 19940130 125 | SNS 19780518 19790518 126 | SNS 19850901 19920101 127 | SWM 19910101 19950101 128 | SWM 19950528 19951231 129 | SYP 19770909 19780202 130 | TJR 19950101 19951231 131 | TM2 19940101 0 132 | TPC 19770607 19780614 133 | TPC 19810428 19820805 134 | TPC 19840830 19880719 135 | TPO 19770607 19780424 136 | TPR 19840104 19841116 137 | TPR 19850320 19851101 138 | TPR 19920101 19920630 139 | TWL 19890101 19940101 140 | UCVF 19920101 19921231 141 | UGGP 19920601 19921231 142 | VANA 19940101 0 143 | VPD 19780621 19781120 144 | WBM 0 19850808 145 | YOLY 19940101 0 146 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.kds: -------------------------------------------------------------------------------- 1 | 0.00 3.0000 2 | 1.00 4.5000 3 | 2.00 5.5000 4 | 3.00 5.6000 5 | 4.00 5.7000 6 | 5.00 5.8000 7 | 6.00 5.9000 8 | 7.00 6.0000 9 | 8.00 6.0182 10 | 9.00 6.0364 11 | 10.00 6.0545 12 | 11.00 6.0727 13 | 12.00 6.0909 14 | 13.00 6.1091 15 | 14.00 6.1273 16 | 15.00 6.1455 17 | 16.00 6.1636 18 | 17.00 6.1818 19 | 18.00 6.2000 20 | 19.00 6.2300 21 | 20.00 6.2600 22 | 21.00 6.2900 23 | 22.00 6.3200 24 | 23.00 6.3500 25 | 24.00 6.3800 26 | 25.00 6.4100 27 | 26.00 6.4400 28 | 27.00 6.4700 29 | 28.00 6.5000 30 | 29.00 6.6300 31 | 30.00 6.7600 32 | 31.00 6.8900 33 | 32.00 7.0200 34 | 33.00 7.1500 35 | 34.00 7.2800 36 | 35.00 7.4100 37 | 36.00 7.5400 38 | 37.00 7.6700 39 | 38.00 7.8000 40 | 39.00 7.8182 41 | 40.00 7.8364 42 | 41.00 7.8545 43 | 42.00 7.8727 44 | 43.00 7.8909 45 | 44.00 7.9091 46 | 45.00 7.9273 47 | 46.00 7.9455 48 | 47.00 7.9636 49 | 48.00 7.9818 50 | 49.00 8.0000 51 | 50.00 8.0182 52 | 51.00 8.0364 53 | 52.00 8.0545 54 | 53.00 8.0727 55 | 54.00 8.0909 56 | 55.00 8.1091 57 | 56.00 8.1273 58 | 57.00 8.1455 59 | 58.00 8.1636 60 | 59.00 8.1818 61 | 60.00 8.2000 62 | 100.00 9.0 63 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.kds_orig: -------------------------------------------------------------------------------- 1 | 0.0 3.0 2 | 1.0 4.5 3 | 2.0 5.5 4 | 7.0 6.0 5 | 18.0 6.2 6 | 28.0 6.5 7 | 38.0 7.8 8 | 60.0 8.2 9 | 100.0 10.2 10 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.lab1: -------------------------------------------------------------------------------- 1 | 0.0 2.9300 2 | 1.0 3.5000 3 | 2.0 4.0667 4 | 3.0 4.6333 5 | 4.0 5.2000 6 | 5.0 5.4000 7 | 6.0 5.6000 8 | 7.0 5.8500 9 | 8.0 6.1000 10 | 9.0 6.1750 11 | 10.0 6.2500 12 | 11.0 6.3250 13 | 12.0 6.4000 14 | 13.0 6.4250 15 | 14.0 6.4500 16 | 15.0 6.4750 17 | 16.0 6.5000 18 | 17.0 6.5500 19 | 18.0 6.6000 20 | 19.0 6.6500 21 | 20.0 6.7000 22 | 21.0 6.7500 23 | 22.0 6.8000 24 | 23.0 6.8500 25 | 24.0 6.9000 26 | 25.0 6.9500 27 | 26.0 7.0000 28 | 27.0 7.0500 29 | 28.0 7.1000 30 | 29.0 7.1500 31 | 30.0 7.2000 32 | 31.0 7.2500 33 | 32.0 7.6700 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.north: -------------------------------------------------------------------------------- 1 | 0.0 4.0200 2 | 1.0 4.2800 3 | 2.0 4.5350 4 | 3.0 4.7900 5 | 4.0 5.0450 6 | 5.0 5.3000 7 | 6.0 5.5900 8 | 7.0 5.6725 9 | 8.0 5.7550 10 | 9.0 5.8375 11 | 10.0 5.9200 12 | 11.0 6.0527 13 | 12.0 6.1855 14 | 13.0 6.3182 15 | 14.0 6.4509 16 | 15.0 6.5836 17 | 16.0 6.6800 18 | 17.0 6.7200 19 | 18.0 6.7400 20 | 19.0 6.7600 21 | 20.0 6.7800 22 | 21.0 6.8000 23 | 22.0 6.8200 24 | 23.0 6.8256 25 | 24.0 6.8311 26 | 25.0 6.8367 27 | 26.0 6.8422 28 | 27.0 6.8478 29 | 28.0 6.8533 30 | 29.0 6.8589 31 | 30.0 6.8644 32 | 31.0 6.8700 33 | 32.0 7.4800 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.pickema1: -------------------------------------------------------------------------------- 1 | 0.00 3.0000 2 | 1.00 5.0000 3 | 2.00 6.0000 4 | 3.00 6.0385 5 | 4.00 6.0769 6 | 5.00 6.1154 7 | 6.00 6.1538 8 | 7.00 6.1923 9 | 8.00 6.2308 10 | 9.00 6.2692 11 | 10.00 6.3077 12 | 11.00 6.3462 13 | 12.00 6.3846 14 | 13.00 6.4231 15 | 14.00 6.4615 16 | 15.00 6.5000 17 | 16.00 6.5286 18 | 17.00 6.5571 19 | 18.00 6.5857 20 | 19.00 6.6143 21 | 20.00 6.6429 22 | 21.00 6.6714 23 | 22.00 6.7000 24 | 23.00 6.8917 25 | 24.00 7.0833 26 | 25.00 7.2750 27 | 26.00 7.4667 28 | 27.00 7.6583 29 | 28.00 7.8500 30 | 29.00 7.8609 31 | 30.00 7.8719 32 | 31.00 7.8828 33 | 32.00 7.8937 34 | 33.00 7.9047 35 | 34.00 7.9156 36 | 35.00 7.9266 37 | 36.00 7.9375 38 | 37.00 7.9484 39 | 38.00 7.9594 40 | 39.00 7.9703 41 | 40.00 7.9812 42 | 41.00 7.9922 43 | 42.00 8.0031 44 | 43.00 8.0141 45 | 44.00 8.0250 46 | 45.00 8.0359 47 | 46.00 8.0469 48 | 47.00 8.0578 49 | 48.00 8.0688 50 | 49.00 8.0797 51 | 50.00 8.0906 52 | 51.00 8.1016 53 | 52.00 8.1125 54 | 53.00 8.1234 55 | 54.00 8.1344 56 | 55.00 8.1453 57 | 56.00 8.1563 58 | 57.00 8.1672 59 | 58.00 8.1781 60 | 59.00 8.1891 61 | 60.00 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.pickema2: -------------------------------------------------------------------------------- 1 | 0.00 5.8500 2 | 1.00 5.8714 3 | 2.00 5.8929 4 | 3.00 5.9143 5 | 4.00 5.9357 6 | 5.00 5.9571 7 | 6.00 5.9786 8 | 7.00 6.0000 9 | 8.00 6.0467 10 | 9.00 6.0933 11 | 10.00 6.1400 12 | 11.00 6.1867 13 | 12.00 6.2333 14 | 13.00 6.2800 15 | 14.00 6.3267 16 | 15.00 6.3733 17 | 16.00 6.4200 18 | 17.00 6.4667 19 | 18.00 6.5133 20 | 19.00 6.5600 21 | 20.00 6.6067 22 | 21.00 6.6533 23 | 22.00 6.7000 24 | 23.00 6.8917 25 | 24.00 7.0833 26 | 25.00 7.2750 27 | 26.00 7.4667 28 | 27.00 7.6583 29 | 28.00 7.8500 30 | 29.00 7.8609 31 | 30.00 7.8719 32 | 31.00 7.8828 33 | 32.00 7.8937 34 | 33.00 7.9047 35 | 34.00 7.9156 36 | 35.00 7.9266 37 | 36.00 7.9375 38 | 37.00 7.9484 39 | 38.00 7.9594 40 | 39.00 7.9703 41 | 40.00 7.9812 42 | 41.00 7.9922 43 | 42.00 8.0031 44 | 43.00 8.0141 45 | 44.00 8.0250 46 | 45.00 8.0359 47 | 46.00 8.0469 48 | 47.00 8.0578 49 | 48.00 8.0688 50 | 49.00 8.0797 51 | 50.00 8.0906 52 | 51.00 8.1016 53 | 52.00 8.1125 54 | 53.00 8.1234 55 | 54.00 8.1344 56 | 55.00 8.1453 57 | 56.00 8.1563 58 | 57.00 8.1672 59 | 58.00 8.1781 60 | 59.00 8.1891 61 | 60.00 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.pickema3: -------------------------------------------------------------------------------- 1 | 0.00 3.0000 2 | 1.00 4.0000 3 | 2.00 5.2333 4 | 3.00 6.4667 5 | 3.50 5.8800 6 | 4.50 5.9100 7 | 5.50 5.9400 8 | 6.50 5.9700 9 | 7.50 6.0000 10 | 8.50 6.0625 11 | 9.50 6.1250 12 | 10.50 6.1875 13 | 11.50 6.2500 14 | 12.50 6.3125 15 | 13.50 6.3750 16 | 14.50 6.4375 17 | 15.50 6.5000 18 | 16.50 6.5286 19 | 17.50 6.5571 20 | 18.50 6.5857 21 | 19.50 6.6143 22 | 20.50 6.6429 23 | 21.50 6.6714 24 | 22.50 6.7000 25 | 23.50 6.8917 26 | 24.50 7.0833 27 | 25.50 7.2750 28 | 26.50 7.4667 29 | 27.50 7.6583 30 | 28.50 7.8500 31 | 29.50 7.8611 32 | 30.50 7.8722 33 | 31.50 7.8833 34 | 32.50 7.8944 35 | 33.50 7.9056 36 | 34.50 7.9167 37 | 35.50 7.9278 38 | 36.50 7.9389 39 | 37.50 7.9500 40 | 38.50 7.9611 41 | 39.50 7.9722 42 | 40.50 7.9833 43 | 41.50 7.9944 44 | 42.50 8.0056 45 | 43.50 8.0167 46 | 44.50 8.0278 47 | 45.50 8.0389 48 | 46.50 8.0500 49 | 47.50 8.0611 50 | 48.50 8.0722 51 | 49.50 8.0833 52 | 50.50 8.0944 53 | 51.50 8.1056 54 | 52.50 8.1167 55 | 53.50 8.1278 56 | 54.50 8.1389 57 | 55.50 8.1500 58 | 56.50 8.1611 59 | 57.50 8.1722 60 | 58.50 8.1833 61 | 59.50 8.1944 62 | 60.50 8.2056 63 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.sgm1: -------------------------------------------------------------------------------- 1 | 0.0 5.0700 2 | 1.0 5.3000 3 | 2.0 5.5333 4 | 3.0 5.7667 5 | 4.0 6.0000 6 | 5.0 6.0500 7 | 6.0 6.1000 8 | 7.0 6.1500 9 | 8.0 6.2000 10 | 9.0 6.2500 11 | 10.0 6.3000 12 | 11.0 6.3500 13 | 12.0 6.4000 14 | 13.0 6.4000 15 | 14.0 6.4000 16 | 15.0 6.4000 17 | 16.0 6.4000 18 | 17.0 6.4500 19 | 18.0 6.5000 20 | 19.0 6.5500 21 | 20.0 6.6000 22 | 21.0 6.6500 23 | 22.0 6.7000 24 | 23.0 6.7500 25 | 24.0 6.8000 26 | 25.0 6.8500 27 | 26.0 6.9000 28 | 27.0 6.9500 29 | 28.0 7.0000 30 | 29.0 7.0500 31 | 30.0 7.1000 32 | 31.0 7.1500 33 | 32.0 7.6200 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.socal: -------------------------------------------------------------------------------- 1 | 0.0 4.7000 2 | 1.0 4.9909 3 | 2.0 5.2818 4 | 3.0 5.5727 5 | 4.0 5.8636 6 | 5.0 6.1545 7 | 6.0 6.3075 8 | 7.0 6.3226 9 | 8.0 6.3377 10 | 9.0 6.3528 11 | 10.0 6.3679 12 | 11.0 6.3830 13 | 12.0 6.3981 14 | 13.0 6.4132 15 | 14.0 6.4283 16 | 15.0 6.4434 17 | 16.0 6.4585 18 | 17.0 6.4736 19 | 18.0 6.4887 20 | 19.0 6.5038 21 | 20.0 6.5189 22 | 21.0 6.5340 23 | 22.0 6.5491 24 | 23.0 6.5642 25 | 24.0 6.5792 26 | 25.0 6.5943 27 | 26.0 6.6094 28 | 27.0 6.6245 29 | 28.0 6.6396 30 | 29.0 6.6547 31 | 30.0 6.6698 32 | 31.0 6.6849 33 | 32.0 6.7000 34 | 33.0 7.8036 35 | 34.0 7.8071 36 | 35.0 7.8107 37 | 36.0 7.8143 38 | 37.0 7.8179 39 | 38.0 7.8214 40 | 39.0 7.8250 41 | 40.0 7.8286 42 | 41.0 7.8321 43 | 42.0 7.8357 44 | 43.0 7.8393 45 | 44.0 7.8429 46 | 45.0 7.8464 47 | 46.0 7.8500 48 | 47.0 7.8536 49 | 48.0 7.8571 50 | 49.0 7.8607 51 | 50.0 7.8643 52 | 51.0 7.8679 53 | 52.0 7.8714 54 | 53.0 7.8750 55 | 54.0 7.8786 56 | 55.0 7.8821 57 | 56.0 7.8857 58 | 57.0 7.8893 59 | 58.0 7.8929 60 | 59.0 7.8964 61 | 60.0 7.9000 62 | -------------------------------------------------------------------------------- /hashpy/tests/data/vz.vb1: -------------------------------------------------------------------------------- 1 | 0.0 3.4300 2 | 1.0 3.7000 3 | 2.0 3.9667 4 | 3.0 4.2333 5 | 4.0 4.5000 6 | 5.0 5.0000 7 | 6.0 5.5000 8 | 7.0 5.5500 9 | 8.0 5.6000 10 | 9.0 5.7000 11 | 10.0 5.8000 12 | 11.0 5.9000 13 | 12.0 6.0000 14 | 13.0 6.1750 15 | 14.0 6.3500 16 | 15.0 6.5250 17 | 16.0 6.7000 18 | 17.0 6.7250 19 | 18.0 6.7500 20 | 19.0 6.7750 21 | 20.0 6.8000 22 | 21.0 6.8255 23 | 22.0 6.8509 24 | 23.0 6.8764 25 | 24.0 6.9018 26 | 25.0 6.9273 27 | 26.0 6.9527 28 | 27.0 6.9782 29 | 28.0 7.0036 30 | 29.0 7.0291 31 | 30.0 7.0545 32 | 31.0 7.0800 33 | 32.0 7.5850 34 | 33.0 8.0900 35 | 34.0 8.0941 36 | 35.0 8.0981 37 | 36.0 8.1022 38 | 37.0 8.1063 39 | 38.0 8.1104 40 | 39.0 8.1144 41 | 40.0 8.1185 42 | 41.0 8.1226 43 | 42.0 8.1267 44 | 43.0 8.1307 45 | 44.0 8.1348 46 | 45.0 8.1389 47 | 46.0 8.1430 48 | 47.0 8.1470 49 | 48.0 8.1511 50 | 49.0 8.1552 51 | 50.0 8.1593 52 | 51.0 8.1633 53 | 52.0 8.1674 54 | 53.0 8.1715 55 | 54.0 8.1756 56 | 55.0 8.1796 57 | 56.0 8.1837 58 | 57.0 8.1878 59 | 58.0 8.1919 60 | 59.0 8.1959 61 | 60.0 8.2000 62 | -------------------------------------------------------------------------------- /hashpy/tests/test_dbhash.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | # dbhash.py 4 | # 5 | # functions which run HASH using Antelope and hashpy 6 | # 7 | # optionally, can plot by passing ObsPy output to a plotter 8 | """ 9 | import os 10 | from hashpy.hashpype import HashPype, HashError 11 | from hashpy.io.antelopeIO import ( load_pf, eventfocalmech2db, dbloc_source_db, RowPointerDict ) 12 | 13 | def _dump_bitmap(figure=None, directory='.', uid=None): 14 | """ 15 | Dump mpl figure to a file 16 | 17 | Given a figure & dir, make folder called 'images' and 18 | dump it into a png file called '_focalmech.png' 19 | 20 | """ 21 | filename = 'focalmech.png' 22 | if uid: 23 | filename = '_'.join([str(uid),filename]) 24 | imagedir = os.path.join(directory, 'images') 25 | if not os.path.exists(imagedir): 26 | os.mkdir(imagedir) 27 | fullname = os.path.join(imagedir, filename) 28 | figure.savefig(fullname) 29 | 30 | def dbhash_run(dbname, orid=None, pf=None): 31 | """ 32 | Perform a HASH run using Database input and command line args 33 | 34 | Input 35 | ----- 36 | args : Namespace of command line args 37 | 38 | Returns : hp : a hashpy.HashPype object containing solutions 39 | 40 | """ 41 | hp = HashPype() 42 | 43 | # Load settings data from a pf file... 44 | if pf: 45 | load_pf(hp, pffile=pf) 46 | else: 47 | load_pf(hp) 48 | 49 | # Grab data from the db... 50 | hp.input(dbname, format="ANTELOPE", orid=orid) 51 | 52 | # Run and catch errors from the minimum requirements checks 53 | try: 54 | hp.driver2(check_for_maximum_gap_size=False) 55 | except HashError as e: 56 | print "Failed! " + e.message 57 | except: 58 | raise 59 | 60 | return hp 61 | 62 | def main(): 63 | from argparse import ArgumentParser 64 | 65 | # Get command line args 66 | parser = ArgumentParser() 67 | parser.add_argument("dbin", help="Input database") 68 | parser.add_argument("dbout", help="Output database", nargs='?') 69 | parser.add_argument("-p", "--plot", help="Plot result", action='store_true') 70 | parser.add_argument("-l", "--loc", help="dbloc2 mode", action='store_true') 71 | parser.add_argument("-i", "--image", help="Save image with db", action='store_true') 72 | parser.add_argument("--pf", help="Parameter file") 73 | group = parser.add_mutually_exclusive_group() #required=True) 74 | group.add_argument("--evid", help="Event ID", type=int) 75 | group.add_argument("--orid", help="Origin ID", type=int) 76 | args = parser.parse_args() 77 | 78 | # Special 'dbloc2' settings 79 | if args.loc: 80 | from antelope.datascope import Dbptr 81 | # alter args b/c dbloc2 passes a db and a row number 82 | args.dbin = args.dbin.rstrip('.origin') 83 | db = Dbptr(args.dbin) 84 | db = db.lookup(table='origin') 85 | db.record = int(args.dbout) 86 | args.orid = db.getv('orid')[0] 87 | args.dbout = dbloc_source_db(args.dbin, pointer=False) 88 | args.plot = True # force plot 89 | args.image = True # force saving image to db folder 90 | 91 | # Now that we have a save location from command line args, 92 | # make a function to save to that database. The plotter is I/O 93 | # agnostic, it will accept a function to save anything anyhow anywhichway 94 | # 95 | def save_plot_to_db(fmplotter, dbname=args.dbout, dump_bitmap=args.image): 96 | focal_mech = fmplotter.event.focal_mechanisms[fmplotter._fm_index] 97 | if focal_mech is not fmplotter.event.preferred_focal_mechanism(): 98 | fmplotter.event.preferred_focal_mechanism_id = focal_mech.resource_id.resource_id 99 | 100 | # Save to db 101 | eventfocalmech2db(event=fmplotter.event, database=dbname) 102 | 103 | if dump_bitmap: 104 | vers = fmplotter.event.preferred_origin().creation_info.version 105 | dbdir = os.path.dirname(dbname) 106 | _dump_bitmap(figure=fmplotter.fig, directory=dbdir, uid=vers) 107 | 108 | # Run HASH 109 | hp = dbhash_run(args.dbin, orid=args.orid, pf=args.pf) 110 | 111 | # Launch plotter or spit out solution 112 | if args.plot: 113 | from hashpy.plotting.focalmechplotter import FocalMechPlotter 114 | ev = hp.output(format="OBSPY") 115 | p = FocalMechPlotter(ev, save=save_plot_to_db) 116 | else: 117 | # quick orid/strike/dip/rake line 118 | print hp.output() 119 | p = 0 120 | if args.dbout: 121 | db = hp.output(format="ANTELOPE", dbout=args.dbout) 122 | 123 | # Done, return HashPype and/or FocalMechPlotter for debugging 124 | return hp, p 125 | 126 | 127 | if __name__ == '__main__': 128 | import time 129 | t0 = time.time() 130 | ret = main() 131 | print time.time() - t0 132 | -------------------------------------------------------------------------------- /hashpy/tests/test_hashpype.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python 2 | # 3 | # test_hashpype.py -MCW 2013 4 | # 5 | 6 | import unittest 7 | from hashpy.hashpype import HashPype 8 | 9 | 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # 2 | # setup.py file for compiling HASH and installing hashpy 3 | # 4 | import sys 5 | import os 6 | from numpy.distutils.core import setup, Extension 7 | 8 | 9 | #--- libhashpy Fortran extension --------------------------------------------# 10 | # 11 | # Build extension from FORTRAN source of HASH subroutines 12 | # (based on the fucntion numpy.f2py.f2py2e.run_compile) 13 | srcdir = os.path.join('hashpy', 'src') 14 | srcf = ['fmamp_subs.f', 'fmech_subs.f', 'uncert_subs.f', 'util_subs.f', 15 | 'pol_subs.f', 'vel_subs.f', 'station_subs.f', 'vel_subs2.f'] 16 | src_list = [os.path.join(srcdir, src) for src in srcf] 17 | ext_args = {'sources': src_list} 18 | 19 | # 20 | # Use as a template for non-standard (non-distro) python installls... 21 | # 22 | def get_linker_args_for_virtualenv(virtualenv=None): 23 | """Return linker args relative to a virtual env""" 24 | np_inc = os.path.join('lib', 'python2.7', 'site-packages', 'numpy', 'core', 25 | 'include') 26 | inc_dirs = [os.path.join(virtualenv, inc) for inc in ('include', np_inc)] 27 | lib_dirs = [os.path.join(virtualenv, lib) for lib in ('lib',)] 28 | return {'include_dirs': inc_dirs, 29 | 'library_dirs': lib_dirs, 30 | } 31 | 32 | # Have to link against antelope libs if installing to Antelope python 33 | # 34 | # TODO: get python version/path automagically. 35 | if 'antelope' in sys.executable: 36 | python_folder = '/opt/antelope/python2.7.2-64' 37 | ANT_EXT_ARGS = get_linker_args_for_virtualenv(python_folder) 38 | ext_args.update(ANT_EXT_ARGS) 39 | #----------------------------------------------------------------------------# 40 | 41 | 42 | ### SETUP #################################################################### 43 | s_args = {'name' : 'HASHpy', 44 | 'version' : '0.6.0', 45 | 'description' : 'Routines for running HASH algorithms', 46 | 'author' : 'Mark Williams', 47 | 'url' : 'https//github.com/markcwill/hashpy', 48 | 'packages' : ['hashpy', 'hashpy.io', 'hashpy.plotting'], 49 | 'package_data' : {'hashpy': ['src/*.inc','src/Makefile','data/*', 50 | 'scripts/*', 'src/*.f']}, 51 | 'ext_modules' : [Extension('hashpy.libhashpy', **ext_args)], 52 | } 53 | ############################################################################## 54 | 55 | 56 | # hashpy.db -----------------------------------------------------------------# 57 | # TODO: OBSELETED - break out to separate module/package so hashpy can 58 | # stand alone. 59 | # 60 | # copy pf and bins from hashpy.db to antelope if available 61 | if 'ANTELOPE' in os.environ: 62 | ant_bin = os.path.join(os.environ['ANTELOPE'], 'bin') 63 | ant_pf = os.path.join(os.environ['ANTELOPE'], 'data', 'pf') 64 | s_args['data_files'] = [(ant_bin, ['hashpy/scripts/dbhash']), 65 | (ant_pf, ['hashpy/data/dbhash.pf'])] 66 | #----------------------------------------------------------------------------# 67 | 68 | 69 | setup(**s_args) 70 | --------------------------------------------------------------------------------