BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
SaveProjectionsAssistant.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Projection/SaveProjectionsAssistant.cpp
6 //! @brief Implements class SaveProjectionsAssistant
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include "Base/Py/PyFmt.h"
17 #include "Device/Data/Datafield.h"
24 #include "GUI/Util/Error.h"
25 #include <QFileDialog>
26 #include <QTextStream>
27 
28 #include <boost/polymorphic_cast.hpp>
29 
30 using boost::polymorphic_downcast;
31 
32 namespace {
33 
34 const int bin_centers_colwidth = 12;
35 const int bin_values_colwidth = 20;
36 
37 QString to_scientific_str(double value)
38 {
39  auto str = Py::Fmt::printScientificDouble(value);
40  return QString("%1").arg(QString::fromStdString(str), -bin_values_colwidth);
41 }
42 
43 QString to_double_str(double value)
44 {
45  auto str = Py::Fmt::printDouble(value);
46  return QString("%1").arg(QString::fromStdString(str), -bin_centers_colwidth);
47 }
48 
49 bool vert_less_posx(SessionItem* item1, SessionItem* item2)
50 {
51  return polymorphic_downcast<VerticalLineItem*>(item1)->posX()
52  < polymorphic_downcast<VerticalLineItem*>(item2)->posX();
53 }
54 
55 bool horiz_less_posy(SessionItem* item1, SessionItem* item2)
56 {
57  return polymorphic_downcast<HorizontalLineItem*>(item1)->posY()
58  < polymorphic_downcast<HorizontalLineItem*>(item2)->posY();
59 }
60 
61 } // namespace
62 
65 
66 //! Calls file open dialog and writes projection data as ASCII
67 
68 void SaveProjectionsAssistant::saveProjections(QWidget* parent, IntensityDataItem* intensityItem)
69 {
70  ASSERT(intensityItem);
71 
72  QString defaultName = gSessionData->projectDocument.value()->userExportDir() + "/untitled.txt";
73  QString fileName = QFileDialog::getSaveFileName(
74  parent, "Save projections data", defaultName, "", nullptr,
75  appSettings->useNativeFileDialog() ? QFileDialog::Options()
76  : QFileDialog::DontUseNativeDialog);
77 
78  if (fileName.isEmpty())
79  return;
80 
81  QFile file(fileName);
82  if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
83  throw Error("TestGUI::Project::Utils::createTestFile() -> Error. "
84  "Can't create file");
85 
86  m_field.reset(intensityItem->getDatafield());
87 
88  QTextStream out(&file);
89 
90  out << "# Projections along x-axis (horizontal projections) \n";
91  out << projectionsToString(HorizontalLineItem::M_TYPE, intensityItem);
92  out << "\n";
93 
94  out << "# Projections along y-axis (vertical projections) \n";
95  out << projectionsToString(VerticalLineItem::M_TYPE, intensityItem);
96  out << "\n";
97 
98  file.close();
99 }
100 
101 //! Generates multi-line string with projections data of given type (horizontal, vertical).
102 
103 QString SaveProjectionsAssistant::projectionsToString(const QString& projectionsType,
104  IntensityDataItem* intensityItem)
105 {
106  QString result;
107  QTextStream out(&result);
108 
109  auto projData = projectionsData(projectionsType, intensityItem);
110 
111  if (projData.projections.isEmpty())
112  return result;
113 
114  out << projectionFileHeader(projData);
115 
116  auto bin_centers = projData.bin_centers;
117 
118  for (int i_point = 0; i_point < bin_centers.size(); ++i_point) {
119  out << to_double_str(bin_centers[i_point]) << " ";
120  for (auto& data : projData.projections)
121  out << to_scientific_str(data.bin_values[i_point]);
122  out << "\n";
123  }
124  return result;
125 }
126 
127 //! Returns projections data for all projections of given type (horizontal, vertical).
128 
130 SaveProjectionsAssistant::projectionsData(const QString& projectionsType,
131  IntensityDataItem* intensityItem)
132 {
133  ProjectionsData result;
134  result.is_horizontal = (projectionsType != VerticalLineItem::M_TYPE);
135 
136  for (auto* item : projectionItems(projectionsType, intensityItem)) {
137  std::unique_ptr<Datafield> field;
139 
140  if (item->modelType() == HorizontalLineItem::M_TYPE) {
141  data.axis_value = polymorphic_downcast<HorizontalLineItem*>(item)->posY();
142  field.reset(m_field->xProjection(data.axis_value));
143  } else {
144  data.axis_value = polymorphic_downcast<VerticalLineItem*>(item)->posX();
145  field.reset(m_field->yProjection(data.axis_value));
146  }
147 
148 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
149  auto values = field->flatVector();
150  auto centers = field->axis(0).binCenters();
151  data.bin_values = QVector<double>(values.begin(), values.end());
152  if (result.bin_centers.isEmpty())
153  result.bin_centers = QVector<double>(centers.begin(), centers.end());
154 #else
155  data.bin_values = QVector<double>::fromStdVector(hist->binValues());
156  if (result.bin_centers.isEmpty())
157  result.bin_centers = QVector<double>::fromStdVector(hist->binCenters());
158 #endif
159 
160  result.projections.push_back(data);
161  }
162  return result;
163 }
164 
165 //! Returns vector of ProjectionItems sorted according to axis value.
166 
167 QVector<SessionItem*> SaveProjectionsAssistant::projectionItems(const QString& projectionsType,
168  IntensityDataItem* intensityItem)
169 {
170  auto result = intensityItem->projectionContainerItem()->childrenOfType(projectionsType);
171  std::sort(result.begin(), result.end(),
172  projectionsType == HorizontalLineItem::M_TYPE ? horiz_less_posy : vert_less_posx);
173  return result;
174 }
175 
176 //! Returns projections header. For projections along x it will be
177 //! "# x y=6.0194 y=33.5922 y=61.9417"
178 
180 {
181  QString xcol, ycol;
182 
183  projectionsData.is_horizontal ? xcol = "# x" : xcol = "# y";
184  projectionsData.is_horizontal ? ycol = " y=" : ycol = " x=";
185 
186  QString result;
187  result.append(QString("%1").arg(xcol, -bin_centers_colwidth));
188 
189  for (auto& data : projectionsData.projections)
190  result.append(QString("%1%2").arg(ycol).arg(data.axis_value,
191  -(bin_values_colwidth - ycol.size()), 'f', 4));
192  result.append("\n");
193 
194  return result;
195 }
ApplicationSettings * appSettings
global pointer to the instance
Defines class ApplicationSettings.
Defines error class.
Defines class IntensityDataItem.
Defines MaskItems classes.
Defines class ProjectDocument.
Defines items related to projections over color map.
Defines class SaveProjectionsAssistant.
SessionData * gSessionData
global pointer to the single instance
Definition: SessionData.cpp:17
Defines struct SessionData.
bool useNativeFileDialog() const
Datafield * getDatafield()
Definition: DataItem.h:41
static constexpr auto M_TYPE
Definition: MaskItems.h:147
ProjectionContainerItem * projectionContainerItem()
QString projectionFileHeader(ProjectionsData &projectionsData)
Returns projections header. For projections along x it will be "# x y=6.0194 y=33....
std::unique_ptr< Datafield > m_field
ProjectionsData projectionsData(const QString &projectionsType, IntensityDataItem *intensityItem)
Returns projections data for all projections of given type (horizontal, vertical).
QString projectionsToString(const QString &projectionsType, IntensityDataItem *intensityItem)
Generates multi-line string with projections data of given type (horizontal, vertical).
QVector< SessionItem * > projectionItems(const QString &projectionsType, IntensityDataItem *intensityItem)
Returns vector of ProjectionItems sorted according to axis value.
void saveProjections(QWidget *parent, IntensityDataItem *intensityItem)
Calls file open dialog and writes projection data as ASCII.
Base class for a GUI data item.
Definition: SessionItem.h:204
QVector< SessionItem * > childrenOfType(const QString &model_type) const
Returns a vector of all children of the given type.
static constexpr auto M_TYPE
Definition: MaskItems.h:131
double axis_value
value on axis where projection has been made
std::optional< ProjectDocument * > projectDocument
Definition: SessionData.h:27