1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import logging
8from ..common import ldq
10logger = logging.getLogger('psq.cli.response')
12headline = 'Print instrument response information.'
15def indent(prefix, nfirst, n, message):
16 return '\n'.join(
17 prefix + ' ' * (nfirst if i == 0 else n) + line
18 for i, line in enumerate(message.splitlines()))
21def make_subparser(subparsers):
22 return subparsers.add_parser(
23 'response',
24 help=headline,
25 description=headline)
28def setup(parser):
29 parser.add_squirrel_selection_arguments()
30 parser.add_squirrel_query_arguments(without=['kinds'])
32 level_choices = ['response', 'stages']
34 parser.add_argument(
35 '--level',
36 choices=level_choices,
37 dest='level',
38 default='response',
39 help='Set level of detail to be printed. Choices: %s'
40 % ldq(level_choices))
42 parser.add_argument(
43 '--problems',
44 action='store_true',
45 dest='problems',
46 default=False,
47 help='Print attached warnings and error messages.')
49 parser.add_argument(
50 '--plot',
51 action='store_true',
52 dest='plot',
53 default=False,
54 help='Create Bode plot showing the responses.')
56 parser.add_argument(
57 '--fmin',
58 dest='fmin',
59 type=float,
60 default=0.01,
61 help='Minimum frequency [Hz], default: 0.01')
63 parser.add_argument(
64 '--fmax',
65 dest='fmax',
66 type=float,
67 default=100.,
68 help='Maximum frequency [Hz], default: 100')
70 parser.add_argument(
71 '--normalize',
72 dest='normalize',
73 action='store_true',
74 help='Normalize response to be 1 on flat part.')
76 parser.add_argument(
77 '--save',
78 dest='out_path',
79 help='Save figure to file.')
81 parser.add_argument(
82 '--dpi',
83 dest='dpi',
84 type=float,
85 default=100.,
86 help='DPI setting for pixel image output, default: 100')
88 parser.add_argument(
89 '--stages',
90 dest='stages',
91 metavar='START:STOP',
92 help='Show response of selected stages.')
94 input_quantity_choices = ['displacement', 'velocity', 'acceleration']
96 parser.add_argument(
97 '--input-quantity',
98 dest='input_quantity',
99 choices=input_quantity_choices,
100 metavar='QUANTITY',
101 help='Show converted response for given input quantity. choices: %s'
102 % ldq(input_quantity_choices))
104 parser.add_argument(
105 '--show-breakpoints',
106 dest='show_breakpoints',
107 action='store_true',
108 default=False,
109 help='Show breakpoints of pole-zero responses.')
111 parser.add_argument(
112 '--index-labels',
113 dest='index_labels',
114 action='store_true',
115 default=False,
116 help='Label graphs only by index and print details to terminal '
117 'to save space when many labels would be shown. Aggregate '
118 'identical responses under a common index.')
121def run(parser, args):
122 squirrel = args.make_squirrel()
124 stages = None
125 if args.stages:
126 stages = tuple(int(x) for x in args.stages.split(':', 1))
127 stages = stages[0]-1, stages[1]
129 data = []
130 for response in squirrel.get_responses(**args.squirrel_query):
131 print(response.summary)
132 if args.problems:
133 for level, message, _ in response.log:
134 print('! %s: %s' % (
135 level.capitalize(),
136 indent('!', 0, 5, message)))
138 if args.level == 'stages':
139 for stage in response.stages:
140 print(' %s' % stage.summary)
141 if args.problems:
142 for level, message, _ in stage.log:
143 print('! %s: %s' % (
144 level.capitalize(),
145 indent('!', 0, 7, message)))
147 data.append((
148 ', '.join([
149 str(response.codes),
150 response.str_time_span_short,
151 response.summary_log,
152 response.summary_quantities]),
153 response.get_effective(input_quantity=args.input_quantity)))
155 if args.plot:
156 if not data:
157 logger.warning('No response objects found.')
158 return
160 labels, resps = [list(x) for x in zip(*data)]
162 from pyrocko.plot.response import plot
163 plot(
164 resps,
165 fmin=args.fmin,
166 fmax=args.fmax,
167 nf=200,
168 normalize=args.normalize,
169 labels=labels,
170 filename=args.out_path,
171 dpi=args.dpi,
172 show_breakpoints=args.show_breakpoints,
173 separate_combined_labels='print' if args.index_labels else None)