Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/squirrel/tool/commands/response.py: 17%
58 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 06:59 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 06:59 +0000
1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Implementation of :app:`squirrel response`.
8'''
10import logging
12from ..common import ldq
13from pyrocko.squirrel.error import ToolError
15logger = logging.getLogger('psq.cli.response')
17headline = 'Print instrument response information.'
20def indent(prefix, nfirst, n, message):
21 return '\n'.join(
22 prefix + ' ' * (nfirst if i == 0 else n) + line
23 for i, line in enumerate(message.splitlines()))
26def make_subparser(subparsers):
27 return subparsers.add_parser(
28 'response',
29 help=headline,
30 description=headline)
33def setup(parser):
34 parser.add_squirrel_selection_arguments()
35 parser.add_squirrel_query_arguments(without=['kinds'])
37 level_choices = ['response', 'stages']
39 parser.add_argument(
40 '--level',
41 choices=level_choices,
42 dest='level',
43 default='response',
44 help='Set level of detail to be printed. Choices: %s'
45 % ldq(level_choices))
47 parser.add_argument(
48 '--problems',
49 action='store_true',
50 dest='problems',
51 default=False,
52 help='Print attached warnings and error messages.')
54 parser.add_argument(
55 '--plot',
56 action='store_true',
57 dest='plot',
58 default=False,
59 help='Create Bode plot showing the responses.')
61 parser.add_argument(
62 '--fmin',
63 dest='fmin',
64 type=float,
65 default=0.01,
66 help='Minimum frequency [Hz], default: 0.01')
68 parser.add_argument(
69 '--fmax',
70 dest='fmax',
71 type=float,
72 default=100.,
73 help='Maximum frequency [Hz], default: 100')
75 parser.add_argument(
76 '--normalize',
77 dest='normalize',
78 action='store_true',
79 help='Normalize response to be 1 on flat part.')
81 parser.add_argument(
82 '--save',
83 dest='out_path',
84 help='Save figure to file.')
86 parser.add_argument(
87 '--dpi',
88 dest='dpi',
89 type=float,
90 default=100.,
91 help='DPI setting for pixel image output, default: 100')
93 parser.add_argument(
94 '--stages',
95 dest='stages',
96 metavar='START:STOP',
97 help='Show response of selected stages. Indexing is Python style: '
98 'count starts at zero, negative values count from the end.')
100 input_quantity_choices = ['displacement', 'velocity', 'acceleration']
102 parser.add_argument(
103 '--input-quantity',
104 dest='input_quantity',
105 choices=input_quantity_choices,
106 metavar='QUANTITY',
107 help='Show converted response for given input quantity. choices: %s'
108 % ldq(input_quantity_choices))
110 parser.add_argument(
111 '--show-breakpoints',
112 dest='show_breakpoints',
113 action='store_true',
114 default=False,
115 help='Show breakpoints of pole-zero responses.')
117 parser.add_argument(
118 '--index-labels',
119 dest='index_labels',
120 action='store_true',
121 default=False,
122 help='Label graphs only by index and print details to terminal '
123 'to save space when many labels would be shown. Aggregate '
124 'identical responses under a common index.')
127def run(parser, args):
128 squirrel = args.make_squirrel()
130 stages = (None, None)
131 if args.stages:
132 words = args.stages.split(':')
133 try:
134 if len(words) == 1:
135 stages = (int(words[0]), int(words[0])+1)
136 elif len(words) == 2:
137 stages = tuple(int(word) if word else None for word in words)
138 else:
139 raise ValueError()
141 except ValueError:
142 raise ToolError('Invalid --stages argument.')
144 data = []
145 for response in squirrel.get_responses(**args.squirrel_query):
146 print(response.summary)
147 if args.problems:
148 for level, message, _ in response.log:
149 print('! %s: %s' % (
150 level.capitalize(),
151 indent('!', 0, 5, message)))
153 if args.level == 'stages':
154 for stage in response.stages[slice(*stages)]:
155 print(' %s' % stage.summary)
156 if args.problems:
157 for level, message, _ in stage.log:
158 print('! %s: %s' % (
159 level.capitalize(),
160 indent('!', 0, 7, message)))
162 data.append((
163 ', '.join([
164 str(response.codes),
165 response.str_time_span_short,
166 response.summary_log,
167 response.summary_quantities]),
168 response.get_effective(
169 input_quantity=args.input_quantity,
170 stages=stages)))
172 if args.plot:
173 if not data:
174 logger.warning('No response objects found.')
175 return
177 labels, resps = [list(x) for x in zip(*data)]
179 from pyrocko.plot.response import plot
180 plot(
181 resps,
182 fmin=args.fmin,
183 fmax=args.fmax,
184 nf=200,
185 normalize=args.normalize,
186 labels=labels,
187 filename=args.out_path,
188 dpi=args.dpi,
189 show_breakpoints=args.show_breakpoints,
190 separate_combined_labels='print' if args.index_labels else None)