Coverage for /home/andrew/Documents/Research/gwent/gwent/snrplot.py : 85%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import numpy as np
2import matplotlib as mpl
3import matplotlib.pyplot as plt
4import matplotlib.colors as colors
5from scipy.constants import golden_ratio
7import astropy.units as u
8from astropy.cosmology import z_at_value
9from astropy.cosmology import WMAP9 as cosmo
12def Plot_SNR(
13 var_x,
14 sample_x,
15 var_y,
16 sample_y,
17 SNRMatrix,
18 fig=None,
19 ax=None,
20 display=True,
21 return_plt=False,
22 dl_axis=False,
23 lb_axis=False,
24 smooth_contours=False,
25 cfill=True,
26 display_cbar=True,
27 x_axis_label=True,
28 y_axis_label=True,
29 x_axis_line=None,
30 y_axis_line=None,
31 logLevels_min=-1.0,
32 logLevels_max=0.0,
33 hspace=0.15,
34 wspace=0.1,
35 contour_kwargs={},
36 contourf_kwargs={},
37 xticklabels_kwargs={},
38 xlabels_kwargs={},
39 xline_kwargs={},
40 yticklabels_kwargs={},
41 ylabels_kwargs={},
42 yline_kwargs={},
43):
44 """Plots the SNR contours from calcSNR
46 Parameters
47 ----------
48 var_x : str
49 x-axis variable
50 sample_x : array
51 samples at which SNRMatrix was calculated corresponding to the x-axis variable
52 var_y : str
53 y-axis variable
54 sample_y : array
55 samples at which SNRMatrix was calculated corresponding to the y-axis variable
56 SNRMatrix : array-like
57 the matrix at which the SNR was calculated corresponding to the particular x and y-axis variable choices
59 fig : object, optional
60 matplotlib figure object on which to collate the individual plots
61 ax : object, optional
62 matplotlib axes object on which to plot the individual plot
63 display : bool, optional
64 Option to turn off display if saving multiple plots to a file
65 return_plt : bool, optional
66 Option to return fig and ax
67 dl_axis : bool, optional
68 Option to turn on the right hand side labels of luminosity distance
69 lb_axis : bool, optional
70 Option to turn on the right hand side labels of lookback time
71 smooth_contours : bool, optional
72 Option to have contours appear smooth instead of tiered (depending on sample size the edges appear boxey).
73 cfill : bool, optional
74 Option to use filled contours or not, default is True
75 display_cbar : bool, optional
76 Option to display the colorbar on the axes object
77 x_axis_label : bool, optional
78 Option to display the x axis label
79 y_axis_label : bool, optional
80 Option to display the y axis label
81 x_axis_line : int,float, optional
82 Option to display a line on the x axis if not None
83 y_axis_line : int,float, optional
84 Option to display a line on the y axis if not None
85 logLevels_min : float, optional
86 Sets the minimum log level of the colorbar, default is -1.0 which set the minimum to the log minimum of the given SNRMatrix
87 logLevels_max : float, optional
88 Sets the maximum log level of the colorbar, default is 0.0, which sets the maximum to the log maximum value of the given SNRMatrix
89 hspace : float, optional
90 Sets the vertical space between axes objects, default is 0.15
91 wspace : float, optional
92 Sets the horizontal space between axes objects, default is 0.1
93 contour_kwargs : dict, optional
94 Sets additional kwargs taken by contour in matplotlib
95 contourf_kwargs : dict, optional
96 Sets additional kwargs taken by contourf in matplotlib
97 xticklabels_kwargs : dict, optional
98 Sets additional kwargs taken by xticklabel in matplotlib
99 xlabels_kwargs= : dict, optional
100 Sets additional kwargs taken by xlabel in matplotlib
101 xline_kwargs : dict, optional
102 Sets additional kwargs taken by ax.axvline in matplotlib
103 yticklabels_kwargs : dict, optional
104 Sets additional kwargs taken by yticklabel in matplotlib
105 ylabels_kwargs : dict, optional
106 Sets additional kwargs taken by ylabel in matplotlib
107 yline_kwargs : dict, optional
108 Sets additional kwargs taken by ax.axhline in matplotlib
110 """
111 if fig is not None:
112 if ax is not None:
113 pass
114 else:
115 fig, ax = plt.subplots()
116 else:
117 fig, ax = plt.subplots()
119 if "colors" not in contour_kwargs.keys() and "cmap" not in contour_kwargs.keys():
120 contour_kwargs["colors"] = "k"
121 if "linewidths" not in contour_kwargs.keys():
122 contour_kwargs["linewidths"] = 2.0
124 if "cmap" not in contourf_kwargs.keys():
125 contourf_kwargs["cmap"] = "viridis"
127 logSNR = np.log10(SNRMatrix)
128 if logLevels_min == -1.0:
129 logLevels_min = np.log10(np.array([1.0]))
130 if logLevels_max == 0.0:
131 logLevels_max = np.ceil(np.amax(logSNR))
132 if logLevels_max < logLevels_min:
133 raise ValueError("All SNRs are lower than 5.")
135 logLevels_add = np.log10(np.array([3.0, 10.0, 31.0]))
136 print_logLevels = np.concatenate(
137 (logLevels_min, logLevels_add, np.arange(2.0, logLevels_max + 1.0))
138 )
140 logLevels = print_logLevels
142 ylabel_min = min(sample_y)
143 ylabel_max = max(sample_y)
144 xlabel_min = min(sample_x)
145 xlabel_max = max(sample_x)
147 # Set whether log or linearly spaced axes
148 if xlabel_max < 0.0 or xlabel_min < 0.0 or var_x in ["n_p", "T_obs"]:
149 xaxis_type = "lin"
150 step_size = int(xlabel_max - xlabel_min + 1)
151 x_labels = np.linspace(xlabel_min, xlabel_max, step_size)
152 else:
153 x_log_range = np.log10(xlabel_max) - np.log10(xlabel_min)
154 if x_log_range >= 2.0:
155 xaxis_type = "log"
156 step_size = int(np.log10(xlabel_max) - np.log10(xlabel_min) + 1)
157 x_labels = np.logspace(
158 np.log10(xlabel_min), np.log10(xlabel_max), step_size
159 )
160 else:
161 xaxis_type = "lin"
162 x_scale = 10 ** round(np.log10(xlabel_min))
163 x_labels = (
164 np.arange(
165 round(xlabel_min / x_scale), round(xlabel_max / x_scale) + 1, 1
166 )
167 * x_scale
168 )
169 if x_labels[0] < xlabel_min:
170 x_labels[0] = xlabel_min
171 if x_labels[-1] > xlabel_max:
172 x_labels[-1] = xlabel_max
174 if ylabel_max < 0.0 or ylabel_min < 0.0 or var_y in ["n_p", "T_obs"]:
175 yaxis_type = "lin"
176 step_size = int(ylabel_max - ylabel_min + 1)
177 y_labels = np.linspace(ylabel_min, ylabel_max, step_size)
178 else:
179 y_log_range = np.log10(ylabel_max) - np.log10(ylabel_min)
180 if y_log_range >= 2.0:
181 yaxis_type = "log"
182 step_size = int(np.log10(ylabel_max) - np.log10(ylabel_min) + 1)
183 y_labels = np.logspace(
184 np.log10(ylabel_min), np.log10(ylabel_max), step_size
185 )
186 else:
187 yaxis_type = "lin"
188 y_scale = 10 ** round(np.log10(ylabel_min))
189 y_labels = (
190 np.arange(
191 round(ylabel_min / y_scale), round(ylabel_max / y_scale) + 1, 1
192 )
193 * y_scale
194 )
195 if y_labels[0] < ylabel_min:
196 y_labels[0] = ylabel_min
197 if y_labels[-1] > ylabel_max:
198 y_labels[-1] = ylabel_max
200 # Set axis scales based on what data sampling we used
201 if yaxis_type == "lin" and xaxis_type == "log":
202 if cfill == False:
203 CS1 = ax.contour(
204 np.log10(sample_x), sample_y, logSNR, print_logLevels, **contour_kwargs
205 )
206 else:
207 if smooth_contours:
208 cmap = mpl.cm.get_cmap(name=contourf_kwargs["cmap"])
209 cmap.set_under(color="white")
210 CS1 = ax.imshow(
211 logSNR,
212 extent=[
213 np.log10(xlabel_min),
214 np.log10(xlabel_max),
215 ylabel_min,
216 ylabel_max,
217 ],
218 vmin=logLevels_min,
219 vmax=logLevels_max,
220 origin="lower",
221 aspect="auto",
222 cmap=cmap,
223 )
224 else:
225 CS1 = ax.contourf(
226 np.log10(sample_x), sample_y, logSNR, logLevels, **contourf_kwargs
227 )
228 ax.contour(
229 np.log10(sample_x), sample_y, logSNR, print_logLevels, **contour_kwargs
230 )
231 ax.set_xlim(np.log10(xlabel_min), np.log10(xlabel_max))
232 ax.set_ylim(ylabel_min, ylabel_max)
234 elif yaxis_type == "log" and xaxis_type == "lin":
235 if cfill == False:
236 CS1 = ax.contour(
237 sample_x, np.log10(sample_y), logSNR, print_logLevels, **contour_kwargs
238 )
239 else:
240 if smooth_contours:
241 cmap = mpl.cm.get_cmap(name=contourf_kwargs["cmap"])
242 cmap.set_under(color="white")
243 CS1 = ax.imshow(
244 logSNR,
245 extent=[
246 xlabel_min,
247 xlabel_max,
248 np.log10(ylabel_min),
249 np.log10(ylabel_max),
250 ],
251 vmin=logLevels_min,
252 vmax=logLevels_max,
253 origin="lower",
254 aspect="auto",
255 cmap=cmap,
256 )
257 else:
258 CS1 = ax.contourf(
259 sample_x, np.log10(sample_y), logSNR, logLevels, **contourf_kwargs
260 )
261 ax.contour(
262 sample_x, np.log10(sample_y), logSNR, print_logLevels, **contour_kwargs
263 )
264 ax.set_xlim(xlabel_min, xlabel_max)
265 ax.set_ylim(np.log10(ylabel_min), np.log10(ylabel_max))
266 elif yaxis_type == "lin" and xaxis_type == "lin":
267 if cfill == False:
268 CS1 = ax.contour(
269 sample_x, sample_y, logSNR, print_logLevels, **contour_kwargs
270 )
271 else:
272 if smooth_contours:
273 cmap = mpl.cm.get_cmap(name=contourf_kwargs["cmap"])
274 cmap.set_under(color="white")
275 CS1 = ax.imshow(
276 logSNR,
277 extent=[xlabel_min, xlabel_max, ylabel_min, ylabel_max],
278 vmin=logLevels_min,
279 vmax=logLevels_max,
280 origin="lower",
281 aspect="auto",
282 cmap=cmap,
283 )
284 else:
285 CS1 = ax.contourf(
286 sample_x, sample_y, logSNR, logLevels, **contourf_kwargs
287 )
288 ax.contour(sample_x, sample_y, logSNR, print_logLevels, **contour_kwargs)
289 ax.set_xlim(xlabel_min, xlabel_max)
290 ax.set_ylim(ylabel_min, ylabel_max)
291 else:
292 if cfill == False:
293 CS1 = ax.contour(
294 np.log10(sample_x),
295 np.log10(sample_y),
296 logSNR,
297 print_logLevels,
298 **contour_kwargs
299 )
300 else:
301 if smooth_contours:
302 cmap = mpl.cm.get_cmap(name=contourf_kwargs["cmap"])
303 cmap.set_under(color="white")
304 CS1 = ax.imshow(
305 logSNR,
306 extent=[
307 np.log10(xlabel_min),
308 np.log10(xlabel_max),
309 np.log10(ylabel_min),
310 np.log10(ylabel_max),
311 ],
312 vmin=logLevels_min,
313 vmax=logLevels_max,
314 origin="lower",
315 aspect="auto",
316 cmap=cmap,
317 interpolation="None",
318 )
319 else:
320 CS1 = ax.contourf(
321 np.log10(sample_x),
322 np.log10(sample_y),
323 logSNR,
324 logLevels,
325 **contourf_kwargs
326 )
327 ax.contour(
328 np.log10(sample_x),
329 np.log10(sample_y),
330 logSNR,
331 print_logLevels,
332 **contour_kwargs
333 )
334 ax.set_xlim(np.log10(xlabel_min), np.log10(xlabel_max))
335 ax.set_ylim(np.log10(ylabel_min), np.log10(ylabel_max))
337 Get_Axes_Labels(
338 ax,
339 "x",
340 var_x,
341 xaxis_type,
342 x_labels,
343 x_axis_line,
344 xlabels_kwargs,
345 xticklabels_kwargs,
346 xline_kwargs,
347 )
348 Get_Axes_Labels(
349 ax,
350 "y",
351 var_y,
352 yaxis_type,
353 y_labels,
354 y_axis_line,
355 ylabels_kwargs,
356 yticklabels_kwargs,
357 yline_kwargs,
358 )
360 if not x_axis_label:
361 ax.set_xticklabels("")
362 ax.set_xlabel("")
363 if not y_axis_label:
364 ax.set_yticklabels("")
365 ax.set_ylabel("")
367 # If true, display luminosity distance on right side of plot
368 if dl_axis:
369 if var_y != "z":
370 raise ValueError(
371 "Sorry, we can only plot luminosity distance when redshift is on the y axis."
372 )
374 # Set other side y-axis for luminosity distance scalings
375 ax2 = ax.twinx()
376 # Set axis scales based on what data sampling we used
377 if yaxis_type == "lin" and xaxis_type == "log":
378 ax2.contour(
379 np.log10(sample_x), sample_y, logSNR, print_logLevels, **contour_kwargs
380 )
381 elif yaxis_type == "log" and xaxis_type == "lin":
382 ax2.contour(
383 sample_x, np.log10(sample_y), logSNR, print_logLevels, **contour_kwargs
384 )
385 else:
386 ax2.contour(
387 np.log10(sample_x),
388 np.log10(sample_y),
389 logSNR,
390 print_logLevels,
391 **contour_kwargs
392 )
394 dists_min = cosmo.luminosity_distance(ylabel_min).to("Gpc")
395 dists_min = np.ceil(np.log10(dists_min.value))
396 dists_max = cosmo.luminosity_distance(ylabel_max).to("Gpc")
397 dists_max = np.ceil(np.log10(dists_max.value))
398 dists = np.arange(dists_min, dists_max)
399 dists = 10 ** dists * u.Gpc
401 distticks = [z_at_value(cosmo.luminosity_distance, dist) for dist in dists]
402 # Set other side y-axis for lookback time scalings
403 ax2.set_yticks(np.log10(distticks))
404 # ax2.set_yticklabels(['%f' %dist for dist in distticks],fontsize = axissize)
405 ax2.set_yticklabels(
406 [
407 r"$10^{%i}$" % np.log10(dist)
408 if np.abs(int(np.log10(dist))) > 1
409 else "{:g}".format(dist)
410 for dist in dists.value
411 ]
412 )
413 ax2.set_ylabel(r"$D_{L}$ [Gpc]")
415 # cbar = fig.colorbar(CS1,cax=cbar_ax,ax=(ax,ax2),pad=0.01,ticks=print_logLevels)
416 elif lb_axis:
417 if var_y != "z":
418 raise ValueError(
419 "Sorry, we can only plot lookback time when redshift is on the y axis."
420 )
421 # Set other side y-axis for lookback time scalings
422 ax2 = ax.twinx()
423 # Set axis scales based on what data sampling we used
424 if yaxis_type == "lin" and xaxis_type == "log":
425 ax2.contour(
426 np.log10(sample_x), sample_y, logSNR, print_logLevels, **contour_kwargs
427 )
428 elif yaxis_type == "log" and xaxis_type == "lin":
429 ax2.contour(
430 sample_x, np.log10(sample_y), logSNR, print_logLevels, **contour_kwargs
431 )
432 else:
433 ax2.contour(
434 np.log10(sample_x),
435 np.log10(sample_y),
436 logSNR,
437 print_logLevels,
438 **contour_kwargs
439 )
441 ages1 = np.array([13.5, 13, 10, 5, 1]) * u.Gyr
442 ages2 = np.array([500, 100, 10, 1]) * u.Myr
443 ages2 = ages2.to("Gyr")
444 ages = np.hstack((ages1.value, ages2.value))
445 ages = ages * u.Gyr
446 ageticks = [z_at_value(cosmo.age, age) for age in ages]
448 # Set axes limits
449 ax2.set_yticks(np.log10(ageticks))
450 ax2.set_yticklabels(["{:g}".format(age) for age in ages.value])
451 ax2.set_ylabel(r"$t_{\rm cosmic}$ [Gyr]")
452 ax2.yaxis.set_label_coords(1.2, 0.5)
454 if display_cbar:
455 if lb_axis or dl_axis:
456 fig.subplots_adjust(right=0.8)
457 cbar_ax = fig.add_axes([0.9, 0.15, 0.025, 0.7])
458 # Make colorbar
459 if cfill == False:
460 # Make colorbar
461 norm = colors.Normalize(vmin=logLevels_min, vmax=logLevels_max)
462 tick_levels = np.linspace(
463 float(logLevels_min), logLevels_max, len(print_logLevels)
464 )
465 cbar = mpl.colorbar.ColorbarBase(
466 cbar_ax,
467 ax=(ax, ax2),
468 pad=0.01,
469 cmap=CS1.cmap,
470 norm=norm,
471 boundaries=tick_levels,
472 ticks=tick_levels,
473 spacing="proportional",
474 )
475 else:
476 cbar = fig.colorbar(CS1, cax=cbar_ax, ax=(ax, ax2), pad=0.01)
477 else:
478 fig.subplots_adjust(right=0.8)
479 cbar_ax = fig.add_axes([0.82, 0.15, 0.025, 0.7])
480 if cfill == False:
481 # Make colorbar
482 norm = colors.Normalize(vmin=logLevels_min, vmax=logLevels_max)
483 tick_levels = np.linspace(
484 float(logLevels_min), logLevels_max, len(print_logLevels)
485 )
486 cbar = mpl.colorbar.ColorbarBase(
487 cbar_ax,
488 cmap=CS1.cmap,
489 norm=norm,
490 boundaries=tick_levels,
491 ticks=tick_levels,
492 spacing="proportional",
493 )
494 else:
495 # Make colorbar
496 cbar = fig.colorbar(CS1, cax=cbar_ax, ticks=print_logLevels)
498 cbar.set_label(r"SNR")
499 cbar.ax.set_yticklabels(
500 [
501 r"$10^{%i}$" % x if int(x) > 1 else r"$%i$" % (10 ** x)
502 for x in print_logLevels
503 ],
504 **yticklabels_kwargs
505 )
507 if display:
508 # fig.tight_layout()
509 fig.subplots_adjust(hspace=hspace, wspace=wspace)
510 plt.show()
512 if return_plt:
513 return fig, ax
516def Get_Axes_Labels(
517 ax,
518 var_axis,
519 var,
520 var_scale,
521 orig_labels,
522 line_val,
523 label_kwargs,
524 tick_label_kwargs,
525 line_kwargs,
526):
527 """Gives paper plot labels for given axis
529 Parameters
530 ----------
531 ax: object
532 The current axes object
533 var_axis: str
534 The axis to change labels and ticks, can either be 'y' or 'x'
535 var: str
536 The variable to label
537 orig_labels: list,np.ndarray
538 The original labels for the particular axis, may be updated depending on parameter
539 line_val: int,float
540 Value of line plotted on var_axis if not None. Assumed to be non-log10 value
541 label_kwargs: dict
542 The dictionary adjusting the particular axis' label kwargs
543 tick_label_kwargs: dict
544 The dictionary adjusting the particular axis' tick label kwargs
545 line_kwargs: dict
546 The dictionary associated with the line displayed on var_axis
548 """
550 # Set axes labels and whether log or linearly spaced
551 if var_axis not in ["y", "x"]:
552 raise ValueError("var_axis can only by x or y")
554 ax_dict = {}
556 if var == "M":
557 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
558 ax_dict[var_axis + "label"] = r"$M_{\mathrm{tot}}~[M_{\odot}]$"
559 ax_dict[var_axis + "ticklabels"] = [
560 r"$10^{%i}$" % x if int(x) > 1 else r"$%i$" % (10 ** x)
561 for x in np.log10(orig_labels)
562 ]
563 elif var == "q":
564 new_labels = orig_labels[::2]
565 ax_dict[var_axis + "ticks"] = new_labels
566 ax_dict[var_axis + "label"] = r"$\mathrm{Mass~Ratio}~q$"
567 ax_dict[var_axis + "ticklabels"] = [r"$%i$" % int(x) for x in new_labels]
568 elif var == "z":
569 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
570 ax_dict[var_axis + "label"] = r"$\mathrm{Redshift}~z$"
571 ax_dict[var_axis + "ticklabels"] = [
572 x if int(x) < 1 else int(x) for x in orig_labels
573 ]
574 elif var in ["chi1", "chi2"]:
575 new_labels = (
576 np.arange(round(min(orig_labels) * 10), round(max(orig_labels) * 10) + 1, 1)
577 / 10
578 )
579 new_labels = new_labels[::2]
580 ax_dict[var_axis + "ticks"] = new_labels
581 ax_dict[var_axis + "label"] = r"$\mathrm{Spin}~\chi_{i}$"
582 ax_dict[var_axis + "ticklabels"] = [r"$%.1f$" % x for x in new_labels]
583 elif var == "L":
584 # Proposed Value = 2.5Gm: L3 LISA
585 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
586 ax_dict[var_axis + "label"] = r"Arm Length [m]"
587 ax_dict[var_axis + "ticklabels"] = [
588 r"$10^{%i}$" % x if int(x) > 1 else r"$%i$" % (10 ** x)
589 for x in np.log10(orig_labels)
590 ]
591 elif var == "A_acc":
592 # Proposed Value = 3x10^{-15}: L3 LISA
593 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
594 ax_dict[var_axis + "label"] = r"$A_{\mathrm{acc}} [\mathrm{m~s^{-2}}]$"
595 ax_dict[var_axis + "ticklabels"] = [
596 r"$10^{%.0f}$" % x for x in np.log10(orig_labels)
597 ]
598 elif var == "A_IFO":
599 # Proposed Value = 10^{-12}: L3 LISA
600 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
601 ax_dict[var_axis + "label"] = r"$A_{\mathrm{IFO}}$ [m]"
602 ax_dict[var_axis + "ticklabels"] = [
603 r"$10^{%.0f}$" % x for x in np.log10(orig_labels)
604 ]
605 elif var == "f_acc_break_low":
606 # Proposed Value = 0.4mHz: L3 LISA
607 scale = 10 ** round(np.log10(min(orig_labels)))
608 new_labels = (
609 np.arange(
610 round(min(orig_labels) / scale), round(max(orig_labels) / scale) + 1, 1
611 )
612 * scale
613 )
614 ax_dict[var_axis + "ticks"] = new_labels
615 ax_dict[var_axis + "label"] = r"$f_{\mathrm{acc,low}}$ [mHz]"
616 ax_dict[var_axis + "ticklabels"] = [r"$%.1f$" % x for x in new_labels * 1e3]
617 elif var == "f_acc_break_high":
618 # Proposed Value = 8mHz: L3 LISA
619 scale = 10 ** round(np.log10(min(orig_labels)))
620 new_labels = (
621 np.arange(
622 round(min(orig_labels) / scale), round(max(orig_labels) / scale) + 1, 1
623 )
624 * scale
625 )
626 ax_dict[var_axis + "ticks"] = new_labels
627 ax_dict[var_axis + "label"] = r"$f_{\mathrm{acc,high}}$ [mHz]"
628 ax_dict[var_axis + "ticklabels"] = [r"$%.1f$" % x for x in new_labels * 1e3]
629 elif var == "f_IFO_break":
630 # Proposed Value = 2mHz: L3 LISA
631 scale = 10 ** round(np.log10(min(orig_labels)))
632 new_labels = (
633 np.arange(
634 round(min(orig_labels) / scale), round(max(orig_labels) / scale) + 1, 1
635 )
636 * scale
637 )
638 ax_dict[var_axis + "ticks"] = new_labels
639 ax_dict[var_axis + "label"] = r"$f_{\mathrm{IFO,break}}$ [mHz]"
640 ax_dict[var_axis + "ticklabels"] = [r"$%.1f$" % x for x in new_labels * 1e3]
641 elif var == "n_p":
642 sample_range = max(orig_labels) - min(orig_labels)
643 sample_rate = max(2, int(sample_range / 10))
644 new_labels = orig_labels[::sample_rate]
645 ax_dict[var_axis + "ticks"] = new_labels
646 ax_dict[var_axis + "label"] = r"$\mathrm{Number~of~Pulsars}$"
647 ax_dict[var_axis + "ticklabels"] = [r"$%i$" % int(x) for x in new_labels]
648 elif var == "cadence":
649 new_labels = np.arange(round(min(orig_labels)), round(max(orig_labels)) + 1, 5)
650 ax_dict[var_axis + "ticks"] = new_labels
651 ax_dict[
652 var_axis + "label"
653 ] = r"$\mathrm{Observation~Cadence}$ $[\mathrm{yr}^{-1}]$"
654 ax_dict[var_axis + "ticklabels"] = [r"$%i$" % int(x) for x in new_labels]
655 elif var == "sigma":
656 scale = 10 ** round(np.log10(min(orig_labels)))
657 new_labels = (
658 np.arange(
659 round(min(orig_labels) / scale), round(max(orig_labels) / scale) + 1, 1
660 )
661 * scale
662 )
663 ax_dict[var_axis + "ticks"] = new_labels
664 ax_dict[var_axis + "label"] = r"TOA Error RMS [ns]"
665 ax_dict[var_axis + "ticklabels"] = [r"$%.0f$" % x for x in new_labels * 1e9]
666 elif var == "T_obs":
667 new_labels = orig_labels[::2]
668 ax_dict[var_axis + "ticks"] = new_labels
669 ax_dict[var_axis + "label"] = r"${\rm T_{obs}}$ [yr]"
670 ax_dict[var_axis + "ticklabels"] = [r"$%i$" % int(x) for x in new_labels]
671 elif var == "Infrastructure Length":
672 # Proposed Value = 3995: aLIGO, Voyager
673 # Proposed Value = 40000: CE1
674 if var_scale == "log":
675 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
676 ax_dict[var_axis + "label"] = r"Infrastructure Length [m]"
677 ax_dict[var_axis + "ticklabels"] = [
678 r"$10^{%.0f}$" % y if abs(int(y)) > 1 else r"$%.1f$" % (10 ** y)
679 for y in np.log10(orig_labels)
680 ]
681 elif var_scale == "lin":
682 ax_dict[var_axis + "ticks"] = orig_labels
683 ax_dict[var_axis + "label"] = r"Infrastructure Length [km]"
684 ax_dict[var_axis + "ticklabels"] = [
685 r"$%.1f$" % (x / 1e3) for x in orig_labels
686 ]
687 elif var == "Laser Power":
688 # Proposed Value = 125: aLIGO
689 # Proposed Value = 145: Voyager
690 # Proposed Value = 150: CE1
691 if var_scale == "log":
692 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
693 ax_dict[var_axis + "label"] = r"Laser Power [W]"
694 ax_dict[var_axis + "ticklabels"] = [
695 r"$10^{%.0f}$" % x if abs(int(x)) > 1 else r"$%.1f$" % (10 ** x)
696 for x in np.log10(orig_labels)
697 ]
698 elif var_scale == "lin":
699 ax_dict[var_axis + "ticks"] = orig_labels
700 ax_dict[var_axis + "label"] = r"Laser Power [W]"
701 ax_dict[var_axis + "ticklabels"] = [r"$%.1f$" % x for x in orig_labels]
702 elif var == "Seismic Gamma":
703 # Proposed Value = 0.8: aLIGO, Voyager, CE1
704 if var_scale == "log":
705 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
706 ax_dict[var_axis + "label"] = r"Seismic Gamma"
707 ax_dict[var_axis + "ticklabels"] = [
708 r"$10^{%.0f}$" % y if abs(int(y)) > 1 else r"$%.1f$" % (10 ** y)
709 for y in np.log10(orig_labels)
710 ]
711 elif var_scale == "lin":
712 ax_dict[var_axis + "ticks"] = orig_labels
713 ax_dict[var_axis + "label"] = r"Seismic Gamma"
714 ax_dict[var_axis + "ticklabels"] = [r"$%.1f$" % y for y in orig_labels]
715 elif var == "Materials Substrate Temp":
716 # Proposed Value = 295: aLIGO, CE1
717 # Proposed Value = 123: Voyager
718 if var_scale == "lin":
719 ax_dict[var_axis + "ticks"] = orig_labels
720 ax_dict[var_axis + "label"] = r"Mirror Substrate Temp [K]"
721 ax_dict[var_axis + "ticklabels"] = [
722 r"$%.1f \times 10^{%i}$" % (x / 10 ** int(np.log10(x)), np.log10(x))
723 if np.abs(int(np.log10(x))) > 1
724 else "{:g}".format(x)
725 for x in orig_labels
726 ]
727 elif var_scale == "log":
728 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
729 ax_dict[var_axis + "label"] = r"Mirror Substrate Temp [K]"
730 ax_dict[var_axis + "ticklabels"] = [
731 r"$10^{%.0f}$" % y if abs(int(y)) > 1 else r"$%.1f$" % (10 ** y)
732 for y in np.log10(orig_labels)
733 ]
734 else:
735 if var_scale == "lin":
736 ax_dict[var_axis + "ticks"] = orig_labels
737 ax_dict[var_axis + "label"] = str(var)
738 ax_dict[var_axis + "ticklabels"] = [
739 r"$%.1f \times 10^{%i}$" % (x / 10 ** int(np.log10(x)), np.log10(x))
740 if np.abs(int(np.log10(x))) > 1
741 else "{:g}".format(x)
742 for x in orig_labels
743 ]
744 elif var_scale == "log":
745 ax_dict[var_axis + "ticks"] = np.log10(orig_labels)
746 ax_dict[var_axis + "label"] = str(var)
747 ax_dict[var_axis + "ticklabels"] = [
748 r"$10^{%.0f}$" % y if abs(int(y)) > 1 else r"$%.1f$" % (10 ** y)
749 for y in np.log10(orig_labels)
750 ]
751 if line_val is not None:
752 if "linestyle" not in line_kwargs.keys():
753 line_kwargs["linestyle"] = "--"
754 if "color" not in line_kwargs.keys():
755 line_kwargs["color"] = "k"
756 if "label" not in line_kwargs.keys():
757 line_kwargs["label"] = "Proposed Value"
759 if var_scale == "log":
760 if var_axis == "y":
761 ax.axhline(y=np.log10(line_val), **line_kwargs)
762 elif var_axis == "x":
763 ax.axvline(x=np.log10(line_val), **line_kwargs)
764 elif var_scale == "lin":
765 if var_axis == "y":
766 ax.axhline(y=line_val, **line_kwargs)
767 elif var_axis == "x":
768 ax.axvline(x=line_val, **line_kwargs)
770 ax.update(ax_dict)
771 if label_kwargs:
772 if var_axis == "y":
773 ax.set_ylabel(ax.get_ylabel(), **label_kwargs)
774 elif var_axis == "x":
775 ax.set_xlabel(ax.get_xlabel(), **label_kwargs)
777 if tick_label_kwargs:
778 if var_axis == "y":
779 ax.set_yticklabels(ax.get_yticklabels(), **tick_label_kwargs)
780 elif var_axis == "x":
781 ax.set_xticklabels(ax.get_xticklabels(), **tick_label_kwargs)