import { Component , OnInit , OnDestroy } from '@angular/core' ; import { MatDialog } from '@angular/material/dialog' ; import { Sort } from '@angular/material/sort' ; import { Subscription } from 'rxjs' ; import { EventService } from '@core/event.service' ; import { QuakemlService } from '@core/quakeml.service' ; import { DownloadDialogComponent } from '@shared/download-dialog/download-dialog.component' ; import { toArray } from '../../to-array' ; import { Quakeml } from '../../quakeml' ; /**
 * Phase data tab contents for the Origin Module
 */ @ Component ( { selector : 'origin-phase' , styleUrls : [ './phase.component.scss' ] , templateUrl : './phase.component.html' } ) export class PhaseComponent implements OnInit , OnDestroy { columnsToDisplay = [ 'channel' , 'distance' , 'azimuth' , 'phase' , 'time' , 'status' , 'timeResidual' , 'timeWeight' ] ; columnTitles = { azimuth : 'Azimuth' , channel : 'Channel' , distance : 'Distance' , phase : 'Phase' , status : 'Status' , time : 'Arrival Time' , timeResidual : 'Residual' , timeWeight : 'Weight' } ; /** phases parsed from quakeml. */ phases : Array < any > ; /** phases after sorting. */ sortedPhases : Array < any > ; /** subscriptions */ subscription : Subscription = new Subscription ( ) ; constructor ( public dialog , public eventService , public quakemlService ) { } param a param b param isAsc compare ( a , b , isAsc ) { return ( a < b ? - 1 : 1 ) * ( isAsc ? 1 : - 1 ) ; } ngOnDestroy ( ) { this . subscription . unsubscribe ( ) ; } ngOnInit ( ) { this . subscription . add ( this . eventService . product$ . subscribe ( product => { this . onProduct ( product ) ; } ) ) ; this . subscription . add ( this . quakemlService . quakeml$ . subscribe ( quakeml => { this . onQuakeml ( quakeml ) ; } ) ) ; } /**
     * Called when download button is clicked.
     *
     * Show a download dialog with tab-separated value content.
     */ onDownload ( ) { const header = this . columnsToDisplay . map ( c => { return this . columnTitles [ c ] ; } ) . join ( '\t' ) ; const lines = this . sortedPhases . map ( phase => { return this . columnsToDisplay . map ( c => { return phase [ c ] ; } ) . join ( '\t' ) ; } ) ; this . dialog . open ( DownloadDialogComponent , { data : { content : header + '\n' + lines . join ( '\n' ) , message : 'Copy then paste into a spreadsheet application' , title : 'Download Phase Arrival Times' } } ) ; } param product onProduct ( product ) { this . quakemlService . getQuakeml ( product ) ; } param quakeml onQuakeml ( quakeml ) { const phases = [ ] ; if ( quakeml === null ) { this . phases = phases ; return ; } const event = quakeml . events [ 0 ] ; const origin = event . preferredOrigin ( ) ; const originTime = Quakeml . parseTime ( origin . time . value ) ; toArray ( origin . arrival ) . forEach ( arrival => { let pick ; let time ; let timeRelative ; try { pick = event . picks [ arrival . pickID ] ; time = Quakeml . parseTime ( pick . time . value ) ; } catch ( e ) { pick = { } ; time = null ; timeRelative = null ; } if ( time ) { timeRelative = ( time . getTime ( ) - originTime . getTime ( ) ) / 1000 ; time = time . toISOString ( ) ; } phases . push ( { arrivalPublicID : arrival . publicID , azimuth : arrival . azimuth , channel : Quakeml . formatWaveformID ( pick . waveformID ) , distance : arrival . distance , phase : arrival . phase , pickPublicId : pick . publicID , status : pick . evaluationMode , time : time , timeRelative : timeRelative , timeResidual : arrival . timeResidual , timeWeight : arrival . timeWeight } ) ; } ) ; this . phases = phases ; this . sortPhases ( null ) ; } param sort sortPhases ( sort ) { const phases = this . phases . slice ( ) ; if ( ! sort || ! sort . active || sort . direction === '' ) { this . sortedPhases = phases ; return ; } phases . sort ( ( a , b ) => { const isAsc = sort . direction === 'asc' ; switch ( sort . active ) { case 'azimuth' : return this . compare ( + a . azimuth , + b . azimuth , isAsc ) ; case 'channel' : return this . compare ( a . channel , b . channel , isAsc ) ; case 'distance' : return this . compare ( + a . distance , + b . distance , isAsc ) ; case 'phase' : return this . compare ( a . phase , b . phase , isAsc ) ; case 'status' : return this . compare ( a . status , b . status , isAsc ) ; case 'time' : return this . compare ( a . time , b . time , isAsc ) ; case 'timeResidual' : return this . compare ( + a . timeResidual , + b . timeResidual , isAsc ) ; case 'timeWeight' : return this . compare ( + a . timeWeight , + b . timeWeight , isAsc ) ; default : return 0 ; } } ) ; this . sortedPhases = phases ; } }