def __init__(self, credo, title='Sample-to-detector distance calibration'): ToolDialog.__init__(self, credo, title=title, buttons=('OK', Gtk.ResponseType.OK, 'Apply', Gtk.ResponseType.APPLY, 'Cancel', Gtk.ResponseType.CANCEL)) vb = self.get_content_area() f = Gtk.Expander(label='Exposure') vb.pack_start(f, False, False, 0) es = ExposureSelector(credo) es.connect('open', self.do_load_exposure) f.add(es) f.set_expanded(True) hb = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) vb.pack_start(hb, True, True, 0) vb1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) hb.pack_start(vb1, False, False, 0) hb1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) vb1.pack_start(hb1, True, True, 0) self._treemodel = Gtk.ListStore(GObject.TYPE_PYOBJECT, # ErrorValue of uncalibrated data (pixel/radius) GObject.TYPE_PYOBJECT, # ErrorValue of calibrated data (q) GObject.TYPE_STRING, # String representation of uncalibrated data GObject.TYPE_STRING) # String representation of calibrated data self._treeview = Gtk.TreeView(self._treemodel) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) hb1.pack_start(sw, True, True, 0) sw.add(self._treeview) self._treeview.append_column(Gtk.TreeViewColumn('Pixel', Gtk.CellRendererText(), text=2)) self._treeview.append_column(Gtk.TreeViewColumn('q', Gtk.CellRendererText(), text=3)) self._treeview.set_rules_hint(True) self._treeview.set_headers_visible(True) self._treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self._treeview.set_size_request(150, -1) tv_buttonbox = Gtk.ButtonBox(orientation=Gtk.Orientation.VERTICAL) tv_buttonbox.set_layout(Gtk.ButtonBoxStyle.START) hb1.pack_start(tv_buttonbox, False, False, 0) b = Gtk.Button(label='Add', image=Gtk.Image.new_from_icon_name('list-add', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_add) b = Gtk.Button(label='Remove', image=Gtk.Image.new_from_icon_name('list-remove', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_remove) b = Gtk.Button(label='Clear', image=Gtk.Image.new_from_icon_name('edit-clear', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_clear) b = Gtk.Button(label='Save As', image=Gtk.Image.new_from_icon_name('document-save-as', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_saveas) b = Gtk.Button(label='Open', image=Gtk.Image.new_from_icon_name('document-open', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_open) b = Gtk.Button(label='Refresh', image=Gtk.Image.new_from_icon_name('view-refresh', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_refresh) self._findpeakbutton = Gtk.Button(label='Find peaks', image=Gtk.Image.new_from_icon_name('edit-find', Gtk.IconSize.BUTTON)) tv_buttonbox.add(self._findpeakbutton) self._findpeakbutton.connect('clicked', self._treeview_findpeak) self._findpeakbutton.set_sensitive(False) b = Gtk.Button(label='Export to HTML') tv_buttonbox.add(b) b.connect('clicked', self._treeview_export_html) vb2 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) hb.pack_start(vb2, True, True, 0) self._fig = Figure() self._canvas = FigureCanvasGTK3Agg(self._fig) self._canvas.set_size_request(400, 300) vb2.pack_start(self._canvas, True, True, 0) self._figtoolbar = NavigationToolbar2GTK3(self._canvas, None) vb2.pack_start(self._figtoolbar, False, False, 0) grid = Gtk.Grid() vb.pack_start(grid, False, False, 0) l = Gtk.Label(label='Wavelength:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 0, 0, 1, 1) self._wavelength_entry = Gtk.SpinButton( adjustment=Gtk.Adjustment(value=0.15418, lower=0, upper=100, step_increment=0.01, page_increment=0.1, page_size=0.1), digits=5) self._wavelength_entry.set_value(0.15418) grid.attach(self._wavelength_entry, 1, 0, 1, 1) l = Gtk.Label(label='Pixel size:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 2, 0, 1, 1) self._pixelsize_entry = Gtk.SpinButton( adjustment=Gtk.Adjustment(value=0.172, lower=0, upper=100, step_increment=0.01, page_increment=0.1), digits=3) self._pixelsize_entry.set_value(0.172) grid.attach(self._pixelsize_entry, 3, 0, 1, 1) l = Gtk.Label(label='Coefficient of determination (R2) of the fit:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 0, 1, 1, 1) self._r2_label = Gtk.Label(label='N/A') grid.attach(self._r2_label, 1, 1, 1, 1) l = Gtk.Label(label='Reduced Chi2 of the fit:') l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 2, 1, 1, 1) self._chi2_label = Gtk.Label(label='N/A') grid.attach(self._chi2_label, 3, 1, 1, 1) l = Gtk.Label(label='Sample-to-detector distance:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 0, 2, 1, 1) self._sddist_label = Gtk.Label(label='N/A') grid.attach(self._sddist_label, 1, 2, 1, 1)
class DistCalibrationDialog(ToolDialog): __gtype_name__ = 'SAXSCtrl_DistCalibrationDialog' def __init__(self, credo, title='Sample-to-detector distance calibration'): ToolDialog.__init__(self, credo, title=title, buttons=('OK', Gtk.ResponseType.OK, 'Apply', Gtk.ResponseType.APPLY, 'Cancel', Gtk.ResponseType.CANCEL)) vb = self.get_content_area() f = Gtk.Expander(label='Exposure') vb.pack_start(f, False, False, 0) es = ExposureSelector(credo) es.connect('open', self.do_load_exposure) f.add(es) f.set_expanded(True) hb = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) vb.pack_start(hb, True, True, 0) vb1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) hb.pack_start(vb1, False, False, 0) hb1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) vb1.pack_start(hb1, True, True, 0) self._treemodel = Gtk.ListStore(GObject.TYPE_PYOBJECT, # ErrorValue of uncalibrated data (pixel/radius) GObject.TYPE_PYOBJECT, # ErrorValue of calibrated data (q) GObject.TYPE_STRING, # String representation of uncalibrated data GObject.TYPE_STRING) # String representation of calibrated data self._treeview = Gtk.TreeView(self._treemodel) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) hb1.pack_start(sw, True, True, 0) sw.add(self._treeview) self._treeview.append_column(Gtk.TreeViewColumn('Pixel', Gtk.CellRendererText(), text=2)) self._treeview.append_column(Gtk.TreeViewColumn('q', Gtk.CellRendererText(), text=3)) self._treeview.set_rules_hint(True) self._treeview.set_headers_visible(True) self._treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self._treeview.set_size_request(150, -1) tv_buttonbox = Gtk.ButtonBox(orientation=Gtk.Orientation.VERTICAL) tv_buttonbox.set_layout(Gtk.ButtonBoxStyle.START) hb1.pack_start(tv_buttonbox, False, False, 0) b = Gtk.Button(label='Add', image=Gtk.Image.new_from_icon_name('list-add', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_add) b = Gtk.Button(label='Remove', image=Gtk.Image.new_from_icon_name('list-remove', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_remove) b = Gtk.Button(label='Clear', image=Gtk.Image.new_from_icon_name('edit-clear', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_clear) b = Gtk.Button(label='Save As', image=Gtk.Image.new_from_icon_name('document-save-as', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_saveas) b = Gtk.Button(label='Open', image=Gtk.Image.new_from_icon_name('document-open', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_open) b = Gtk.Button(label='Refresh', image=Gtk.Image.new_from_icon_name('view-refresh', Gtk.IconSize.BUTTON)) tv_buttonbox.add(b) b.connect('clicked', self._treeview_refresh) self._findpeakbutton = Gtk.Button(label='Find peaks', image=Gtk.Image.new_from_icon_name('edit-find', Gtk.IconSize.BUTTON)) tv_buttonbox.add(self._findpeakbutton) self._findpeakbutton.connect('clicked', self._treeview_findpeak) self._findpeakbutton.set_sensitive(False) b = Gtk.Button(label='Export to HTML') tv_buttonbox.add(b) b.connect('clicked', self._treeview_export_html) vb2 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) hb.pack_start(vb2, True, True, 0) self._fig = Figure() self._canvas = FigureCanvasGTK3Agg(self._fig) self._canvas.set_size_request(400, 300) vb2.pack_start(self._canvas, True, True, 0) self._figtoolbar = NavigationToolbar2GTK3(self._canvas, None) vb2.pack_start(self._figtoolbar, False, False, 0) grid = Gtk.Grid() vb.pack_start(grid, False, False, 0) l = Gtk.Label(label='Wavelength:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 0, 0, 1, 1) self._wavelength_entry = Gtk.SpinButton( adjustment=Gtk.Adjustment(value=0.15418, lower=0, upper=100, step_increment=0.01, page_increment=0.1, page_size=0.1), digits=5) self._wavelength_entry.set_value(0.15418) grid.attach(self._wavelength_entry, 1, 0, 1, 1) l = Gtk.Label(label='Pixel size:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 2, 0, 1, 1) self._pixelsize_entry = Gtk.SpinButton( adjustment=Gtk.Adjustment(value=0.172, lower=0, upper=100, step_increment=0.01, page_increment=0.1), digits=3) self._pixelsize_entry.set_value(0.172) grid.attach(self._pixelsize_entry, 3, 0, 1, 1) l = Gtk.Label(label='Coefficient of determination (R2) of the fit:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 0, 1, 1, 1) self._r2_label = Gtk.Label(label='N/A') grid.attach(self._r2_label, 1, 1, 1, 1) l = Gtk.Label(label='Reduced Chi2 of the fit:') l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 2, 1, 1, 1) self._chi2_label = Gtk.Label(label='N/A') grid.attach(self._chi2_label, 3, 1, 1, 1) l = Gtk.Label(label='Sample-to-detector distance:'); l.set_halign(Gtk.Align.START); l.set_valign(Gtk.Align.CENTER) grid.attach(l, 0, 2, 1, 1) self._sddist_label = Gtk.Label(label='N/A') grid.attach(self._sddist_label, 1, 2, 1, 1) def do_response(self, respid): if respid in (Gtk.ResponseType.OK, Gtk.ResponseType.APPLY) and hasattr(self, '_dist'): self.credo.dist = self._dist.val self.credo.dist_error = self._dist.err if respid in (Gtk.ResponseType.OK, Gtk.ResponseType.CANCEL): ToolDialog.do_response(self, respid) return def do_load_exposure(self, exposureselector, exposure): try: self._rad = exposure.radial_average(pixel=True) del exposure self._findpeakbutton.set_sensitive(True) except sastool.classes.SASExposureException: md = Gtk.MessageDialog(self.get_toplevel(), Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, 'Please load a mask!') md.run() md.destroy() del md def _treeview_add(self, button=None): self._treemodel.append((sastool.ErrorValue(0, 0), sastool.ErrorValue(0, 0), '0', '0')) def _treeview_remove(self, button=None): model, selection = self._treeview.get_selection().get_selected_rows() for row in reversed(selection): model.remove(self._treemodel.get_iter(row)) self._treeview_refresh() def _treeview_clear(self, button=None): self._treemodel.clear() def _treeview_saveas(self, button=None): pass def _treeview_open(self, button=None): pass def _treeview_export_html(self, button=None): htmlout = '<table border="1" cellpadding="1" cellspacing="1" style="width:500px">\n' htmlout = htmlout + ' <tr>\n' htmlout = htmlout + ' <th>Uncalibrated values (pixel)</th>\n' htmlout = htmlout + ' <th>Calibrated values (1/nm)</th>\n' htmlout = htmlout + ' <th>Determined from (calibration sample, peak nr.)</th>\n' htmlout = htmlout + ' </tr>\n' for uncal, cal, struncal, strcal in self._treemodel: htmlout = htmlout + ' <tr>\n' htmlout = htmlout + ' <td>%s</td>\n <td>%s</td>\n <td>...</td>\n' % (uncal.tostring(extra_digits=1), cal.tostring(extra_digits=1)) htmlout = htmlout + ' </tr>\n' htmlout = htmlout + '</table>\n' Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD).set_text(htmlout, -1) def _treeview_refresh(self, button=None): self._fig.clear() axes = self._fig.add_subplot(1, 1, 1) x = np.array([r[0].val for r in self._treemodel]) y = np.array([r[1].val for r in self._treemodel]) dx = np.array([r[0].err for r in self._treemodel]) dy = np.array([r[1].err for r in self._treemodel]) axes.errorbar(x, y, dx, dy, 'bo', label='Calibration points') def qfrompix(pix, pixelsize, wavelength, dist): return 4 * np.pi * np.sin(0.5 * np.arctan(pixelsize * pix / dist)) / wavelength if len(x) > 1: dist, stat = sastool.easylsq.nonlinear_leastsquares(x, y, dy, qfrompix, [sastool.FixedParameter(self._pixelsize_entry.get_value()), sastool.FixedParameter(self._wavelength_entry.get_value()), 100. ])[2:] pixscale = np.linspace(x.min(), x.max(), 100) self._r2_label.set_label(str(stat['R2'])) self._chi2_label.set_label(str(stat['Chi2_reduced'])) else: q = sastool.ErrorValue(y[0], dy[0]) pix = sastool.ErrorValue(x[0], dx[0]) dist = self._pixelsize_entry.get_value() * pix / np.tan(np.arcsin(q * self._wavelength_entry.get_value() / (4 * np.pi)) * 2) pixscale = np.linspace(0, float(pix), 100) self._r2_label.set_label('N/A') self._chi2_label.set_label('N/A') self._sddist_label.set_label(dist.tostring(extra_digits=3)) self._dist = dist axes.plot(pixscale, qfrompix(pixscale, self._pixelsize_entry.get_value(), self._wavelength_entry.get_value(), dist), 'r-', label='Calibration curve from LSQ fit') axes.set_xlabel('Pixels') axes.set_ylabel('q') axes.legend(loc='best') self._fig.canvas.draw() def _treeview_findpeak(self, button=None): pf = PeakFinder(self._rad) res = Gtk.ResponseType.APPLY conn = pf.connect('peak-found', self._on_peak_found) try: res = pf.run() finally: pf.disconnect(conn) pf.destroy() def _on_peak_found(self, peakfinder, a, x0, sigma, y0, stat, cal): if not isinstance(cal, sastool.ErrorValue): uncal = sastool.ErrorValue(cal) self._treemodel.append((x0, cal, unicode(x0), unicode(cal))) self._treeview_refresh()