1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6import logging 

7 

8from ..common import ldq 

9 

10logger = logging.getLogger('psq.cli.response') 

11 

12headline = 'Print instrument response information.' 

13 

14 

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())) 

19 

20 

21def make_subparser(subparsers): 

22 return subparsers.add_parser( 

23 'response', 

24 help=headline, 

25 description=headline) 

26 

27 

28def setup(parser): 

29 parser.add_squirrel_selection_arguments() 

30 parser.add_squirrel_query_arguments(without=['kinds']) 

31 

32 level_choices = ['response', 'stages'] 

33 

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)) 

41 

42 parser.add_argument( 

43 '--problems', 

44 action='store_true', 

45 dest='problems', 

46 default=False, 

47 help='Print attached warnings and error messages.') 

48 

49 parser.add_argument( 

50 '--plot', 

51 action='store_true', 

52 dest='plot', 

53 default=False, 

54 help='Create Bode plot showing the responses.') 

55 

56 parser.add_argument( 

57 '--fmin', 

58 dest='fmin', 

59 type=float, 

60 default=0.01, 

61 help='Minimum frequency [Hz], default: 0.01') 

62 

63 parser.add_argument( 

64 '--fmax', 

65 dest='fmax', 

66 type=float, 

67 default=100., 

68 help='Maximum frequency [Hz], default: 100') 

69 

70 parser.add_argument( 

71 '--normalize', 

72 dest='normalize', 

73 action='store_true', 

74 help='Normalize response to be 1 on flat part.') 

75 

76 parser.add_argument( 

77 '--save', 

78 dest='out_path', 

79 help='Save figure to file.') 

80 

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') 

87 

88 parser.add_argument( 

89 '--stages', 

90 dest='stages', 

91 metavar='START:STOP', 

92 help='Show response of selected stages.') 

93 

94 input_quantity_choices = ['displacement', 'velocity', 'acceleration'] 

95 

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)) 

103 

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.') 

110 

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.') 

119 

120 

121def run(parser, args): 

122 squirrel = args.make_squirrel() 

123 

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] 

128 

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))) 

137 

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))) 

146 

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))) 

154 

155 if args.plot: 

156 if not data: 

157 logger.warning('No response objects found.') 

158 return 

159 

160 labels, resps = [list(x) for x in zip(*data)] 

161 

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)