From 1e59a56420a32a5637c6d376151976e23ae44e0f Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Mon, 14 Jun 2021 11:32:51 +0200 Subject: [PATCH 01/17] add plot tests --- plottest.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 plottest.py diff --git a/plottest.py b/plottest.py new file mode 100644 index 0000000..6833317 --- /dev/null +++ b/plottest.py @@ -0,0 +1,23 @@ +from matplotlib import pyplot as plt +from sunpy.net import Fido, attrs as a +from sunpy.timeseries import TimeSeries + +from stixpy.net.client import STIXClient # Need to import to register with Fido +from stixpy import timeseries # Need to import to register with timeseries +from stixpy.science import ScienceData + +# Ok this look like an interesting event let look for some pixel data +query = Fido.search(a.Time('2020-11-17T00:00', '2020-11-17T23:59'), a.Instrument.stix, a.stix.DataProduct.sci_xray_l1) +query +# Again the 2nd to last file seem to match the time range of interest +pd_file = Fido.fetch(query[0, -2]) +pd = ScienceData.from_fits(pd_file[0]) + +# jsut printg the object gives a textual overview, pixel data support the same plot methods as +pd + +# spectrograms with an additional method to plot the pixel data +pd.plot_pixels(energy_indices=[[1, 10], [10, 30]]) +plt.show() + +print(1) From fc2ece840f337c69f3903a1e6f61c919454c52ee Mon Sep 17 00:00:00 2001 From: lukasgraf-internship Date: Mon, 14 Jun 2021 11:49:41 +0200 Subject: [PATCH 02/17] Update plottest.py Changed 1 to hello --- plottest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plottest.py b/plottest.py index 6833317..d1f86e8 100644 --- a/plottest.py +++ b/plottest.py @@ -20,4 +20,4 @@ pd.plot_pixels(energy_indices=[[1, 10], [10, 30]]) plt.show() -print(1) +print("Hallo") From 0cf5f294dba951cd4380a80cd5d5969422055d5d Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Wed, 16 Jun 2021 15:53:28 +0200 Subject: [PATCH 03/17] add collimator reader --- .gitignore | 2 ++ plottest.py | 5 +++++ stixpy/science.py | 14 +++++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 0684792..1ae89d5 100644 --- a/.gitignore +++ b/.gitignore @@ -154,3 +154,5 @@ htmlcov/ #stixpy stixpy/data/*.fits +.vscode/launch.json +.vscode/settings.json diff --git a/plottest.py b/plottest.py index 6833317..55a899c 100644 --- a/plottest.py +++ b/plottest.py @@ -1,10 +1,12 @@ from matplotlib import pyplot as plt from sunpy.net import Fido, attrs as a from sunpy.timeseries import TimeSeries +from pathlib import Path from stixpy.net.client import STIXClient # Need to import to register with Fido from stixpy import timeseries # Need to import to register with timeseries from stixpy.science import ScienceData +from stixcore.config.reader import read_subc_params # Ok this look like an interesting event let look for some pixel data query = Fido.search(a.Time('2020-11-17T00:00', '2020-11-17T23:59'), a.Instrument.stix, a.stix.DataProduct.sci_xray_l1) @@ -16,6 +18,9 @@ # jsut printg the object gives a textual overview, pixel data support the same plot methods as pd +scp = read_subc_params(Path(read_subc_params.__code__.co_filename).parent + / "data" / "common" / "detector" / "stx_subc_params.csv") + # spectrograms with an additional method to plot the pixel data pd.plot_pixels(energy_indices=[[1, 10], [10, 30]]) plt.show() diff --git a/stixpy/science.py b/stixpy/science.py index 1afd1ae..74bdb59 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -266,11 +266,19 @@ def energyval(val): axcolor = 'lightgoldenrodyellow' axenergy = plt.axes([0.15, 0.05, 0.55, 0.03], facecolor=axcolor) - senergy = SliderCustomValue(axenergy, 'Energy', 0, len(energies)-1, format_func=energyval, + senergy = SliderCustomValue(ax=axenergy, + label='Energy', + valmin=0, + valmax=len(energies)-1, + format_func=energyval, valinit=0, valstep=1) axetime = plt.axes([0.15, 0.01, 0.55, 0.03], facecolor=axcolor) - stime = SliderCustomValue(axetime, 'Time', 0, counts.shape[0]-1, format_func=timeval, - valinit=0, valstep=1) + stime = SliderCustomValue(ax=axetime, + label='Time', + valmin=0, + valmax=counts.shape[0]-1, + format_func=timeval, + valinit=1, valstep=1) pixel_ids = [slice(0, 4), slice(4, 8), slice(8, 12)] if counts.shape[2] == 4: From 9c823c33f199db23e5ff4bca5ae1c637741a0ab6 Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Wed, 16 Jun 2021 16:06:43 +0200 Subject: [PATCH 04/17] add collimator plot --- plottest.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plottest.py b/plottest.py index 55a899c..779f531 100644 --- a/plottest.py +++ b/plottest.py @@ -21,6 +21,13 @@ scp = read_subc_params(Path(read_subc_params.__code__.co_filename).parent / "data" / "common" / "detector" / "stx_subc_params.csv") + +plt.plot(scp["SC Xcen"], scp["SC Ycen"], 'ro') +for i, txt in enumerate(scp['Grid Label']): + plt.text(scp["SC Xcen"][i]+.03, scp["SC Ycen"][i]+0.3, txt, fontsize=9) + +plt.show() + # spectrograms with an additional method to plot the pixel data pd.plot_pixels(energy_indices=[[1, 10], [10, 30]]) plt.show() From e70a932f4ae7985789ef408c28fff7fd0665f3c7 Mon Sep 17 00:00:00 2001 From: lukasgraf-internship Date: Wed, 16 Jun 2021 16:24:39 +0200 Subject: [PATCH 05/17] Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 0684792..a5314a7 100644 --- a/.gitignore +++ b/.gitignore @@ -154,3 +154,5 @@ htmlcov/ #stixpy stixpy/data/*.fits +/Minergie Test Data/ +/Start Practice/ From c1ff99e500d3658a77c90e6f7dfc44dc107e76ec Mon Sep 17 00:00:00 2001 From: lukasgraf-internship Date: Thu, 17 Jun 2021 11:51:12 +0200 Subject: [PATCH 06/17] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6875280..c6a5b4d 100644 --- a/.gitignore +++ b/.gitignore @@ -155,6 +155,6 @@ htmlcov/ #stixpy stixpy/data/*.fits /Minergie Test Data/ -/Start Practice/ +/Matplotlib Practice/ .vscode/launch.json .vscode/settings.json From 95091df67dfd045ec507b9227461f14e6832c704 Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Wed, 23 Jun 2021 16:38:02 +0200 Subject: [PATCH 07/17] subplot position of pixel plot --- stixpy/science.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/stixpy/science.py b/stixpy/science.py index 74bdb59..3dd27f2 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -13,6 +13,7 @@ from matplotlib.dates import date2num, HourLocator, DateFormatter from matplotlib.widgets import Slider from sunpy.time.timerange import TimeRange +from stixcore.config.reader import read_subc_params __all__ = ['ScienceData', 'RawPixelData', 'CompressedPixelData', 'SummedCompressedPixelData', 'Visibility', 'Spectrogram', 'PPrintMixin', 'IndexMasks', 'DetectorMasks', 'PixelMasks', @@ -20,7 +21,8 @@ quantity_support() - +SCP = read_subc_params(Path(read_subc_params.__code__.co_filename).parent + / "data" / "common" / "detector" / "stx_subc_params.csv") class PPrintMixin: """ Provides pretty printing for index masks. @@ -251,9 +253,9 @@ def plot_pixels(self, time_indices=None, energy_indices=None, fig=None): """ if fig: - axes = fig.subplots(nrows=4, ncols=8, sharex=True, sharey=True, figsize=(10, 5)) + axes = fig.subplots(nrows=4, ncols=8, sharex=True, sharey=True, figsize=(7, 7)) else: - fig, axes = plt.subplots(nrows=4, ncols=8, sharex=True, sharey=True, figsize=(10, 5)) + fig, axes = plt.subplots(nrows=4, ncols=8, sharex=True, sharey=True, figsize=(7, 7)) counts, count_err, times, dt, energies = self.get_data(time_indices=time_indices, energy_indices=energy_indices) @@ -286,6 +288,9 @@ def energyval(val): containers = defaultdict(list) + xnorm = plt.Normalize(SCP["SC Xcen"].min()*1.5, SCP["SC Xcen"].max()*1.5) + ynorm = plt.Normalize(SCP["SC Ycen"].min()*1.5, SCP["SC Ycen"].max()*1.5) + for detector_id in range(32): row, col = divmod(detector_id, 8) for pixel_id in pixel_ids: @@ -293,12 +298,15 @@ def energyval(val): counts[0, detector_id, pixel_id, 0], yerr=count_err[0, detector_id, pixel_id, 0], xerr=0.5, ls='') + x = SCP["SC Xcen"][detector_id] + y = SCP["SC Ycen"][detector_id] + axes[row, col].set_position([xnorm(x), ynorm(y), 1/10.0, 1/10.0]) containers[row, col].append(errbar_cont) axes[row, col].set_xlim(0, 4) axes[row, col].set_title(f'Det {detector_id}') axes[row, col].set_xticks([]) - if col != 0: + if detector_id > 0: # axs[row, col].set_yticks([]) axes[row, col].set_ylabel('') From aeafa9d51d72baf141cbac5a1271d352bf57815f Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Wed, 30 Jun 2021 14:16:48 +0200 Subject: [PATCH 08/17] minimal plottest from test and fido --- plottest.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plottest.py b/plottest.py index 10ade82..b2953fe 100644 --- a/plottest.py +++ b/plottest.py @@ -7,29 +7,29 @@ from stixpy import timeseries # Need to import to register with timeseries from stixpy.science import ScienceData from stixcore.config.reader import read_subc_params +from stixpy.data import test # Ok this look like an interesting event let look for some pixel data query = Fido.search(a.Time('2020-11-17T00:00', '2020-11-17T23:59'), a.Instrument.stix, a.stix.DataProduct.sci_xray_l1) query # Again the 2nd to last file seem to match the time range of interest -pd_file = Fido.fetch(query[0, -2]) +pd_file = Fido.fetch(query[0]) pd = ScienceData.from_fits(pd_file[0]) # jsut printg the object gives a textual overview, pixel data support the same plot methods as pd -scp = read_subc_params(Path(read_subc_params.__code__.co_filename).parent - / "data" / "common" / "detector" / "stx_subc_params.csv") +l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) +# spectrograms with an additional method to plot the pixel data +pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) +plt.show() -plt.plot(scp["SC Xcen"], scp["SC Ycen"], 'ro') -for i, txt in enumerate(scp['Grid Label']): - plt.text(scp["SC Xcen"][i]+.03, scp["SC Ycen"][i]+0.3, txt, fontsize=9) +counts, count_err, times, dt, energies = l1.get_data(time_indices=[0], energy_indices=[0]) +counts = counts.reshape([32, 12]) -plt.show() -# spectrograms with an additional method to plot the pixel data -pd.plot_pixels(energy_indices=[[1, 10], [10, 30]]) +l1.plot_pixels() plt.show() -print("Hallo") +print(1) From e27c8f8a31b76627f9e601af6f115fc7084814fb Mon Sep 17 00:00:00 2001 From: lukasgraf-internship Date: Wed, 30 Jun 2021 14:26:05 +0200 Subject: [PATCH 09/17] Add pixel and config plot --- stixpy/science.py | 233 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 220 insertions(+), 13 deletions(-) diff --git a/stixpy/science.py b/stixpy/science.py index 3dd27f2..143cfd6 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -9,9 +9,12 @@ from astropy.time import Time from astropy.visualization import quantity_support from matplotlib import pyplot as plt +from matplotlib import cm +from matplotlib import colors from matplotlib.colors import LogNorm from matplotlib.dates import date2num, HourLocator, DateFormatter from matplotlib.widgets import Slider +from matplotlib.widgets import Button from sunpy.time.timerange import TimeRange from stixcore.config.reader import read_subc_params @@ -229,12 +232,15 @@ class PixelPlotMixin: """ Pixel plot mixin providing pixel plotting for pixel data. """ - def plot_pixels(self, time_indices=None, energy_indices=None, fig=None): + def plot_pixels(self, plottype, time_indices=None, energy_indices=None, fig=None, cmap='viridis'): """ Plot individual pixel data for each detector. Parameters ---------- + plottype : `string` + The user can choose how he wants to visualize the data. The possible options ar 'errorbar' and 'pixels'. + The data will then be shown in the selected style. time_indices : `list` or `numpy.ndarray` If an 1xN array will be treated as mask if 2XN array will sum data between given indices. For example `time_indices=[0, 2, 5]` would return only the first, third and @@ -245,6 +251,9 @@ def plot_pixels(self, time_indices=None, energy_indices=None, fig=None): sixth times while `energy_indices=[[0, 2],[3, 5]]` would sum the data between. fig : optional `matplotlib.figure` The figure where to which the pixel plot will be added. + cmap : optional `colormap' type + If the plottype is `bar` a colormap will be shown. Select different types of colormaps + to change the colormap used. Returns ------- @@ -260,12 +269,199 @@ def plot_pixels(self, time_indices=None, energy_indices=None, fig=None): counts, count_err, times, dt, energies = self.get_data(time_indices=time_indices, energy_indices=energy_indices) + max_counts = counts.max().value + min_counts = counts.min().value + norm = plt.Normalize(min_counts, max_counts) + det_font = {'weight': 'regular', 'size': 6} + ax_font = {'weight': 'regular', 'size': 7} + q_font = {'weight': 'regular', 'size': 15} + clrmap = cm.get_cmap(cmap) + def timeval(val): return times[val].isot def energyval(val): return f"{energies[val]['e_low'].value}-{energies[val]['e_high']}" + def det_pixels_plot(counts, norm, axes, clrmap, fig): + """ + Parameters + ---------- + counts = data collection of the number of counts + norm = normalizes the data in the parentheses + axes = the axes in which the data will be plotted + clrmap = the colormap which will be used to visualize the data/counts + fig = helps the hover function to understand in which figure it should return the label + + Returns + ------- + A barplot which visualizes the data with the help of a colorbar. + """ + # Set the variables needed. + bar1 = [1, 1, 1, 1] + bar2 = [-1, -1, -1, -1] + bar3 = [.2, .2, .2, .2] + x_pos = ['A', 'B', 'C', 'D'] + + cdata_a = counts[0:4] # .astype(int) + cdata_b = counts[4:8] # .astype(int) + b1 = axes.bar(x_pos, bar1, color=clrmap(norm(cdata_a)), width=1, zorder=1, label='T') + b2 = axes.bar(x_pos, bar2, color=clrmap(norm(cdata_b)), width=1, zorder=1, label='B') + axes.bar(x_pos, bar3, color='black', width=-0.5, align='edge', bottom=-0.1, zorder=1) + axes.axes.get_xaxis().set_visible(False) + axes.axes.get_yaxis().set_visible(False) + + annot = axes.annotate("", xy=(0, 0), xytext=(-60, 20), textcoords="offset points", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="-"), zorder=33) + + annot.set_visible(False) + + def update_annot(artist, annot, cdata_a, cdata_b): + """ update tooltip when hovering a given plotted object """ + # find the middle of the bar + center_x = artist.get_x() + artist.get_width() / 2 + center_y = artist.get_y() + artist.get_height() / 2 + annot.xy = (center_x, center_y) + + # Get the artists and the labels + handles, labels = artist.axes.get_legend_handles_labels() + + # Search for your current artist within all plot groups + label = [label for h, label in zip(handles, labels) if artist in h.get_children()] + + # Get the bar Index + bar_ind = artist.get_x() + text = object + + for lb, data in zip(['T', 'B'], [cdata_a, cdata_b]): + if label == [lb]: + if bar_ind == -0.5: + text = data[0] + elif bar_ind == 0.5: + text = data[1] + elif bar_ind == 1.5: + text = data[2] + else: + text = data[3] + + annot.set_text(text) + annot.get_bbox_patch().set_alpha(1) + + def hover(event): + """ update and show a tooltip while hovering an object; hide it otherwise """ + if isinstance(event.inaxes, type(axes)): + for p in [b1, b2]: + for artist in p: + contains, _ = artist.contains(event) + if contains: + update_annot(artist, annot, cdata_a, cdata_b) + annot.set_visible(True) + fig.canvas.draw_idle() + else: + # one wants to hide the annotation only if no artist in the graph is hovered + annot.set_visible(False) + fig.canvas.draw_idle() + + fig.canvas.mpl_connect("motion_notify_event", hover) + + def mm2deg(x): + return x * 360 / 1 + + def deg2mm(x): + return x / 360 * 1 + + def det_config_plot(info, axes, font, detector_id): + if info['Phase Sense'] > 0: + phase_sense = '+' + elif info['Phase Sense'] < 0: + phase_sense = '-' + else: + phase_sense = 'n' + + front_pitch = info['Front Pitch'] + front_orient = info['Front Orient'] + rear_pitch = info['Rear Pitch'] + rear_orient = info['Rear Orient'] + slit_width = info['Slit Width'] + y1 = [slit_width, front_pitch, rear_pitch, 0, deg2mm(front_orient), deg2mm(rear_orient)] + x = np.arange(len(y1)) + x_ticklabels = ['Slit Width', 'Pitch', '', '', 'Orientation', ''] + color = ['black', 'orange', '#1f77b4', 'b', 'orange', '#1f77b4'] + + # plot the information on axes + axes.bar(x, y1, color=color) + axes.text(x=0.8, y=0.7, s=f'Phase: {phase_sense}', **font) + axes.set_ylim(0, 1) + axes.axes.get_xaxis().set_visible(False) + + # Create secondary y axis + ax2 = axes.secondary_yaxis('right', functions=(mm2deg, deg2mm)) + ax2.set_yticks([0, 90, 270, 360]) + ax2.set_yticklabels(['0°', '90°', '270°', '360°'], fontsize=8) + + if not detector_id == 22: + axes.set_yticks([0, 1]) + axes.set_ylabel('mm', **font) + axes.yaxis.set_label_coords(-0.1, 0.5) + ax2.set_visible(False) + axes.axes.get_yaxis().set_visible(False) + elif detector_id == 22: + # leave the spaces to set the correct x position of the label!! + ax2.set_ylabel(' deg °', rotation=0, **font) + # x parameter doesn't change anything because it's a secondary y axis (has only 1 x position). + ax2.yaxis.set_label_coords(x=1, y=0.55) + + if detector_id == 0: + axes.axes.get_yaxis().set_visible(True) + elif detector_id == 27: + axes.axes.get_xaxis().set_visible(True) + axes.set_xticklabels(x_ticklabels, fontsize=8, rotation=-90) + + def colorbar(counts, min_counts, max_counts, clrmap, fig): + """ Creates a colormap at the left side of the created figure. """ + norm = colors.Normalize(vmin=min_counts, vmax=max_counts) + cax = fig.add_axes([0.05, 0.15, 0.025, 0.8]) + cbar = plt.colorbar(cm.ScalarMappable(norm=norm, cmap=clrmap), orientation='vertical', cax=cax) + cbar.ax.set_title(f'{str(counts.unit)}', rotation=90, x=-0.8, y=0.4) + + def helpers(fig, font): + """ Shows helpers in the background of the subplots to make it easier to locate the detectors. """ + x = [0, 2] + y = [1, 1] + fig.add_axes([0.06, 0.055, 0.97, 0.97]) + plt.plot(x, y, c='b') + plt.plot(y, x, c='b') + plt.axis('off') + fig.add_axes([0.09, 0.08, 0.91, 0.92]) + draw_circle_1 = plt.Circle((0.545, 0.540), 0.443, color='b', alpha=0.1) + draw_circle_2 = plt.Circle((0.545, 0.540), 0.07, color='#2b330b', alpha=0.95) + fig.add_artist(draw_circle_1) + fig.add_artist(draw_circle_2) + plt.axis('off') + fig.add_axes([0, 0, 1, 1]) + plt.text(0.19, 0.89, 'Q1', **font) + plt.text(0.19, 0.17, 'Q2', **font) + plt.text(0.86, 0.17, 'Q3', **font) + plt.text(0.86, 0.89, 'Q4', **font) + plt.axis('off') + + helpers(fig, q_font) + + """ + def _switch(event): + Switches the plottype if the 'switch' button is getting pressed. + # det_config_plot(SCP[detector_id], axes[3, 5], det_font) + # axes[3, 5].set_zorder(500) + # plt.show() + return bt + + button_pos = fig.add_axes([0.87, 0.09, 0.1, 0.06]) + button_pos.set_zorder(200) + bt = Button(button_pos, 'switch', color='gray', hovercolor='green') + bt.on_clicked(_switch) + """ + axcolor = 'lightgoldenrodyellow' axenergy = plt.axes([0.15, 0.05, 0.55, 0.03], facecolor=axcolor) senergy = SliderCustomValue(ax=axenergy, @@ -290,25 +486,36 @@ def energyval(val): xnorm = plt.Normalize(SCP["SC Xcen"].min()*1.5, SCP["SC Xcen"].max()*1.5) ynorm = plt.Normalize(SCP["SC Ycen"].min()*1.5, SCP["SC Ycen"].max()*1.5) + if plottype == 'pixels': + counts = counts.reshape([32, 12]) + colorbar(counts, min_counts, max_counts, clrmap, fig) for detector_id in range(32): row, col = divmod(detector_id, 8) - for pixel_id in pixel_ids: - errbar_cont = axes[row, col].errorbar((0.5, 1.5, 2.5, 3.5), + plot_cont = object + if plottype == 'pixels': + plot_cont = det_pixels_plot(counts[detector_id], norm, axes[row, col], clrmap, fig) + axes[row, col].set_xticks([]) + elif plottype == 'errorbar': + for pixel_id in pixel_ids: + plot_cont = axes[row, col].errorbar((0.5, 1.5, 2.5, 3.5), counts[0, detector_id, pixel_id, 0], yerr=count_err[0, detector_id, pixel_id, 0], xerr=0.5, ls='') - x = SCP["SC Xcen"][detector_id] - y = SCP["SC Ycen"][detector_id] - axes[row, col].set_position([xnorm(x), ynorm(y), 1/10.0, 1/10.0]) - - containers[row, col].append(errbar_cont) - axes[row, col].set_xlim(0, 4) - axes[row, col].set_title(f'Det {detector_id}') axes[row, col].set_xticks([]) - if detector_id > 0: - # axs[row, col].set_yticks([]) - axes[row, col].set_ylabel('') + elif plottype == 'config': + # if not detector_id in [8, 9]: + plot_cont = det_config_plot(SCP[detector_id], axes[row, col], ax_font, detector_id) + + axes[row, col].set_zorder(100) + x = SCP["SC Xcen"][detector_id] + y = SCP["SC Ycen"][detector_id] + axes[row, col].set_position([xnorm(x), ynorm(y), 1/11.0, 1/11.0]) + + containers[row, col].append(plot_cont) + axes[row, col].set_title(f'Det {SCP["Grid Label"][detector_id]}', y=0.89, **det_font) + if detector_id > 0: + axes[row, col].set_ylabel('') def update(_): energy_index = senergy.val From b794c0a9f1a106a565cbaac7af9232eb2df8250f Mon Sep 17 00:00:00 2001 From: lukasgraf-internship Date: Wed, 30 Jun 2021 16:57:03 +0200 Subject: [PATCH 10/17] time and energy update the hover update is not working yet --- plottest.py | 10 ++-- stixpy/science.py | 126 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 110 insertions(+), 26 deletions(-) diff --git a/plottest.py b/plottest.py index b2953fe..28e4e92 100644 --- a/plottest.py +++ b/plottest.py @@ -22,14 +22,10 @@ l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) # spectrograms with an additional method to plot the pixel data -pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) -plt.show() - -counts, count_err, times, dt, energies = l1.get_data(time_indices=[0], energy_indices=[0]) -counts = counts.reshape([32, 12]) - +# pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) +# plt.show() -l1.plot_pixels() +l1.plot_pixels(plottype='pixels') plt.show() print(1) diff --git a/stixpy/science.py b/stixpy/science.py index 143cfd6..1190782 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -232,7 +232,7 @@ class PixelPlotMixin: """ Pixel plot mixin providing pixel plotting for pixel data. """ - def plot_pixels(self, plottype, time_indices=None, energy_indices=None, fig=None, cmap='viridis'): + def plot_pixels(self, *, plottype='pixels', time_indices=None, energy_indices=None, fig=None, cmap='viridis'): """ Plot individual pixel data for each detector. @@ -261,6 +261,9 @@ def plot_pixels(self, plottype, time_indices=None, energy_indices=None, fig=None The figure """ + if not plottype in ["pixels", "errorbar", "config"]: + plottype = 'pixels' + if fig: axes = fig.subplots(nrows=4, ncols=8, sharex=True, sharey=True, figsize=(7, 7)) else: @@ -303,11 +306,13 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig): bar3 = [.2, .2, .2, .2] x_pos = ['A', 'B', 'C', 'D'] - cdata_a = counts[0:4] # .astype(int) - cdata_b = counts[4:8] # .astype(int) - b1 = axes.bar(x_pos, bar1, color=clrmap(norm(cdata_a)), width=1, zorder=1, label='T') - b2 = axes.bar(x_pos, bar2, color=clrmap(norm(cdata_b)), width=1, zorder=1, label='B') - axes.bar(x_pos, bar3, color='black', width=-0.5, align='edge', bottom=-0.1, zorder=1) + cdata_top = counts[0:4] + cdata_bottom = counts[4:8] + cdata_small = counts[8:12] + + b1 = axes.bar(x_pos, bar1, color=clrmap(norm(cdata_top)), width=1, zorder=1, label='T') + b2 = axes.bar(x_pos, bar2, color=clrmap(norm(cdata_bottom)), width=1, zorder=1, label='B') + b3 = axes.bar(x_pos, bar3, color=clrmap(norm(cdata_small)), width=-0.5, align='edge', bottom=-0.1, zorder=1) axes.axes.get_xaxis().set_visible(False) axes.axes.get_yaxis().set_visible(False) @@ -317,7 +322,7 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig): annot.set_visible(False) - def update_annot(artist, annot, cdata_a, cdata_b): + def update_annot(artist, annot, cdata_top, cdata_bottom): """ update tooltip when hovering a given plotted object """ # find the middle of the bar center_x = artist.get_x() + artist.get_width() / 2 @@ -334,7 +339,7 @@ def update_annot(artist, annot, cdata_a, cdata_b): bar_ind = artist.get_x() text = object - for lb, data in zip(['T', 'B'], [cdata_a, cdata_b]): + for lb, data in zip(['T', 'B'], [cdata_top, cdata_bottom]): if label == [lb]: if bar_ind == -0.5: text = data[0] @@ -355,7 +360,7 @@ def hover(event): for artist in p: contains, _ = artist.contains(event) if contains: - update_annot(artist, annot, cdata_a, cdata_b) + update_annot(artist, annot, cdata_top, cdata_bottom) annot.set_visible(True) fig.canvas.draw_idle() else: @@ -363,15 +368,19 @@ def hover(event): annot.set_visible(False) fig.canvas.draw_idle() - fig.canvas.mpl_connect("motion_notify_event", hover) + cid = fig.canvas.mpl_connect("motion_notify_event", hover) + return [b1, b2, b3, annot, cid] - def mm2deg(x): - return x * 360 / 1 - def deg2mm(x): - return x / 360 * 1 def det_config_plot(info, axes, font, detector_id): + + def mm2deg(x): + return x * 360 / 1 + + def deg2mm(x): + return x / 360 * 1 + if info['Phase Sense'] > 0: phase_sense = '+' elif info['Phase Sense'] < 0: @@ -487,14 +496,13 @@ def _switch(event): xnorm = plt.Normalize(SCP["SC Xcen"].min()*1.5, SCP["SC Xcen"].max()*1.5) ynorm = plt.Normalize(SCP["SC Ycen"].min()*1.5, SCP["SC Ycen"].max()*1.5) if plottype == 'pixels': - counts = counts.reshape([32, 12]) colorbar(counts, min_counts, max_counts, clrmap, fig) for detector_id in range(32): row, col = divmod(detector_id, 8) plot_cont = object if plottype == 'pixels': - plot_cont = det_pixels_plot(counts[detector_id], norm, axes[row, col], clrmap, fig) + plot_cont = det_pixels_plot(counts[0, detector_id, :, 0], norm, axes[row, col], clrmap, fig) axes[row, col].set_xticks([]) elif plottype == 'errorbar': for pixel_id in pixel_ids: @@ -517,7 +525,80 @@ def _switch(event): if detector_id > 0: axes[row, col].set_ylabel('') - def update(_): + def update_void(_): + energy_index = senergy.val + time_index = stime.val + + def update_pixels(_): + energy_index = senergy.val + time_index = stime.val + imaging_mask = np.ones(32, bool) + imaging_mask[8:10] = False + + for detector_id in range(32): + row, col = divmod(detector_id, 8) + # axes[row, col].clear() + cnts = counts[time_index, imaging_mask, :, energy_index][detector_id] + top, bottom, small, annot, cid = containers[row, col][0] + cnts = cnts.reshape([3, 4]) + for pix_artist, pix in zip(range(4), range(12)): + norm_counts = norm(cnts[0][pix].value) + top[pix_artist].set_color(clrmap(norm_counts)) + norm_counts = norm(cnts[1][pix].value) + bottom[pix_artist].set_color(clrmap(norm_counts)) + norm_counts = norm(cnts[2][pix].value) + small[pix_artist].set_color(clrmap(norm_counts)) + + def update_annot(artist, annot, cdata_top, cdata_bottom): + """ update tooltip when hovering a given plotted object """ + # find the middle of the bar + center_x = artist.get_x() + artist.get_width() / 2 + center_y = artist.get_y() + artist.get_height() / 2 + annot.xy = (center_x, center_y) + + # Get the artists and the labels + handles, labels = artist.axes.get_legend_handles_labels() + + # Search for your current artist within all plot groups + label = [label for h, label in zip(handles, labels) if artist in h.get_children()] + + # Get the bar Index + bar_ind = artist.get_x() + text = object + + for lb, data in zip(['T', 'B'], [cdata_top, cdata_bottom]): + if label == [lb]: + if bar_ind == -0.5: + text = data[0] + elif bar_ind == 0.5: + text = data[1] + elif bar_ind == 1.5: + text = data[2] + else: + text = data[3] + + annot.set_text(text) + annot.get_bbox_patch().set_alpha(1) + + def hoverUpdate(event): + """ update and show a tooltip while hovering an object; hide it otherwise """ + if isinstance(event.inaxes, type(axes)): + for p in [top, bottom]: + for artist in p: + contains, _ = artist.contains(event) + if contains: + update_annot(artist, annot, cnts[0, :], cnts[1, :]) + annot.set_visible(True) + fig.canvas.draw_idle() + else: + # one wants to hide the annotation only if no artist in the graph is hovered + annot.set_visible(False) + fig.canvas.draw_idle() + + fig.canvas.mpl_disconnect(cid) + containers[row, col][0][4] = fig.canvas.mpl_connect("motion_notify_event", hoverUpdate) + + def update_errorbar(_): energy_index = senergy.val time_index = stime.val pids_ = [slice(0, 4), slice(4, 8), slice(8, 12)] @@ -553,8 +634,15 @@ def update(_): + count_err[time_index, did, pid, energy_index] bars[1].set_segments(segs) - senergy.on_changed(update) - stime.on_changed(update) + updatefunction = update_pixels + + if plottype == 'config': + updatefunction = update_void + elif plottype == 'errorbar': + updatefunction = update_errorbar + + senergy.on_changed(updatefunction) + stime.on_changed(updatefunction) class ScienceData: From 37abb3eb423d720af43d4aa0229cbc6c67afd68d Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Wed, 30 Jun 2021 22:38:15 +0200 Subject: [PATCH 11/17] fix mouse annotations --- plottest.py | 8 +-- stixpy/science.py | 173 +++++++++++++++------------------------------- 2 files changed, 61 insertions(+), 120 deletions(-) diff --git a/plottest.py b/plottest.py index 28e4e92..a0ccf33 100644 --- a/plottest.py +++ b/plottest.py @@ -17,15 +17,15 @@ pd = ScienceData.from_fits(pd_file[0]) # jsut printg the object gives a textual overview, pixel data support the same plot methods as -pd +# pd l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) # spectrograms with an additional method to plot the pixel data -# pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) -# plt.show() +pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) +plt.show() -l1.plot_pixels(plottype='pixels') +l1.plot_pixels(kind='pixels') plt.show() print(1) diff --git a/stixpy/science.py b/stixpy/science.py index 1190782..aed4a21 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -232,7 +232,7 @@ class PixelPlotMixin: """ Pixel plot mixin providing pixel plotting for pixel data. """ - def plot_pixels(self, *, plottype='pixels', time_indices=None, energy_indices=None, fig=None, cmap='viridis'): + def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, fig=None, cmap='viridis'): """ Plot individual pixel data for each detector. @@ -261,8 +261,8 @@ def plot_pixels(self, *, plottype='pixels', time_indices=None, energy_indices=No The figure """ - if not plottype in ["pixels", "errorbar", "config"]: - plottype = 'pixels' + if not kind in ["pixels", "errorbar", "config"]: + kind = 'pixels' if fig: axes = fig.subplots(nrows=4, ncols=8, sharex=True, sharey=True, figsize=(7, 7)) @@ -286,7 +286,7 @@ def timeval(val): def energyval(val): return f"{energies[val]['e_low'].value}-{energies[val]['e_high']}" - def det_pixels_plot(counts, norm, axes, clrmap, fig): + def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): """ Parameters ---------- @@ -310,96 +310,80 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig): cdata_bottom = counts[4:8] cdata_small = counts[8:12] - b1 = axes.bar(x_pos, bar1, color=clrmap(norm(cdata_top)), width=1, zorder=1, label='T') - b2 = axes.bar(x_pos, bar2, color=clrmap(norm(cdata_bottom)), width=1, zorder=1, label='B') - b3 = axes.bar(x_pos, bar3, color=clrmap(norm(cdata_small)), width=-0.5, align='edge', bottom=-0.1, zorder=1) + top = axes.bar(x_pos, bar1, color=clrmap(norm(cdata_top)), width=1, zorder=1, edgecolor="w", linewidth=0.5) + bottom = axes.bar(x_pos, bar2, color=clrmap(norm(cdata_bottom)), width=1, zorder=1, edgecolor="w", linewidth=0.5) + small = axes.bar(x_pos, bar3, color=clrmap(norm(cdata_small)), width=-0.5, align='edge', bottom=-0.1, zorder=1, edgecolor="w", linewidth=0.5) + + for i in range(4): + top[i].data = cdata_top[i] + bottom[i].data = cdata_bottom[i] + small[i].data = cdata_small[i] + axes.axes.get_xaxis().set_visible(False) axes.axes.get_yaxis().set_visible(False) - annot = axes.annotate("", xy=(0, 0), xytext=(-60, 20), textcoords="offset points", - bbox=dict(boxstyle="round", fc="w"), - arrowprops=dict(arrowstyle="-"), zorder=33) + annot = axes.annotate("", xy=(0, 0), xytext=(-60, 20), + textcoords="offset points", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="-"), zorder=33) annot.set_visible(False) - def update_annot(artist, annot, cdata_top, cdata_bottom): + def update_annot(artist, annot): """ update tooltip when hovering a given plotted object """ # find the middle of the bar center_x = artist.get_x() + artist.get_width() / 2 center_y = artist.get_y() + artist.get_height() / 2 annot.xy = (center_x, center_y) - # Get the artists and the labels - handles, labels = artist.axes.get_legend_handles_labels() - - # Search for your current artist within all plot groups - label = [label for h, label in zip(handles, labels) if artist in h.get_children()] - - # Get the bar Index - bar_ind = artist.get_x() - text = object - - for lb, data in zip(['T', 'B'], [cdata_top, cdata_bottom]): - if label == [lb]: - if bar_ind == -0.5: - text = data[0] - elif bar_ind == 0.5: - text = data[1] - elif bar_ind == 1.5: - text = data[2] - else: - text = data[3] - - annot.set_text(text) + annot.set_text(artist.data) annot.get_bbox_patch().set_alpha(1) def hover(event): """ update and show a tooltip while hovering an object; hide it otherwise """ + # one wants to hide the annotation only if no artist in the graph is hovered + annot.set_visible(False) if isinstance(event.inaxes, type(axes)): - for p in [b1, b2]: + for p in [top, bottom, small]: for artist in p: contains, _ = artist.contains(event) if contains: - update_annot(artist, annot, cdata_top, cdata_bottom) + update_annot(artist, annot) annot.set_visible(True) - fig.canvas.draw_idle() - else: - # one wants to hide the annotation only if no artist in the graph is hovered - annot.set_visible(False) + if last: fig.canvas.draw_idle() - cid = fig.canvas.mpl_connect("motion_notify_event", hover) - return [b1, b2, b3, annot, cid] - + fig.canvas.mpl_connect("motion_notify_event", hover) + return (top, bottom, small) - - def det_config_plot(info, axes, font, detector_id): + def det_config_plot(detector_config, axes, font, detector_id): def mm2deg(x): - return x * 360 / 1 + return x * 360.0 / 1 def deg2mm(x): - return x / 360 * 1 + return x / 360.0 * 1 - if info['Phase Sense'] > 0: + if detector_config['Phase Sense'] > 0: phase_sense = '+' - elif info['Phase Sense'] < 0: + elif detector_config['Phase Sense'] < 0: phase_sense = '-' else: phase_sense = 'n' - front_pitch = info['Front Pitch'] - front_orient = info['Front Orient'] - rear_pitch = info['Rear Pitch'] - rear_orient = info['Rear Orient'] - slit_width = info['Slit Width'] - y1 = [slit_width, front_pitch, rear_pitch, 0, deg2mm(front_orient), deg2mm(rear_orient)] - x = np.arange(len(y1)) + y = [detector_config['Slit Width'], + detector_config['Front Pitch'], + detector_config['Rear Pitch'], + 0, + deg2mm(detector_config['Front Orient']), + deg2mm(detector_config['Rear Orient'])] + + x = np.arange(len(y)) x_ticklabels = ['Slit Width', 'Pitch', '', '', 'Orientation', ''] color = ['black', 'orange', '#1f77b4', 'b', 'orange', '#1f77b4'] # plot the information on axes - axes.bar(x, y1, color=color) + axes.bar(x, y, color=color) axes.text(x=0.8, y=0.7, s=f'Phase: {phase_sense}', **font) axes.set_ylim(0, 1) axes.axes.get_xaxis().set_visible(False) @@ -495,23 +479,23 @@ def _switch(event): xnorm = plt.Normalize(SCP["SC Xcen"].min()*1.5, SCP["SC Xcen"].max()*1.5) ynorm = plt.Normalize(SCP["SC Ycen"].min()*1.5, SCP["SC Ycen"].max()*1.5) - if plottype == 'pixels': + if kind == 'pixels': colorbar(counts, min_counts, max_counts, clrmap, fig) for detector_id in range(32): row, col = divmod(detector_id, 8) plot_cont = object - if plottype == 'pixels': - plot_cont = det_pixels_plot(counts[0, detector_id, :, 0], norm, axes[row, col], clrmap, fig) + if kind == 'pixels': + plot_cont = det_pixels_plot(counts[0, detector_id, :, 0], norm, axes[row, col], clrmap, fig, last=detector_id==31) axes[row, col].set_xticks([]) - elif plottype == 'errorbar': + elif kind == 'errorbar': for pixel_id in pixel_ids: plot_cont = axes[row, col].errorbar((0.5, 1.5, 2.5, 3.5), counts[0, detector_id, pixel_id, 0], yerr=count_err[0, detector_id, pixel_id, 0], xerr=0.5, ls='') axes[row, col].set_xticks([]) - elif plottype == 'config': + elif kind == 'config': # if not detector_id in [8, 9]: plot_cont = det_config_plot(SCP[detector_id], axes[row, col], ax_font, detector_id) @@ -532,71 +516,28 @@ def update_void(_): def update_pixels(_): energy_index = senergy.val time_index = stime.val - imaging_mask = np.ones(32, bool) - imaging_mask[8:10] = False for detector_id in range(32): row, col = divmod(detector_id, 8) # axes[row, col].clear() - cnts = counts[time_index, imaging_mask, :, energy_index][detector_id] - top, bottom, small, annot, cid = containers[row, col][0] + cnts = counts[time_index, detector_id, :, energy_index] + top, bottom, small = containers[row, col][0] cnts = cnts.reshape([3, 4]) for pix_artist, pix in zip(range(4), range(12)): norm_counts = norm(cnts[0][pix].value) top[pix_artist].set_color(clrmap(norm_counts)) + top[pix_artist].data = cnts[0][pix] + top[pix_artist].set_edgecolor("w") + norm_counts = norm(cnts[1][pix].value) bottom[pix_artist].set_color(clrmap(norm_counts)) + bottom[pix_artist].data = cnts[1][pix] + bottom[pix_artist].set_edgecolor("w") + norm_counts = norm(cnts[2][pix].value) small[pix_artist].set_color(clrmap(norm_counts)) - - def update_annot(artist, annot, cdata_top, cdata_bottom): - """ update tooltip when hovering a given plotted object """ - # find the middle of the bar - center_x = artist.get_x() + artist.get_width() / 2 - center_y = artist.get_y() + artist.get_height() / 2 - annot.xy = (center_x, center_y) - - # Get the artists and the labels - handles, labels = artist.axes.get_legend_handles_labels() - - # Search for your current artist within all plot groups - label = [label for h, label in zip(handles, labels) if artist in h.get_children()] - - # Get the bar Index - bar_ind = artist.get_x() - text = object - - for lb, data in zip(['T', 'B'], [cdata_top, cdata_bottom]): - if label == [lb]: - if bar_ind == -0.5: - text = data[0] - elif bar_ind == 0.5: - text = data[1] - elif bar_ind == 1.5: - text = data[2] - else: - text = data[3] - - annot.set_text(text) - annot.get_bbox_patch().set_alpha(1) - - def hoverUpdate(event): - """ update and show a tooltip while hovering an object; hide it otherwise """ - if isinstance(event.inaxes, type(axes)): - for p in [top, bottom]: - for artist in p: - contains, _ = artist.contains(event) - if contains: - update_annot(artist, annot, cnts[0, :], cnts[1, :]) - annot.set_visible(True) - fig.canvas.draw_idle() - else: - # one wants to hide the annotation only if no artist in the graph is hovered - annot.set_visible(False) - fig.canvas.draw_idle() - - fig.canvas.mpl_disconnect(cid) - containers[row, col][0][4] = fig.canvas.mpl_connect("motion_notify_event", hoverUpdate) + small[pix_artist].data = cnts[2][pix] + small[pix_artist].set_edgecolor("w") def update_errorbar(_): energy_index = senergy.val @@ -636,9 +577,9 @@ def update_errorbar(_): updatefunction = update_pixels - if plottype == 'config': + if kind == 'config': updatefunction = update_void - elif plottype == 'errorbar': + elif kind == 'errorbar': updatefunction = update_errorbar senergy.on_changed(updatefunction) From 7137600dfd6729bfc6277d65775c74f0ebefc635 Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Thu, 1 Jul 2021 14:34:20 +0200 Subject: [PATCH 12/17] separate errorbar plot --- plottest.py | 12 ++-- stixpy/science.py | 159 ++++++++++++++++++++++++++-------------------- 2 files changed, 99 insertions(+), 72 deletions(-) diff --git a/plottest.py b/plottest.py index a0ccf33..98c5d13 100644 --- a/plottest.py +++ b/plottest.py @@ -15,17 +15,21 @@ # Again the 2nd to last file seem to match the time range of interest pd_file = Fido.fetch(query[0]) pd = ScienceData.from_fits(pd_file[0]) +print(pd_file[0]) # jsut printg the object gives a textual overview, pixel data support the same plot methods as # pd l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) -# spectrograms with an additional method to plot the pixel data -pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) -plt.show() +# spectrograms with an additional method to plot the pixel data default kind is pixel +#pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) +#plt.show() + +#pd.plot_pixels(kind='config') +#plt.show() -l1.plot_pixels(kind='pixels') +pd.plot_pixels(kind='errorbar', energy_indices=[[1, 5], [5, 20], [20, 30]]) plt.show() print(1) diff --git a/stixpy/science.py b/stixpy/science.py index aed4a21..81629e4 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -17,6 +17,7 @@ from matplotlib.widgets import Button from sunpy.time.timerange import TimeRange from stixcore.config.reader import read_subc_params +import copy __all__ = ['ScienceData', 'RawPixelData', 'CompressedPixelData', 'SummedCompressedPixelData', 'Visibility', 'Spectrogram', 'PPrintMixin', 'IndexMasks', 'DetectorMasks', 'PixelMasks', @@ -24,7 +25,7 @@ quantity_support() -SCP = read_subc_params(Path(read_subc_params.__code__.co_filename).parent +SubCollimatorConfig = read_subc_params(Path(read_subc_params.__code__.co_filename).parent / "data" / "common" / "detector" / "stx_subc_params.csv") class PPrintMixin: """ @@ -232,7 +233,7 @@ class PixelPlotMixin: """ Pixel plot mixin providing pixel plotting for pixel data. """ - def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, fig=None, cmap='viridis'): + def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, fig=None, cmap=None): """ Plot individual pixel data for each detector. @@ -272,13 +273,24 @@ def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, counts, count_err, times, dt, energies = self.get_data(time_indices=time_indices, energy_indices=energy_indices) - max_counts = counts.max().value - min_counts = counts.min().value + imaging_mask = np.ones(32, bool) + imaging_mask[8:10] = False + + max_counts = counts[:, imaging_mask, :, :].max().value + min_counts = counts[:, imaging_mask, :, :].min().value + norm = plt.Normalize(min_counts, max_counts) - det_font = {'weight': 'regular', 'size': 6} + det_font = {'weight': 'regular', 'size': 8} ax_font = {'weight': 'regular', 'size': 7} q_font = {'weight': 'regular', 'size': 15} - clrmap = cm.get_cmap(cmap) + + if cmap is None: + clrmap = copy.copy(cm.get_cmap('viridis')) + clrmap.set_over("w") + elif isinstance(cmap, str): + clrmap = copy.copy(cm.get_cmap(cmap)) + else: + clrmap = cmap def timeval(val): return times[val].isot @@ -306,21 +318,31 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): bar3 = [.2, .2, .2, .2] x_pos = ['A', 'B', 'C', 'D'] - cdata_top = counts[0:4] - cdata_bottom = counts[4:8] - cdata_small = counts[8:12] + counts = counts.reshape(3, 4) - top = axes.bar(x_pos, bar1, color=clrmap(norm(cdata_top)), width=1, zorder=1, edgecolor="w", linewidth=0.5) - bottom = axes.bar(x_pos, bar2, color=clrmap(norm(cdata_bottom)), width=1, zorder=1, edgecolor="w", linewidth=0.5) - small = axes.bar(x_pos, bar3, color=clrmap(norm(cdata_small)), width=-0.5, align='edge', bottom=-0.1, zorder=1, edgecolor="w", linewidth=0.5) + top = axes.bar(x_pos, bar1, color=clrmap(norm(counts[0, :])), + width=1, zorder=1, edgecolor="w", linewidth=0.5) + bottom = axes.bar(x_pos, bar2, color=clrmap(norm(counts[1, :])), + width=1, zorder=1, edgecolor="w", linewidth=0.5) + small = axes.bar(x_pos, bar3, color=clrmap(norm(counts[2, :])), + width=-0.5, align='edge', bottom=-0.1, zorder=1, + edgecolor="w", linewidth=0.5) - for i in range(4): - top[i].data = cdata_top[i] - bottom[i].data = cdata_bottom[i] - small[i].data = cdata_small[i] + #hide most of the axes ticks + if last: + axes.set_xticks(range(4)) + axes.set_xticklabels(x_pos) + axes.axes.get_xaxis().set_visible(True) + axes.axes.get_yaxis().set_visible(False) + else: + axes.set_xticks([]) + axes.axes.get_xaxis().set_visible(False) + axes.axes.get_yaxis().set_visible(False) - axes.axes.get_xaxis().set_visible(False) - axes.axes.get_yaxis().set_visible(False) + for i in range(4): + top[i].data = counts[0, i] + bottom[i].data = counts[1, i] + small[i].data = counts[2, i] annot = axes.annotate("", xy=(0, 0), xytext=(-60, 20), textcoords="offset points", @@ -336,8 +358,8 @@ def update_annot(artist, annot): center_y = artist.get_y() + artist.get_height() / 2 annot.xy = (center_x, center_y) - annot.set_text(artist.data) - annot.get_bbox_patch().set_alpha(1) + annot.set_text(artist.data.round(decimals=3)) + #annot.get_bbox_patch().set_alpha(1) def hover(event): """ update and show a tooltip while hovering an object; hide it otherwise """ @@ -356,6 +378,18 @@ def hover(event): fig.canvas.mpl_connect("motion_notify_event", hover) return (top, bottom, small) + def det_errorbar_plot(counts, count_err, pixel_ids, detector_id, axes): + plot_cont = [] + for pixel_id in pixel_ids: + plot_cont.append(axes.errorbar((0.5, 1.5, 2.5, 3.5), + counts[pixel_id], + yerr=count_err[pixel_id], + xerr=0.5, ls='')) + axes.set_xticks([]) + if detector_id > 0: + axes.set_ylabel('') + return plot_cont + def det_config_plot(detector_config, axes, font, detector_id): def mm2deg(x): @@ -393,7 +427,7 @@ def deg2mm(x): ax2.set_yticks([0, 90, 270, 360]) ax2.set_yticklabels(['0°', '90°', '270°', '360°'], fontsize=8) - if not detector_id == 22: + if detector_id != 22: axes.set_yticks([0, 1]) axes.set_ylabel('mm', **font) axes.yaxis.set_label_coords(-0.1, 0.5) @@ -402,7 +436,8 @@ def deg2mm(x): elif detector_id == 22: # leave the spaces to set the correct x position of the label!! ax2.set_ylabel(' deg °', rotation=0, **font) - # x parameter doesn't change anything because it's a secondary y axis (has only 1 x position). + # x parameter doesn't change anything because it's a secondary + # y axis (has only 1 x position). ax2.yaxis.set_label_coords(x=1, y=0.55) if detector_id == 0: @@ -415,11 +450,14 @@ def colorbar(counts, min_counts, max_counts, clrmap, fig): """ Creates a colormap at the left side of the created figure. """ norm = colors.Normalize(vmin=min_counts, vmax=max_counts) cax = fig.add_axes([0.05, 0.15, 0.025, 0.8]) - cbar = plt.colorbar(cm.ScalarMappable(norm=norm, cmap=clrmap), orientation='vertical', cax=cax) - cbar.ax.set_title(f'{str(counts.unit)}', rotation=90, x=-0.8, y=0.4) - - def helpers(fig, font): - """ Shows helpers in the background of the subplots to make it easier to locate the detectors. """ + cbar = plt.colorbar(cm.ScalarMappable(norm=norm, cmap=clrmap), + orientation='vertical', cax=cax) + cbar.ax.set_title(f'{str(counts.unit)}', rotation=90, + x=-0.8, y=0.4) + + def instrument_layout(fig, font): + """ Shows helpers in the background of the subplots to make it + easier to locate the detectors. """ x = [0, 2] y = [1, 1] fig.add_axes([0.06, 0.055, 0.97, 0.97]) @@ -427,8 +465,10 @@ def helpers(fig, font): plt.plot(y, x, c='b') plt.axis('off') fig.add_axes([0.09, 0.08, 0.91, 0.92]) - draw_circle_1 = plt.Circle((0.545, 0.540), 0.443, color='b', alpha=0.1) - draw_circle_2 = plt.Circle((0.545, 0.540), 0.07, color='#2b330b', alpha=0.95) + draw_circle_1 = plt.Circle((0.545, 0.540), 0.443, color='b', + alpha=0.1) + draw_circle_2 = plt.Circle((0.545, 0.540), 0.07, color='#2b330b', + alpha=0.95) fig.add_artist(draw_circle_1) fig.add_artist(draw_circle_2) plt.axis('off') @@ -439,21 +479,7 @@ def helpers(fig, font): plt.text(0.86, 0.89, 'Q4', **font) plt.axis('off') - helpers(fig, q_font) - - """ - def _switch(event): - Switches the plottype if the 'switch' button is getting pressed. - # det_config_plot(SCP[detector_id], axes[3, 5], det_font) - # axes[3, 5].set_zorder(500) - # plt.show() - return bt - - button_pos = fig.add_axes([0.87, 0.09, 0.1, 0.06]) - button_pos.set_zorder(200) - bt = Button(button_pos, 'switch', color='gray', hovercolor='green') - bt.on_clicked(_switch) - """ + instrument_layout(fig, q_font) axcolor = 'lightgoldenrodyellow' axenergy = plt.axes([0.15, 0.05, 0.55, 0.03], facecolor=axcolor) @@ -477,8 +503,8 @@ def _switch(event): containers = defaultdict(list) - xnorm = plt.Normalize(SCP["SC Xcen"].min()*1.5, SCP["SC Xcen"].max()*1.5) - ynorm = plt.Normalize(SCP["SC Ycen"].min()*1.5, SCP["SC Ycen"].max()*1.5) + xnorm = plt.Normalize(SubCollimatorConfig["SC Xcen"].min()*1.5, SubCollimatorConfig["SC Xcen"].max()*1.5) + ynorm = plt.Normalize(SubCollimatorConfig["SC Ycen"].min()*1.4, SubCollimatorConfig["SC Ycen"].max()*1.4) if kind == 'pixels': colorbar(counts, min_counts, max_counts, clrmap, fig) @@ -486,32 +512,32 @@ def _switch(event): row, col = divmod(detector_id, 8) plot_cont = object if kind == 'pixels': - plot_cont = det_pixels_plot(counts[0, detector_id, :, 0], norm, axes[row, col], clrmap, fig, last=detector_id==31) - axes[row, col].set_xticks([]) + plot_cont = det_pixels_plot(counts[0, detector_id, :, 0], norm, + axes[row, col], clrmap, fig, + last=(detector_id == 31)) elif kind == 'errorbar': - for pixel_id in pixel_ids: - plot_cont = axes[row, col].errorbar((0.5, 1.5, 2.5, 3.5), - counts[0, detector_id, pixel_id, 0], - yerr=count_err[0, detector_id, pixel_id, 0], - xerr=0.5, ls='') - axes[row, col].set_xticks([]) + plot_cont = det_errorbar_plot(counts[0, detector_id, :, 0], + count_err[0, detector_id, :, 0], + pixel_ids, detector_id, + axes[row, col]) elif kind == 'config': - # if not detector_id in [8, 9]: - plot_cont = det_config_plot(SCP[detector_id], axes[row, col], ax_font, detector_id) + plot_cont = det_config_plot(SubCollimatorConfig[detector_id], + axes[row, col], ax_font, + detector_id) axes[row, col].set_zorder(100) - x = SCP["SC Xcen"][detector_id] - y = SCP["SC Ycen"][detector_id] - axes[row, col].set_position([xnorm(x), ynorm(y), 1/11.0, 1/11.0]) + + axes[row, col].set_position([xnorm(SubCollimatorConfig["SC Xcen"][detector_id]), + ynorm(SubCollimatorConfig["SC Ycen"][detector_id]), + 1/11.0, 1/11.0]) containers[row, col].append(plot_cont) - axes[row, col].set_title(f'Det {SCP["Grid Label"][detector_id]}', y=0.89, **det_font) - if detector_id > 0: - axes[row, col].set_ylabel('') + axes[row, col].set_title(f'Det {SubCollimatorConfig["Grid Label"][detector_id]}', y=0.89, **det_font) def update_void(_): - energy_index = senergy.val - time_index = stime.val + # get the val as this will update the slider + _ = senergy.val + _ = stime.val def update_pixels(_): energy_index = senergy.val @@ -546,16 +572,13 @@ def update_errorbar(_): if counts.shape[2] == 4: pids_ = [slice(0, 4)] - imaging_mask = np.ones(32, bool) - imaging_mask[8:10] = False - for did in range(32): r, c = divmod(did, 8) axes[r, c].set_ylim(0, counts[time_index, imaging_mask, :, energy_index].max()*1.2) for i, pid in enumerate(pids_): - lines, caps, bars = containers[r, c][i] + lines, caps, bars = containers[r, c][0][i] lines.set_ydata(counts[time_index, did, pid, energy_index]) # horizontal bars at value From e8cd036326239387c5de44affbefef7affe50d5b Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Thu, 1 Jul 2021 17:47:27 +0200 Subject: [PATCH 13/17] labels on config plot --- stixpy/science.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/stixpy/science.py b/stixpy/science.py index 81629e4..9173da7 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -413,7 +413,6 @@ def deg2mm(x): deg2mm(detector_config['Rear Orient'])] x = np.arange(len(y)) - x_ticklabels = ['Slit Width', 'Pitch', '', '', 'Orientation', ''] color = ['black', 'orange', '#1f77b4', 'b', 'orange', '#1f77b4'] # plot the information on axes @@ -426,26 +425,26 @@ def deg2mm(x): ax2 = axes.secondary_yaxis('right', functions=(mm2deg, deg2mm)) ax2.set_yticks([0, 90, 270, 360]) ax2.set_yticklabels(['0°', '90°', '270°', '360°'], fontsize=8) + ax2.set_visible(False) + axes.axes.get_yaxis().set_visible(False) - if detector_id != 22: + if detector_id == 0: axes.set_yticks([0, 1]) axes.set_ylabel('mm', **font) axes.yaxis.set_label_coords(-0.1, 0.5) - ax2.set_visible(False) - axes.axes.get_yaxis().set_visible(False) - elif detector_id == 22: + axes.axes.get_yaxis().set_visible(True) + if detector_id == 31: + ax2.set_visible(True) + axes.axes.get_xaxis().set_visible(True) + axes.set_xticks([0, 1.5, 4.5]) + axes.set_xticklabels(['Slit Width', 'Pitch', 'Orientation'], + rotation=90) # leave the spaces to set the correct x position of the label!! ax2.set_ylabel(' deg °', rotation=0, **font) # x parameter doesn't change anything because it's a secondary # y axis (has only 1 x position). ax2.yaxis.set_label_coords(x=1, y=0.55) - if detector_id == 0: - axes.axes.get_yaxis().set_visible(True) - elif detector_id == 27: - axes.axes.get_xaxis().set_visible(True) - axes.set_xticklabels(x_ticklabels, fontsize=8, rotation=-90) - def colorbar(counts, min_counts, max_counts, clrmap, fig): """ Creates a colormap at the left side of the created figure. """ norm = colors.Normalize(vmin=min_counts, vmax=max_counts) From 91414ada5b6f4d5b8ecb90bd899b25da2f32fe5c Mon Sep 17 00:00:00 2001 From: lukasgraf-internship Date: Fri, 2 Jul 2021 11:02:40 +0200 Subject: [PATCH 14/17] Add a legend to config plot Also added a documentation at some parts. --- stixpy/science.py | 83 +++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/stixpy/science.py b/stixpy/science.py index 9173da7..1798bbc 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -14,7 +14,7 @@ from matplotlib.colors import LogNorm from matplotlib.dates import date2num, HourLocator, DateFormatter from matplotlib.widgets import Slider -from matplotlib.widgets import Button +from matplotlib.patches import Patch from sunpy.time.timerange import TimeRange from stixcore.config.reader import read_subc_params import copy @@ -239,9 +239,8 @@ def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, Parameters ---------- - plottype : `string` - The user can choose how he wants to visualize the data. The possible options ar 'errorbar' and 'pixels'. - The data will then be shown in the selected style. + kind : `string` the options: 'pixels', 'errorbar', 'config' + This sets the visualization type of the subplots. The data will then be shown in the selected style. time_indices : `list` or `numpy.ndarray` If an 1xN array will be treated as mask if 2XN array will sum data between given indices. For example `time_indices=[0, 2, 5]` would return only the first, third and @@ -253,8 +252,10 @@ def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, fig : optional `matplotlib.figure` The figure where to which the pixel plot will be added. cmap : optional `colormap' type - If the plottype is `bar` a colormap will be shown. Select different types of colormaps + If the kind is `bar` a colormap will be shown. Select different types of colormaps to change the colormap used. + NOTE: If the color of the special detectors 'cfl', 'bkg' is way above + the rest, the color will be automatically set to white. Returns ------- @@ -279,10 +280,10 @@ def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, max_counts = counts[:, imaging_mask, :, :].max().value min_counts = counts[:, imaging_mask, :, :].min().value - norm = plt.Normalize(min_counts, max_counts) + norm = plt.Normalize(min_counts, max_counts) # Needed to select the color values for the pixels plot. det_font = {'weight': 'regular', 'size': 8} - ax_font = {'weight': 'regular', 'size': 7} - q_font = {'weight': 'regular', 'size': 15} + axes_font = {'weight': 'regular', 'size': 7} + quadrant_font = {'weight': 'regular', 'size': 15} if cmap is None: clrmap = copy.copy(cm.get_cmap('viridis')) @@ -300,18 +301,23 @@ def energyval(val): def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): """ + Shows a plot to visualize the pixel counts; the pixels plot. + Parameters ---------- - counts = data collection of the number of counts + counts = data collection with the number of counts norm = normalizes the data in the parentheses axes = the axes in which the data will be plotted clrmap = the colormap which will be used to visualize the data/counts - fig = helps the hover function to understand in which figure it should return the label + fig = sets the current figure Returns ------- - A barplot which visualizes the data with the help of a colorbar. + top: The 4 pixels positioned at the top + bottom: The 4 pixels positioned at the bottom + small: The 4 small pixels in the middle """ + # Set the variables needed. bar1 = [1, 1, 1, 1] bar2 = [-1, -1, -1, -1] @@ -320,6 +326,7 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): counts = counts.reshape(3, 4) + # plot the pixels top = axes.bar(x_pos, bar1, color=clrmap(norm(counts[0, :])), width=1, zorder=1, edgecolor="w", linewidth=0.5) bottom = axes.bar(x_pos, bar2, color=clrmap(norm(counts[1, :])), @@ -328,7 +335,7 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): width=-0.5, align='edge', bottom=-0.1, zorder=1, edgecolor="w", linewidth=0.5) - #hide most of the axes ticks + # hide most of the axes ticks if last: axes.set_xticks(range(4)) axes.set_xticklabels(x_pos) @@ -344,6 +351,7 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): bottom[i].data = counts[1, i] small[i].data = counts[2, i] + # Create the label annotation annot = axes.annotate("", xy=(0, 0), xytext=(-60, 20), textcoords="offset points", bbox=dict(boxstyle="round", fc="w"), @@ -351,6 +359,7 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): annot.set_visible(False) + # Create a hover function def update_annot(artist, annot): """ update tooltip when hovering a given plotted object """ # find the middle of the bar @@ -359,7 +368,7 @@ def update_annot(artist, annot): annot.xy = (center_x, center_y) annot.set_text(artist.data.round(decimals=3)) - #annot.get_bbox_patch().set_alpha(1) + # annot.get_bbox_patch().set_alpha(1) def hover(event): """ update and show a tooltip while hovering an object; hide it otherwise """ @@ -376,9 +385,10 @@ def hover(event): fig.canvas.draw_idle() fig.canvas.mpl_connect("motion_notify_event", hover) - return (top, bottom, small) + return top, bottom, small def det_errorbar_plot(counts, count_err, pixel_ids, detector_id, axes): + """ Shows a plot to visualize the counts; the errorbar plot. """ plot_cont = [] for pixel_id in pixel_ids: plot_cont.append(axes.errorbar((0.5, 1.5, 2.5, 3.5), @@ -391,13 +401,15 @@ def det_errorbar_plot(counts, count_err, pixel_ids, detector_id, axes): return plot_cont def det_config_plot(detector_config, axes, font, detector_id): - + """ Shows a plot with the configurations of the detectors; the config plot. """ + # Create Functions to convert 'Front' and 'Rear Orient'. def mm2deg(x): return x * 360.0 / 1 def deg2mm(x): return x / 360.0 * 1 + # get the information that will be plotted if detector_config['Phase Sense'] > 0: phase_sense = '+' elif detector_config['Phase Sense'] < 0: @@ -428,25 +440,34 @@ def deg2mm(x): ax2.set_visible(False) axes.axes.get_yaxis().set_visible(False) + # Create axes labeling and legend if detector_id == 0: axes.set_yticks([0, 1]) axes.set_ylabel('mm', **font) axes.yaxis.set_label_coords(-0.1, 0.5) axes.axes.get_yaxis().set_visible(True) + legend_bars = [Patch(facecolor='orange'), Patch(facecolor='#1f77b4')] + axes.legend(legend_bars, ['Front', 'Rear'], loc='center right', bbox_to_anchor=(0, 2.5)) if detector_id == 31: ax2.set_visible(True) axes.axes.get_xaxis().set_visible(True) axes.set_xticks([0, 1.5, 4.5]) axes.set_xticklabels(['Slit Width', 'Pitch', 'Orientation'], rotation=90) - # leave the spaces to set the correct x position of the label!! + # leave the spaces to set the correct x position of the label! ax2.set_ylabel(' deg °', rotation=0, **font) # x parameter doesn't change anything because it's a secondary # y axis (has only 1 x position). ax2.yaxis.set_label_coords(x=1, y=0.55) def colorbar(counts, min_counts, max_counts, clrmap, fig): - """ Creates a colormap at the left side of the created figure. """ + """ + Creates a colormap at the left side of the created figure. + + NOTE: If the color of the special detectors 'cfl', 'bkg' is way above + the rest, the color will be automatically set to white. + """ + norm = colors.Normalize(vmin=min_counts, vmax=max_counts) cax = fig.add_axes([0.05, 0.15, 0.025, 0.8]) cbar = plt.colorbar(cm.ScalarMappable(norm=norm, cmap=clrmap), @@ -455,8 +476,7 @@ def colorbar(counts, min_counts, max_counts, clrmap, fig): x=-0.8, y=0.4) def instrument_layout(fig, font): - """ Shows helpers in the background of the subplots to make it - easier to locate the detectors. """ + """ Shows the layout of the instrument to make it easier to locate the detectors. """ x = [0, 2] y = [1, 1] fig.add_axes([0.06, 0.055, 0.97, 0.97]) @@ -471,6 +491,8 @@ def instrument_layout(fig, font): fig.add_artist(draw_circle_1) fig.add_artist(draw_circle_2) plt.axis('off') + + # Label the quandrants of the instrument fig.add_axes([0, 0, 1, 1]) plt.text(0.19, 0.89, 'Q1', **font) plt.text(0.19, 0.17, 'Q2', **font) @@ -478,8 +500,9 @@ def instrument_layout(fig, font): plt.text(0.86, 0.89, 'Q4', **font) plt.axis('off') - instrument_layout(fig, q_font) + instrument_layout(fig, quadrant_font) # Call the instrument layout + # Create the energy and time slider add the bottom of the figure axcolor = 'lightgoldenrodyellow' axenergy = plt.axes([0.15, 0.05, 0.55, 0.03], facecolor=axcolor) senergy = SliderCustomValue(ax=axenergy, @@ -507,6 +530,7 @@ def instrument_layout(fig, font): if kind == 'pixels': colorbar(counts, min_counts, max_counts, clrmap, fig) + # plot the layout of the 32 detectors for detector_id in range(32): row, col = divmod(detector_id, 8) plot_cont = object @@ -521,11 +545,12 @@ def instrument_layout(fig, font): axes[row, col]) elif kind == 'config': plot_cont = det_config_plot(SubCollimatorConfig[detector_id], - axes[row, col], ax_font, + axes[row, col], axes_font, detector_id) axes[row, col].set_zorder(100) + # set the custom position of the detectors axes[row, col].set_position([xnorm(SubCollimatorConfig["SC Xcen"][detector_id]), ynorm(SubCollimatorConfig["SC Ycen"][detector_id]), 1/11.0, 1/11.0]) @@ -534,17 +559,17 @@ def instrument_layout(fig, font): axes[row, col].set_title(f'Det {SubCollimatorConfig["Grid Label"][detector_id]}', y=0.89, **det_font) def update_void(_): - # get the val as this will update the slider + """ get the value as this will update the slider """ _ = senergy.val _ = stime.val def update_pixels(_): + """ Update the value of the pixels plot when the energy and time slider is being used. """ energy_index = senergy.val time_index = stime.val for detector_id in range(32): row, col = divmod(detector_id, 8) - # axes[row, col].clear() cnts = counts[time_index, detector_id, :, energy_index] top, bottom, small = containers[row, col][0] cnts = cnts.reshape([3, 4]) @@ -565,6 +590,7 @@ def update_pixels(_): small[pix_artist].set_edgecolor("w") def update_errorbar(_): + """ Update the errorbar plot when the energy and time slider is being used. """ energy_index = senergy.val time_index = stime.val pids_ = [slice(0, 4), slice(4, 8), slice(8, 12)] @@ -597,15 +623,16 @@ def update_errorbar(_): + count_err[time_index, did, pid, energy_index] bars[1].set_segments(segs) - updatefunction = update_pixels + update_function = update_pixels if kind == 'config': - updatefunction = update_void + update_function = update_void elif kind == 'errorbar': - updatefunction = update_errorbar + update_function = update_errorbar - senergy.on_changed(updatefunction) - stime.on_changed(updatefunction) + # Call the update functions + senergy.on_changed(update_function) + stime.on_changed(update_function) class ScienceData: From f915440fd144b0bbe3bd8d09a3a171a05111dbdf Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Fri, 2 Jul 2021 11:04:23 +0200 Subject: [PATCH 15/17] update plottest --- plottest.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/plottest.py b/plottest.py index 98c5d13..3b9e4e6 100644 --- a/plottest.py +++ b/plottest.py @@ -20,16 +20,18 @@ # jsut printg the object gives a textual overview, pixel data support the same plot methods as # pd -l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) +#l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) +l2 = ScienceData.from_fits(test.STIX_SCI_XRAY_L2) +l2.plot_pixels() -# spectrograms with an additional method to plot the pixel data default kind is pixel -#pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) -#plt.show() - -#pd.plot_pixels(kind='config') -#plt.show() +# plot the pixel data as default "kind=pixels" +pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) +plt.show() +# plot the pixel data as line chart with errorbars" pd.plot_pixels(kind='errorbar', energy_indices=[[1, 5], [5, 20], [20, 30]]) plt.show() -print(1) +# plot the detector configuration (independent on the actual pixeldata)" +pd.plot_pixels(kind='config') +plt.show() From e12383c92af1445e921b24e008128690b87e9101 Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Fri, 2 Jul 2021 11:16:37 +0200 Subject: [PATCH 16/17] cleanup --- plottest.py | 4 ++-- stixpy/science.py | 26 ++++++++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/plottest.py b/plottest.py index 3b9e4e6..a2a91a2 100644 --- a/plottest.py +++ b/plottest.py @@ -21,8 +21,8 @@ # pd #l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) -l2 = ScienceData.from_fits(test.STIX_SCI_XRAY_L2) -l2.plot_pixels() +#l2 = ScienceData.from_fits(test.STIX_SCI_XRAY_L2) +#l2.plot_pixels() # plot the pixel data as default "kind=pixels" pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) diff --git a/stixpy/science.py b/stixpy/science.py index 1798bbc..d2ffa30 100644 --- a/stixpy/science.py +++ b/stixpy/science.py @@ -251,11 +251,12 @@ def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, sixth times while `energy_indices=[[0, 2],[3, 5]]` would sum the data between. fig : optional `matplotlib.figure` The figure where to which the pixel plot will be added. - cmap : optional `colormap' type - If the kind is `bar` a colormap will be shown. Select different types of colormaps - to change the colormap used. + cmap : `string` | `colormap` optional + If the kind is `pixels` a colormap will be shown. + String : default colormap name + colormap: a custom colormap NOTE: If the color of the special detectors 'cfl', 'bkg' is way above - the rest, the color will be automatically set to white. + the imaging detectors, the color will be automatically set to white. Returns ------- @@ -263,7 +264,7 @@ def plot_pixels(self, *, kind='pixels', time_indices=None, energy_indices=None, The figure """ - if not kind in ["pixels", "errorbar", "config"]: + if kind not in ["pixels", "errorbar", "config"]: kind = 'pixels' if fig: @@ -305,11 +306,16 @@ def det_pixels_plot(counts, norm, axes, clrmap, fig, last=False): Parameters ---------- - counts = data collection with the number of counts - norm = normalizes the data in the parentheses - axes = the axes in which the data will be plotted - clrmap = the colormap which will be used to visualize the data/counts - fig = sets the current figure + counts : `List` + data collection with the number of counts + norm : `function` + normalizes the data in the parentheses + axes : `matplotlib.axes` + the axes in which the data will be plotted + clrmap : `colormap` + the colormap which will be used to visualize the data/counts + fig : `matplotlib.figure` + the current figure to use Returns ------- From 2c3428d4b4fc3c3d897e61c29f5504f17be26598 Mon Sep 17 00:00:00 2001 From: Nicky Hochmuth Date: Fri, 2 Jul 2021 11:55:44 +0200 Subject: [PATCH 17/17] remove sample script for showing plots --- .gitignore | 5 +---- plottest.py | 37 ------------------------------------- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 plottest.py diff --git a/.gitignore b/.gitignore index c6a5b4d..649e24f 100644 --- a/.gitignore +++ b/.gitignore @@ -154,7 +154,4 @@ htmlcov/ #stixpy stixpy/data/*.fits -/Minergie Test Data/ -/Matplotlib Practice/ -.vscode/launch.json -.vscode/settings.json +.vscode/* diff --git a/plottest.py b/plottest.py deleted file mode 100644 index a2a91a2..0000000 --- a/plottest.py +++ /dev/null @@ -1,37 +0,0 @@ -from matplotlib import pyplot as plt -from sunpy.net import Fido, attrs as a -from sunpy.timeseries import TimeSeries -from pathlib import Path - -from stixpy.net.client import STIXClient # Need to import to register with Fido -from stixpy import timeseries # Need to import to register with timeseries -from stixpy.science import ScienceData -from stixcore.config.reader import read_subc_params -from stixpy.data import test - -# Ok this look like an interesting event let look for some pixel data -query = Fido.search(a.Time('2020-11-17T00:00', '2020-11-17T23:59'), a.Instrument.stix, a.stix.DataProduct.sci_xray_l1) -query -# Again the 2nd to last file seem to match the time range of interest -pd_file = Fido.fetch(query[0]) -pd = ScienceData.from_fits(pd_file[0]) -print(pd_file[0]) - -# jsut printg the object gives a textual overview, pixel data support the same plot methods as -# pd - -#l1 = ScienceData.from_fits(test.STIX_SCI_XRAY_L1) -#l2 = ScienceData.from_fits(test.STIX_SCI_XRAY_L2) -#l2.plot_pixels() - -# plot the pixel data as default "kind=pixels" -pd.plot_pixels(energy_indices=[[1, 5], [5, 20], [20, 30]]) -plt.show() - -# plot the pixel data as line chart with errorbars" -pd.plot_pixels(kind='errorbar', energy_indices=[[1, 5], [5, 20], [20, 30]]) -plt.show() - -# plot the detector configuration (independent on the actual pixeldata)" -pd.plot_pixels(kind='config') -plt.show()