api: record the beam size at the sample, and write it where NXmx puts it
dataset_settings gains beam_size_x_um and beam_size_y_um, the horizontal and vertical size of the X-ray beam where it meets the sample. They follow the same route total_flux takes - OpenAPI, DatasetSettings, the CBOR start message, the HDF5 master, and back out of a stored file - and nothing consumes them; this is metadata a beamline can state and a downstream program can read. NXmx puts this in the application definition rather than the base class: not NXbeam's extent (rank 2, nP x 2, per scan point, always FWHM of a rectangular aperture) but NXmx's own incident_beam_size, a recommended rank-1 two-element array in the order x, y. Both are live and neither is deprecated, so the choice matters; the MX definition wins in an MX file. Written as one array with a units attribute of "m", like every other length in the master, so the settings hold micrometres and FillMessage converts once. The unit table of ReadLength_m becomes LengthUnitFactor so the array read can share it: a master written elsewhere may state this in millimetres. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
This commit is contained in:
1 parent
7890149ad6
commit
8a04773d1d
20 files changed
+253
-10
No files matched your search
@@ -663,6 +663,10 @@ DatasetSettings Convert(const org::openapitools::server::model::Dataset_settings
|
||||
|
||||
if (input.totalFluxIsSet())
|
||||
ret.TotalFlux(input.getTotalFlux());
|
||||
if (input.beamSizeXUmIsSet())
|
||||
ret.BeamSizeX_um(input.getBeamSizeXUm());
|
||||
if (input.beamSizeYUmIsSet())
|
||||
ret.BeamSizeY_um(input.getBeamSizeYUm());
|
||||
if (input.transmissionIsSet())
|
||||
ret.AttenuatorTransmission(input.getTransmission());
|
||||
// Not alternatives: a grid scan is often collected at a given head position, so an axis and a
|
||||
|
||||
@@ -45,6 +45,10 @@ Dataset_settings::Dataset_settings()
|
||||
m_Total_fluxIsSet = false;
|
||||
m_Transmission = 0.0f;
|
||||
m_TransmissionIsSet = false;
|
||||
m_Beam_size_x_um = 0.0f;
|
||||
m_Beam_size_x_umIsSet = false;
|
||||
m_Beam_size_y_um = 0.0f;
|
||||
m_Beam_size_y_umIsSet = false;
|
||||
m_GoniometerIsSet = false;
|
||||
m_Grid_scanIsSet = false;
|
||||
m_Header_appendixIsSet = false;
|
||||
@@ -237,6 +241,34 @@ bool Dataset_settings::validate(std::stringstream& msg, const std::string& pathP
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (beamSizeXUmIsSet())
|
||||
{
|
||||
const float& value = m_Beam_size_x_um;
|
||||
const std::string currentValuePath = _pathPrefix + ".beamSizeXUm";
|
||||
|
||||
|
||||
if (value < static_cast<float>(0.0))
|
||||
{
|
||||
success = false;
|
||||
msg << currentValuePath << ": must be greater than or equal to 0.0;";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (beamSizeYUmIsSet())
|
||||
{
|
||||
const float& value = m_Beam_size_y_um;
|
||||
const std::string currentValuePath = _pathPrefix + ".beamSizeYUm";
|
||||
|
||||
|
||||
if (value < static_cast<float>(0.0))
|
||||
{
|
||||
success = false;
|
||||
msg << currentValuePath << ": must be greater than or equal to 0.0;";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (dataReductionFactorSerialmxIsSet())
|
||||
{
|
||||
@@ -478,6 +510,12 @@ bool Dataset_settings::operator==(const Dataset_settings& rhs) const
|
||||
((!transmissionIsSet() && !rhs.transmissionIsSet()) || (transmissionIsSet() && rhs.transmissionIsSet() && getTransmission() == rhs.getTransmission())) &&
|
||||
|
||||
|
||||
((!beamSizeXUmIsSet() && !rhs.beamSizeXUmIsSet()) || (beamSizeXUmIsSet() && rhs.beamSizeXUmIsSet() && getBeamSizeXUm() == rhs.getBeamSizeXUm())) &&
|
||||
|
||||
|
||||
((!beamSizeYUmIsSet() && !rhs.beamSizeYUmIsSet()) || (beamSizeYUmIsSet() && rhs.beamSizeYUmIsSet() && getBeamSizeYUm() == rhs.getBeamSizeYUm())) &&
|
||||
|
||||
|
||||
((!goniometerIsSet() && !rhs.goniometerIsSet()) || (goniometerIsSet() && rhs.goniometerIsSet() && getGoniometer() == rhs.getGoniometer())) &&
|
||||
|
||||
|
||||
@@ -587,6 +625,10 @@ void to_json(nlohmann::json& j, const Dataset_settings& o)
|
||||
j["total_flux"] = o.m_Total_flux;
|
||||
if(o.transmissionIsSet())
|
||||
j["transmission"] = o.m_Transmission;
|
||||
if(o.beamSizeXUmIsSet())
|
||||
j["beam_size_x_um"] = o.m_Beam_size_x_um;
|
||||
if(o.beamSizeYUmIsSet())
|
||||
j["beam_size_y_um"] = o.m_Beam_size_y_um;
|
||||
if(o.goniometerIsSet())
|
||||
j["goniometer"] = o.m_Goniometer;
|
||||
if(o.gridScanIsSet())
|
||||
@@ -696,6 +738,16 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
|
||||
j.at("transmission").get_to(o.m_Transmission);
|
||||
o.m_TransmissionIsSet = true;
|
||||
}
|
||||
if(j.find("beam_size_x_um") != j.end())
|
||||
{
|
||||
j.at("beam_size_x_um").get_to(o.m_Beam_size_x_um);
|
||||
o.m_Beam_size_x_umIsSet = true;
|
||||
}
|
||||
if(j.find("beam_size_y_um") != j.end())
|
||||
{
|
||||
j.at("beam_size_y_um").get_to(o.m_Beam_size_y_um);
|
||||
o.m_Beam_size_y_umIsSet = true;
|
||||
}
|
||||
if(j.find("goniometer") != j.end())
|
||||
{
|
||||
j.at("goniometer").get_to(o.m_Goniometer);
|
||||
@@ -1026,6 +1078,40 @@ void Dataset_settings::unsetTransmission()
|
||||
{
|
||||
m_TransmissionIsSet = false;
|
||||
}
|
||||
float Dataset_settings::getBeamSizeXUm() const
|
||||
{
|
||||
return m_Beam_size_x_um;
|
||||
}
|
||||
void Dataset_settings::setBeamSizeXUm(float const value)
|
||||
{
|
||||
m_Beam_size_x_um = value;
|
||||
m_Beam_size_x_umIsSet = true;
|
||||
}
|
||||
bool Dataset_settings::beamSizeXUmIsSet() const
|
||||
{
|
||||
return m_Beam_size_x_umIsSet;
|
||||
}
|
||||
void Dataset_settings::unsetBeam_size_x_um()
|
||||
{
|
||||
m_Beam_size_x_umIsSet = false;
|
||||
}
|
||||
float Dataset_settings::getBeamSizeYUm() const
|
||||
{
|
||||
return m_Beam_size_y_um;
|
||||
}
|
||||
void Dataset_settings::setBeamSizeYUm(float const value)
|
||||
{
|
||||
m_Beam_size_y_um = value;
|
||||
m_Beam_size_y_umIsSet = true;
|
||||
}
|
||||
bool Dataset_settings::beamSizeYUmIsSet() const
|
||||
{
|
||||
return m_Beam_size_y_umIsSet;
|
||||
}
|
||||
void Dataset_settings::unsetBeam_size_y_um()
|
||||
{
|
||||
m_Beam_size_y_umIsSet = false;
|
||||
}
|
||||
org::openapitools::server::model::Rotation_axis Dataset_settings::getGoniometer() const
|
||||
{
|
||||
return m_Goniometer;
|
||||
|
||||
@@ -155,6 +155,20 @@ public:
|
||||
bool transmissionIsSet() const;
|
||||
void unsetTransmission();
|
||||
/// <summary>
|
||||
/// First element of /entry/instrument/beam/incident_beam_size in NXmx Horizontal size of the X-ray beam where it meets the sample - the FWHM of a focused beam, the full width of a slit-defined one. [um]
|
||||
/// </summary>
|
||||
float getBeamSizeXUm() const;
|
||||
void setBeamSizeXUm(float const value);
|
||||
bool beamSizeXUmIsSet() const;
|
||||
void unsetBeam_size_x_um();
|
||||
/// <summary>
|
||||
/// Second element of /entry/instrument/beam/incident_beam_size in NXmx Vertical size of the X-ray beam where it meets the sample. [um]
|
||||
/// </summary>
|
||||
float getBeamSizeYUm() const;
|
||||
void setBeamSizeYUm(float const value);
|
||||
bool beamSizeYUmIsSet() const;
|
||||
void unsetBeam_size_y_um();
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
org::openapitools::server::model::Rotation_axis getGoniometer() const;
|
||||
@@ -361,6 +375,10 @@ protected:
|
||||
bool m_Total_fluxIsSet;
|
||||
float m_Transmission;
|
||||
bool m_TransmissionIsSet;
|
||||
float m_Beam_size_x_um;
|
||||
bool m_Beam_size_x_umIsSet;
|
||||
float m_Beam_size_y_um;
|
||||
bool m_Beam_size_y_umIsSet;
|
||||
org::openapitools::server::model::Rotation_axis m_Goniometer;
|
||||
bool m_GoniometerIsSet;
|
||||
org::openapitools::server::model::Grid_scan m_Grid_scan;
|
||||
|
||||
@@ -476,6 +476,21 @@ components:
|
||||
description: |
|
||||
/entry/instrument/attenuator/attenuator_transmission
|
||||
Transmission of attenuator (filter) [no units]
|
||||
beam_size_x_um:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0.0
|
||||
description: |
|
||||
First element of /entry/instrument/beam/incident_beam_size in NXmx
|
||||
Horizontal size of the X-ray beam where it meets the sample - the FWHM of a focused beam,
|
||||
the full width of a slit-defined one. [um]
|
||||
beam_size_y_um:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0.0
|
||||
description: |
|
||||
Second element of /entry/instrument/beam/incident_beam_size in NXmx
|
||||
Vertical size of the X-ray beam where it meets the sample. [um]
|
||||
goniometer:
|
||||
$ref: "#/components/schemas/rotation_axis"
|
||||
grid_scan:
|
||||
|
||||
@@ -466,6 +466,11 @@ Sample name</p>
|
||||
Flux incident on beam plane in photons per second. In other words this is the flux integrated over area. [photons/s]</p>
|
||||
</div></div></div></td></tr><tr class=""><td class="sc-dLMFU sc-eldPxv hZbWKe jXkfaY" kind="field" title="transmission"><span class="sc-gFqAkR eRqgPI"></span><span class="property-name">transmission</span></td><td class="sc-fPXMVe bAXEAa"><div><div><span class="sc-Nxspf sc-cfxfcM cXxAXt jrGEaR"></span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr">number</span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr"> <!-- --><<!-- -->float<!-- -->><!-- --> </span><span> <span class="sc-Nxspf sc-fxwrCY cXxAXt eMVOei"> <!-- -->[ 0 .. 1 ]<!-- --> </span></span></div> <div><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>/entry/instrument/attenuator/attenuator_transmission
|
||||
Transmission of attenuator (filter) [no units]</p>
|
||||
</div></div></div></td></tr><tr class=""><td class="sc-dLMFU sc-eldPxv hZbWKe jXkfaY" kind="field" title="beam_size_x_um"><span class="sc-gFqAkR eRqgPI"></span><span class="property-name">beam_size_x_um</span></td><td class="sc-fPXMVe bAXEAa"><div><div><span class="sc-Nxspf sc-cfxfcM cXxAXt jrGEaR"></span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr">number</span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr"> <!-- --><<!-- -->float<!-- -->><!-- --> </span><span> <span class="sc-Nxspf sc-fxwrCY cXxAXt eMVOei"> <!-- -->>= 0<!-- --> </span></span></div> <div><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>First element of /entry/instrument/beam/incident_beam_size in NXmx
|
||||
Horizontal size of the X-ray beam where it meets the sample - the FWHM of a focused beam,
|
||||
the full width of a slit-defined one. [um]</p>
|
||||
</div></div></div></td></tr><tr class=""><td class="sc-dLMFU sc-eldPxv hZbWKe jXkfaY" kind="field" title="beam_size_y_um"><span class="sc-gFqAkR eRqgPI"></span><span class="property-name">beam_size_y_um</span></td><td class="sc-fPXMVe bAXEAa"><div><div><span class="sc-Nxspf sc-cfxfcM cXxAXt jrGEaR"></span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr">number</span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr"> <!-- --><<!-- -->float<!-- -->><!-- --> </span><span> <span class="sc-Nxspf sc-fxwrCY cXxAXt eMVOei"> <!-- -->>= 0<!-- --> </span></span></div> <div><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>Second element of /entry/instrument/beam/incident_beam_size in NXmx
|
||||
Vertical size of the X-ray beam where it meets the sample. [um]</p>
|
||||
</div></div></div></td></tr><tr class=""><td class="sc-dLMFU sc-eldPxv sc-hCPjZK hZbWKe jXkfaY GCgeS" kind="field" title="goniometer"><span class="sc-gFqAkR eRqgPI"></span><button aria-label="expand goniometer"><span class="property-name">goniometer</span><svg class="sc-cwHptR ivsSRP" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button></td><td class="sc-fPXMVe bAXEAa"><div><div><span class="sc-Nxspf sc-cfxfcM cXxAXt jrGEaR"></span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr">object</span><span class="sc-Nxspf sc-gmPhUn cXxAXt hjnRRA"> (<!-- -->rotation_axis<!-- -->) </span></div> <div><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>Definition of a crystal rotation axis</p>
|
||||
</div></div></div></td></tr><tr class=""><td class="sc-dLMFU sc-eldPxv sc-hCPjZK hZbWKe jXkfaY GCgeS" kind="field" title="grid_scan"><span class="sc-gFqAkR eRqgPI"></span><button aria-label="expand grid_scan"><span class="property-name">grid_scan</span><svg class="sc-cwHptR ivsSRP" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button></td><td class="sc-fPXMVe bAXEAa"><div><div><span class="sc-Nxspf sc-cfxfcM cXxAXt jrGEaR"></span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr">object</span><span class="sc-Nxspf sc-gmPhUn cXxAXt hjnRRA"> (<!-- -->grid_scan<!-- -->) </span></div> <div><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>Definition of a grid scan. May be combined with a goniometer axis: a grid is often collected
|
||||
at a particular head position, and a stationary axis records where that was.</p>
|
||||
@@ -517,7 +522,7 @@ Assuming that Smargon is used as static positioner and not moving during the sca
|
||||
</div></button></div><div><button class="sc-kzqdkY bXzzUN"><svg class="sc-cwHptR cSkZlF" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-dSIIpw bpEYcE">400<!-- --> </strong><div class="sc-eeDRCY sc-eBMEME sc-dCFHLb gTGgei kekOtA kCaLQd"><p>Input parsing or validation error</p>
|
||||
</div></button></div><div><button class="sc-kzqdkY bXzzUN"><svg class="sc-cwHptR cSkZlF" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-dSIIpw bpEYcE">500<!-- --> </strong><div class="sc-eeDRCY sc-eBMEME sc-dCFHLb gTGgei kekOtA kCaLQd"><p>Error within Jungfraujoch code - see output message.</p>
|
||||
</div></button></div></div></div><div class="sc-iGgWBj sc-gsFSXq ibAZSi eDeKjd"><div class="sc-ejfMa-d bNUPQg"><button class="sc-EgOXT cFEcOl"><span type="post" class="sc-eZYNyq fPdOXD http-verb post">post</span><span class="sc-iEXKAA gUNSDu">/start</span><svg class="sc-cwHptR iVFMLx" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-dlWCHZ kWacYr"><div class="sc-hHOBiw cndTNO"><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>Test Jungfraujoch system</p>
|
||||
</div><div tabindex="0" role="button"><div class="sc-kWtpeL gEncxT"><span>http://localhost:5232</span>/start</div></div></div></div></div><div><h3 class="sc-kpDqfm eBBgSB"> <!-- -->Request samples<!-- --> </h3><div class="sc-bXCLTC dHowgL" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="react-tabs__tab react-tabs__tab--selected" role="tab" id="tab_R_ii2a_0" aria-selected="true" aria-disabled="false" aria-controls="panel_R_ii2a_0" tabindex="0" data-rttab="true">Payload</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel_R_ii2a_0" aria-labelledby="tab_R_ii2a_0"><div><div class="sc-bbSZdi gCVTxk"><span class="sc-fjvvzt jWReSk">Content type</span><div class="sc-JrDLc iTKzPJ">application/json</div></div><div class="sc-uVWWZ gQROPU"><div class="sc-esYiGF dWQNJI"><div class="sc-koXPp efufqz"><button><div class="sc-fhzFiK kwZDms">Copy</div></button><button> Expand all </button><button> Collapse all </button></div><div tabindex="0" class="sc-eeDRCY gTGgei sc-fXSgeo bnrBiz"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"images_per_trigger"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"ntrigger"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"image_time_us"</span>: <span class="token number">0</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"beam_x_pxl"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"beam_y_pxl"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"detector_distance_mm"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"incident_energy_keV"</span>: <span class="token number">0.001</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"file_prefix"</span>: <span class="token string">""</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"images_per_file"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"space_group_number"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"sample_name"</span>: <span class="token string">""</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"compression"</span>: <span class="token string">"bslz4"</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"total_flux"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"transmission"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"goniometer"</span>: <button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable collapsed"><span class="property token string">"name"</span>: <span class="token string">"omega"</span><span class="token punctuation">,</span></div></li><li><div class="hoverable collapsed"><span class="property token string">"step"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable collapsed"><span class="property token string">"start"</span>: <span class="token number">50</span><span class="token punctuation">,</span></div></li><li><div class="hoverable collapsed"><span class="property token string">"vector"</span>: <button class="collapser" aria-label="expand"></button><span class="token punctuation">[</span><span class="ellipsis"></span><ul class="array collapsible"><li><div class="hoverable collapsed"><span class="token number">1</span>,</div></li><li><div class="hoverable collapsed"><span class="token number">0</span>,</div></li><li><div class="hoverable collapsed"><span class="token number">0</spaLine truncated
|
||||
</div><div tabindex="0" role="button"><div class="sc-kWtpeL gEncxT"><span>http://localhost:5232</span>/start</div></div></div></div></div><div><h3 class="sc-kpDqfm eBBgSB"> <!-- -->Request samples<!-- --> </h3><div class="sc-bXCLTC dHowgL" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="react-tabs__tab react-tabs__tab--selected" role="tab" id="tab_R_ii2a_0" aria-selected="true" aria-disabled="false" aria-controls="panel_R_ii2a_0" tabindex="0" data-rttab="true">Payload</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel_R_ii2a_0" aria-labelledby="tab_R_ii2a_0"><div><div class="sc-bbSZdi gCVTxk"><span class="sc-fjvvzt jWReSk">Content type</span><div class="sc-JrDLc iTKzPJ">application/json</div></div><div class="sc-uVWWZ gQROPU"><div class="sc-esYiGF dWQNJI"><div class="sc-koXPp efufqz"><button><div class="sc-fhzFiK kwZDms">Copy</div></button><button> Expand all </button><button> Collapse all </button></div><div tabindex="0" class="sc-eeDRCY gTGgei sc-fXSgeo bnrBiz"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"images_per_trigger"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"ntrigger"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"image_time_us"</span>: <span class="token number">0</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"beam_x_pxl"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"beam_y_pxl"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"detector_distance_mm"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"incident_energy_keV"</span>: <span class="token number">0.001</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"file_prefix"</span>: <span class="token string">""</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"images_per_file"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"space_group_number"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"sample_name"</span>: <span class="token string">""</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"compression"</span>: <span class="token string">"bslz4"</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"total_flux"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"transmission"</span>: <span class="token number">1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"beam_size_x_um"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"beam_size_y_um"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"goniometer"</span>: <button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable collapsed"><span class="property token string">"name"</span>: <span class="token string">"omega"</span><span class="token punctuation">,</span></div></li><li><div class="hoverable collapsed"><span class="property token string">"step"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable collapsed"><span class="property token string">"start"</span>: <span class="token number">50</span><span class="token punctuation">,</span></div></li><li><div class="hoverable collapsed"><span class="property token string">"vector"</span>: <button class="collapser" aria-label="eLine truncated
|
||||
To not block web server for a indefinite period of time, the procedure is provided with a timeout.
|
||||
Extending timeout is possible, but requires to ensure safety that client will not close the connection and retry the connection.</p>
|
||||
</div></div><div><h5 class="sc-dAlyuH jbQuod">query<!-- --> Parameters</h5><table class="sc-dAbbOL ccPhmY"><tbody><tr class="last "><td class="sc-dLMFU sc-eldPxv hZbWKe jXkfaY" kind="field" title="timeout"><span class="sc-gFqAkR eRqgPI"></span><span class="property-name">timeout</span></td><td class="sc-fPXMVe bAXEAa"><div><div><span class="sc-Nxspf sc-cfxfcM cXxAXt jrGEaR"></span><span class="sc-Nxspf sc-gFAWRd cXxAXt dYzdDr">integer</span><span> <span class="sc-Nxspf sc-fxwrCY cXxAXt eMVOei"> <!-- -->[ 0 .. 3600 ]<!-- --> </span></span></div><div><span class="sc-Nxspf cXxAXt"> <!-- -->Default:<!-- --> </span> <span class="sc-Nxspf sc-ddjGPC cXxAXt jZOCAW">60</span></div> <div><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>Timeout in seconds (0 == immediate response)</p>
|
||||
@@ -988,7 +993,7 @@ then image might be replaced in the buffer between calling /images and /image.cb
|
||||
</div></button></div></div></div><div class="sc-iGgWBj sc-gsFSXq ibAZSi eDeKjd"><div class="sc-ejfMa-d bNUPQg"><button class="sc-EgOXT cFEcOl"><span type="get" class="sc-eZYNyq qGfV http-verb get">get</span><span class="sc-iEXKAA gUNSDu">/version</span><svg class="sc-cwHptR iVFMLx" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-dlWCHZ kWacYr"><div class="sc-hHOBiw cndTNO"><div class="sc-eeDRCY sc-eBMEME gTGgei fbXBig"><p>Test Jungfraujoch system</p>
|
||||
</div><div tabindex="0" role="button"><div class="sc-kWtpeL gEncxT"><span>http://localhost:5232</span>/version</div></div></div></div></div></div></div></div></div><div class="sc-dExYaf gZbfaQ"></div></div></div>
|
||||
<script>
|
||||
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.3","info":{"title":"Jungfraujoch","description":"API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland).\nJungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU.\nJungfraujoch uses FPGA boards to acquire data at high data rates.\n\n# License Clarification\n\nWhile this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply**\nwhen this file is used solely to generate OpenAPI clients or when implementing applications that\ninteract with the API. Generated client code and applications using this API definition are not\nsubject to the GPL license requirements and may be distributed under terms of your choosing.\n\nThis exception is similar in spirit to the Linux Kernel's approach to userspace API headers and\nthe GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that\nuser programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not\nderivative works of the kernel and are not subject to the terms of the GPL.\n\nThis exception is intended to allow wider use of this API specification without imposing GPL\nrequirements on applications that merely interact with the API, regardless of whether they\ncommunicate through network calls or other mechanisms.\n","version":"1.0.0-rc.166","contact":{"name":"Filip Leonarski (Paul Scherrer Institute)","email":"filip.leonarski@psi.ch"},"license":{"name":"GPL-3.0","url":"https://www.gnu.org/licenses/gpl-3.0.html"}},"servers":[{"url":"http://localhost:5232","description":"Test Jungfraujoch system"}],"components":{"parameters":{"binning":{"in":"query","name":"binning","required":false,"schema":{"default":1,"type":"integer"},"description":"Binning of frames for the plot (0 = default binning)"},"experimental_coord":{"in":"query","name":"experimental_coord","required":false,"schema":{"type":"boolean","default":false},"description":"If measurement has goniometer axis defined, plot X-axis will represent rotation angle\nIf measurement has grid scan defined, plot X-axis and Y-axis will represent grid position, Z will be used as the final value\nFor still measurement the number is ignored\n"},"azint_unit":{"in":"query","name":"azint_unit","required":false,"schema":{"type":"string","enum":["Q_recipA","d_A","two_theta_deg"],"default":"Q_recipA"},"description":"Unit used for azim int.\n"},"fill_value":{"in":"query","name":"fill","required":false,"schema":{"type":"number","format":"float"},"description":"Fill value for elements that were missed during data collection\n"},"plot_type":{"in":"query","name":"type","required":true,"description":"Type of requested plot","schema":{"type":"string","enum":["bkg_estimate","azint","azint_1d","spot_count","spot_count_low_res","spot_count_indexed","spot_count_ice","indexing_rate","indexing_lattice_count","indexing_unit_cell_length","indexing_unit_cell_angle","profile_radius","mosaicity","b_factor","error_pixels","saturated_pixels","image_collection_efficiency","receiver_delay","receiver_free_send_buf","strong_pixels","roi_sum","roi_mean","roi_max_count","roi_pixels","roi_weighted_x","roi_weighted_y","packets_received","max_pixel_value","resolution_estimate","pixel_sum","processing_time","beam_center_x","beam_center_y","integrated_reflections","image_scale_factor","image_scale_cc","compression_ratio","ice_ring_score"]}},"roi":{"in":"query","name":"roi","required":false,"schema":{"type":"string","minLength":1},"description":"Name of ROI for which plot is requested"},"image_id":{"in":"query","name":"id","required":false,"schema":{"type":"integer","format":"int64","default":-1,"minimum":-2},"description":"Image ID in the image buffer. Special values: -1 - last image in the buffer, -2: last indexed image in the buffer"},"saturation":{"in":"query","name":"saturation","required":false,"schema":{"type":"number","format":"float","minimum":-32767,"maximum":32767},"description":"Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used"},"background":{"in":"query","name":"background","required":false,"schema":{"type":"number","format":"float","default":0,"minimum":-32767,"maximum":32767},"description":"Background value to set contrast in the preview image"},"show_spots":{"in":"query","name":"show_spots","schema":{"type":"boolean","default":true},"description":"Show spot finding results on the image"},"show_predictions":{"in":"query","name":"show_predictions","schema":{"type":"boolean","default":false},"description":"Show Bragg spot predictions on the image (if available for the image)"},"show_beam_center":{"in":"query","name":"show_beam_center","schema":{"type":"boolean","default":true},"description":"Show beam center on the image"},"show_roi":{"in":"query","name":"show_roi","schema":{"type":"boolean","default":false},"description":"Show ROI areas on the image"},Line truncated
|
||||
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.3","info":{"title":"Jungfraujoch","description":"API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland).\nJungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU.\nJungfraujoch uses FPGA boards to acquire data at high data rates.\n\n# License Clarification\n\nWhile this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply**\nwhen this file is used solely to generate OpenAPI clients or when implementing applications that\ninteract with the API. Generated client code and applications using this API definition are not\nsubject to the GPL license requirements and may be distributed under terms of your choosing.\n\nThis exception is similar in spirit to the Linux Kernel's approach to userspace API headers and\nthe GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that\nuser programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not\nderivative works of the kernel and are not subject to the terms of the GPL.\n\nThis exception is intended to allow wider use of this API specification without imposing GPL\nrequirements on applications that merely interact with the API, regardless of whether they\ncommunicate through network calls or other mechanisms.\n","version":"1.0.0-rc.166","contact":{"name":"Filip Leonarski (Paul Scherrer Institute)","email":"filip.leonarski@psi.ch"},"license":{"name":"GPL-3.0","url":"https://www.gnu.org/licenses/gpl-3.0.html"}},"servers":[{"url":"http://localhost:5232","description":"Test Jungfraujoch system"}],"components":{"parameters":{"binning":{"in":"query","name":"binning","required":false,"schema":{"default":1,"type":"integer"},"description":"Binning of frames for the plot (0 = default binning)"},"experimental_coord":{"in":"query","name":"experimental_coord","required":false,"schema":{"type":"boolean","default":false},"description":"If measurement has goniometer axis defined, plot X-axis will represent rotation angle\nIf measurement has grid scan defined, plot X-axis and Y-axis will represent grid position, Z will be used as the final value\nFor still measurement the number is ignored\n"},"azint_unit":{"in":"query","name":"azint_unit","required":false,"schema":{"type":"string","enum":["Q_recipA","d_A","two_theta_deg"],"default":"Q_recipA"},"description":"Unit used for azim int.\n"},"fill_value":{"in":"query","name":"fill","required":false,"schema":{"type":"number","format":"float"},"description":"Fill value for elements that were missed during data collection\n"},"plot_type":{"in":"query","name":"type","required":true,"description":"Type of requested plot","schema":{"type":"string","enum":["bkg_estimate","azint","azint_1d","spot_count","spot_count_low_res","spot_count_indexed","spot_count_ice","indexing_rate","indexing_lattice_count","indexing_unit_cell_length","indexing_unit_cell_angle","profile_radius","mosaicity","b_factor","error_pixels","saturated_pixels","image_collection_efficiency","receiver_delay","receiver_free_send_buf","strong_pixels","roi_sum","roi_mean","roi_max_count","roi_pixels","roi_weighted_x","roi_weighted_y","packets_received","max_pixel_value","resolution_estimate","pixel_sum","processing_time","beam_center_x","beam_center_y","integrated_reflections","image_scale_factor","image_scale_cc","compression_ratio","ice_ring_score"]}},"roi":{"in":"query","name":"roi","required":false,"schema":{"type":"string","minLength":1},"description":"Name of ROI for which plot is requested"},"image_id":{"in":"query","name":"id","required":false,"schema":{"type":"integer","format":"int64","default":-1,"minimum":-2},"description":"Image ID in the image buffer. Special values: -1 - last image in the buffer, -2: last indexed image in the buffer"},"saturation":{"in":"query","name":"saturation","required":false,"schema":{"type":"number","format":"float","minimum":-32767,"maximum":32767},"description":"Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used"},"background":{"in":"query","name":"background","required":false,"schema":{"type":"number","format":"float","default":0,"minimum":-32767,"maximum":32767},"description":"Background value to set contrast in the preview image"},"show_spots":{"in":"query","name":"show_spots","schema":{"type":"boolean","default":true},"description":"Show spot finding results on the image"},"show_predictions":{"in":"query","name":"show_predictions","schema":{"type":"boolean","default":false},"description":"Show Bragg spot predictions on the image (if available for the image)"},"show_beam_center":{"in":"query","name":"show_beam_center","schema":{"type":"boolean","default":true},"description":"Show beam center on the image"},"show_roi":{"in":"query","name":"show_roi","schema":{"type":"boolean","default":false},"description":"Show ROI areas on the image"},Line truncated
|
||||
|
||||
var container = document.getElementById('redoc');
|
||||
Redoc.hydrate(__redoc_state, container);
|
||||
|
||||
@@ -170,6 +170,24 @@ DatasetSettings &DatasetSettings::TotalFlux(const std::optional<float> &input) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
DatasetSettings &DatasetSettings::BeamSizeX_um(const std::optional<float> &input) {
|
||||
if (input) {
|
||||
check_finite("Beam size X", input.value());
|
||||
check_min("Beam size X", input.value(), 0.0);
|
||||
}
|
||||
beam_size_x_um = input;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DatasetSettings &DatasetSettings::BeamSizeY_um(const std::optional<float> &input) {
|
||||
if (input) {
|
||||
check_finite("Beam size Y", input.value());
|
||||
check_min("Beam size Y", input.value(), 0.0);
|
||||
}
|
||||
beam_size_y_um = input;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DatasetSettings &DatasetSettings::Goniometer(const std::optional<GoniometerAxis> &input) {
|
||||
goniometer = input;
|
||||
return *this;
|
||||
@@ -193,6 +211,14 @@ std::optional<float> DatasetSettings::GetTotalFlux() const {
|
||||
return total_flux;
|
||||
}
|
||||
|
||||
std::optional<float> DatasetSettings::GetBeamSizeX_um() const {
|
||||
return beam_size_x_um;
|
||||
}
|
||||
|
||||
std::optional<float> DatasetSettings::GetBeamSizeY_um() const {
|
||||
return beam_size_y_um;
|
||||
}
|
||||
|
||||
const std::optional<GoniometerAxis> &DatasetSettings::GetGoniometer() const {
|
||||
return goniometer;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ class DatasetSettings {
|
||||
|
||||
std::optional<float> total_flux;
|
||||
std::optional<float> attenuator_transmission;
|
||||
// Size of the beam where it meets the sample, x then y (NXmx incident_beam_size)
|
||||
std::optional<float> beam_size_x_um;
|
||||
std::optional<float> beam_size_y_um;
|
||||
std::optional<float> ring_current_mA;
|
||||
std::optional<GoniometerAxis> goniometer;
|
||||
std::optional<GridScanSettings> grid_scan;
|
||||
@@ -90,6 +93,8 @@ public:
|
||||
DatasetSettings& SampleName(std::string input);
|
||||
DatasetSettings& AttenuatorTransmission(const std::optional<float> &input);
|
||||
DatasetSettings& TotalFlux(const std::optional<float> &input);
|
||||
DatasetSettings& BeamSizeX_um(const std::optional<float> &input);
|
||||
DatasetSettings& BeamSizeY_um(const std::optional<float> &input);
|
||||
DatasetSettings& Goniometer(const std::optional<GoniometerAxis>& input);
|
||||
DatasetSettings& GridScan(const std::optional<GridScanSettings>& input);
|
||||
DatasetSettings& HeaderAppendix(const nlohmann::json& input);
|
||||
@@ -121,6 +126,8 @@ public:
|
||||
|
||||
std::optional<float> GetAttenuatorTransmission() const;
|
||||
std::optional<float> GetTotalFlux() const;
|
||||
std::optional<float> GetBeamSizeX_um() const;
|
||||
std::optional<float> GetBeamSizeY_um() const;
|
||||
|
||||
std::optional<GoniometerAxis> &Goniometer();
|
||||
std::optional<GridScanSettings> &GridScan();
|
||||
|
||||
@@ -665,6 +665,12 @@ void DiffractionExperiment::FillMessage(StartMessage &message) const {
|
||||
if (const auto bw = GetBandwidthFWHM())
|
||||
message.incident_wavelength_spread = bw.value() * GetWavelength_A();
|
||||
message.incident_energy = GetIncidentEnergy_keV() * 1e3f;
|
||||
// NXmx incident_beam_size is a length like every other in this message, so micrometres in
|
||||
// the settings become metres here.
|
||||
if (const auto beam_size_x = GetBeamSizeX_um())
|
||||
message.beam_size_x = beam_size_x.value() * 1e-6f;
|
||||
if (const auto beam_size_y = GetBeamSizeY_um())
|
||||
message.beam_size_y = beam_size_y.value() * 1e-6f;
|
||||
message.image_size_x = GetXPixelsNum();
|
||||
message.image_size_y = GetYPixelsNum();
|
||||
message.mirror_y = IsDetectorMirroredY();
|
||||
@@ -920,6 +926,16 @@ DiffractionExperiment &DiffractionExperiment::TotalFlux(const std::optional<floa
|
||||
return *this;
|
||||
}
|
||||
|
||||
DiffractionExperiment &DiffractionExperiment::BeamSizeX_um(const std::optional<float> &input) {
|
||||
dataset.BeamSizeX_um(input);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DiffractionExperiment &DiffractionExperiment::BeamSizeY_um(const std::optional<float> &input) {
|
||||
dataset.BeamSizeY_um(input);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::optional<float> DiffractionExperiment::GetAttenuatorTransmission() const {
|
||||
return dataset.GetAttenuatorTransmission();
|
||||
}
|
||||
@@ -928,6 +944,14 @@ std::optional<float> DiffractionExperiment::GetTotalFlux() const {
|
||||
return dataset.GetTotalFlux();
|
||||
}
|
||||
|
||||
std::optional<float> DiffractionExperiment::GetBeamSizeX_um() const {
|
||||
return dataset.GetBeamSizeX_um();
|
||||
}
|
||||
|
||||
std::optional<float> DiffractionExperiment::GetBeamSizeY_um() const {
|
||||
return dataset.GetBeamSizeY_um();
|
||||
}
|
||||
|
||||
DiffractionExperiment &DiffractionExperiment::Goniometer(const std::optional<GoniometerAxis> &input) {
|
||||
dataset.Goniometer(input);
|
||||
return *this;
|
||||
|
||||
@@ -144,6 +144,8 @@ public:
|
||||
DiffractionExperiment& SampleName(const std::string &input);
|
||||
DiffractionExperiment& AttenuatorTransmission(const std::optional<float> &input);
|
||||
DiffractionExperiment& TotalFlux(const std::optional<float> &input);
|
||||
DiffractionExperiment& BeamSizeX_um(const std::optional<float> &input);
|
||||
DiffractionExperiment& BeamSizeY_um(const std::optional<float> &input);
|
||||
DiffractionExperiment& Goniometer(const std::optional<GoniometerAxis> &input);
|
||||
DiffractionExperiment& Smargon(const std::optional<SmargonPosition> &input);
|
||||
DiffractionExperiment& HeaderAppendix(const nlohmann::json& input);
|
||||
@@ -334,6 +336,8 @@ public:
|
||||
|
||||
std::optional<float> GetAttenuatorTransmission() const;
|
||||
std::optional<float> GetTotalFlux() const;
|
||||
std::optional<float> GetBeamSizeX_um() const;
|
||||
std::optional<float> GetBeamSizeY_um() const;
|
||||
std::optional<GoniometerAxis> GetGoniometer() const;
|
||||
std::optional<GridScanSettings> GetGridScan() const;
|
||||
|
||||
|
||||
@@ -244,6 +244,9 @@ struct StartMessage {
|
||||
float incident_energy;
|
||||
float incident_wavelength;
|
||||
std::optional<float> incident_wavelength_spread; // NXmx incident_wavelength_spread: FWHM of dlambda (Angstrom)
|
||||
// NXmx incident_beam_size: size of the beam where it meets the sample, x then y (m)
|
||||
std::optional<float> beam_size_x;
|
||||
std::optional<float> beam_size_y;
|
||||
|
||||
float frame_time;
|
||||
float count_time;
|
||||
|
||||
@@ -33,6 +33,8 @@ There are minor differences at the moment:
|
||||
| incident_energy | float | X-ray energy \[eV\] | X |
|
||||
| incident_wavelength | float | X-ray wavelength \[Angstrom\] | X |
|
||||
| incident_wavelength_spread | float (optional) | FWHM of the X-ray wavelength distribution \[Angstrom\] (NXmx incident_wavelength_spread); omitted when the beam is monochromatic | |
|
||||
| beam_size_x | float (optional) | Horizontal size of the X-ray beam at the sample \[m\] (first element of NXmx incident_beam_size) | |
|
||||
| beam_size_y | float (optional) | Vertical size of the X-ray beam at the sample \[m\] (second element of NXmx incident_beam_size) | |
|
||||
| frame_time | float | Frame time, if multiple frames per trigger \[s\] | X |
|
||||
| count_time | float | Exposure time \[s\] | X |
|
||||
| saturation_value | int64 | Maximum valid sample value | X |
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* `jfjoch_writer` writes `direct_beam_x`/`direct_beam_y` in the HDF5 master - where the undeflected beam lands - beside the `beam_center_x`/`beam_center_y` PONI.
|
||||
* `jfjoch_writer` writes `/entry/MX/peakCountUnfiltered` in the HDF5 master beside the other per-image spot counts, instead of only in the data files.
|
||||
* `jfjoch_broker` sends `direct_beam_x`/`direct_beam_y` on the CBOR start message.
|
||||
* `dataset_settings` takes `beam_size_x_um`/`beam_size_y_um`, the size of the X-ray beam at the sample, and `jfjoch_writer` writes them as `incident_beam_size` in the HDF5 master.
|
||||
* `jfjoch_viewer` reads PILATUS miniCBF sweeps natively, and draws grid scan cells in the proportion of the scan steps.
|
||||
* The rugnux manual is reorganised into task pages with a run overview, and gains worked phenix / REFMAC5 / POINTLESS-AIMLESS / careless examples.
|
||||
* `jfjoch_viewer` labels the merge-statistics plot over the range the axis is drawn on, so the CC1/2 curve is no longer read against tick labels covering only part of it.
|
||||
|
||||
@@ -154,6 +154,7 @@ File-level HDF5 attributes `file_name`, `file_time`, `HDF5_Version` are also set
|
||||
| `incident_wavelength` | NXmx | angstrom |
|
||||
| `incident_wavelength_spread` | NXmx | angstrom (only if polychromatic) |
|
||||
| `total_flux` | NXmx | Hz |
|
||||
| `incident_beam_size` | NXmx | m (two elements, x then y; written only when both beam sizes are given) |
|
||||
|
||||
### `/entry/instrument/attenuator` (NXattenuator)
|
||||
|
||||
|
||||
@@ -1276,6 +1276,10 @@ namespace {
|
||||
message.incident_wavelength = GetCBORFloat(value);
|
||||
else if (key == "incident_wavelength_spread")
|
||||
message.incident_wavelength_spread = GetCBORFloat(value);
|
||||
else if (key == "beam_size_x")
|
||||
message.beam_size_x = GetCBORFloat(value);
|
||||
else if (key == "beam_size_y")
|
||||
message.beam_size_y = GetCBORFloat(value);
|
||||
else if (key == "frame_time")
|
||||
message.frame_time = GetCBORFloat(value);
|
||||
else if (key == "count_time")
|
||||
|
||||
@@ -702,6 +702,8 @@ void CBORStream2Serializer::SerializeSequenceStart(const StartMessage& message)
|
||||
CBOR_ENC(mapEncoder, "incident_energy", message.incident_energy);
|
||||
CBOR_ENC(mapEncoder, "incident_wavelength", message.incident_wavelength);
|
||||
CBOR_ENC(mapEncoder, "incident_wavelength_spread", message.incident_wavelength_spread);
|
||||
CBOR_ENC(mapEncoder, "beam_size_x", message.beam_size_x);
|
||||
CBOR_ENC(mapEncoder, "beam_size_y", message.beam_size_y);
|
||||
|
||||
CBOR_ENC(mapEncoder, "frame_time", message.frame_time);
|
||||
CBOR_ENC(mapEncoder, "count_time", message.count_time);
|
||||
|
||||
@@ -228,6 +228,19 @@ export type dataset_settings = {
|
||||
*
|
||||
*/
|
||||
transmission?: number;
|
||||
/**
|
||||
* First element of /entry/instrument/beam/incident_beam_size in NXmx
|
||||
* Horizontal size of the X-ray beam where it meets the sample - the FWHM of a focused beam,
|
||||
* the full width of a slit-defined one. [um]
|
||||
*
|
||||
*/
|
||||
beam_size_x_um?: number;
|
||||
/**
|
||||
* Second element of /entry/instrument/beam/incident_beam_size in NXmx
|
||||
* Vertical size of the X-ray beam where it meets the sample. [um]
|
||||
*
|
||||
*/
|
||||
beam_size_y_um?: number;
|
||||
goniometer?: rotation_axis;
|
||||
grid_scan?: grid_scan;
|
||||
/**
|
||||
|
||||
@@ -125,6 +125,8 @@ export const zDatasetSettings = z.object({
|
||||
]).optional().default('bslz4'),
|
||||
total_flux: z.number().optional(),
|
||||
transmission: z.number().gte(0).lte(1).optional(),
|
||||
beam_size_x_um: z.number().gte(0).optional(),
|
||||
beam_size_y_um: z.number().gte(0).optional(),
|
||||
goniometer: zRotationAxis.optional(),
|
||||
grid_scan: zGridScan.optional(),
|
||||
header_appendix: z.unknown().optional(),
|
||||
|
||||
@@ -197,23 +197,25 @@ std::string ResolveRelativeToMaster(const std::string &directory,
|
||||
// silent factor of a thousand, so the unit is read rather than assumed. An undeclared unit means
|
||||
// metres - what every DECTRIS master and everything this system writes means by one. An unknown
|
||||
// unit is refused rather than guessed at, for the same reason.
|
||||
float ReadLength_m(HDF5Object &file, const std::string &name) {
|
||||
HDF5DataSet dataset(file, name);
|
||||
const float value = dataset.ReadScalar<float>();
|
||||
|
||||
float LengthUnitFactor(HDF5DataSet &dataset, const std::string &name) {
|
||||
if (!dataset.AttrExists("units"))
|
||||
return value;
|
||||
return 1.0f;
|
||||
|
||||
const std::string units = dataset.ReadAttrStr("units");
|
||||
if (units == "m")
|
||||
return value;
|
||||
return 1.0f;
|
||||
if (units == "mm")
|
||||
return value * 1e-3f;
|
||||
return 1e-3f;
|
||||
if (units == "um")
|
||||
return value * 1e-6f;
|
||||
return 1e-6f;
|
||||
throw JFJochException(JFJochExceptionCategory::HDF5, name + ": unknown length unit " + units);
|
||||
}
|
||||
|
||||
float ReadLength_m(HDF5Object &file, const std::string &name) {
|
||||
HDF5DataSet dataset(file, name);
|
||||
return dataset.ReadScalar<float>() * LengthUnitFactor(dataset, name);
|
||||
}
|
||||
|
||||
// The same value under different names. DECTRIS Eiger firmware 1.x writes detector_distance where
|
||||
// NXmx says distance, and a file from that era is still what a repository hands you; a Diamond
|
||||
// master puts the distance one level up, in NXinstrument rather than in NXdetector. The NXmx
|
||||
@@ -926,6 +928,19 @@ HDF5MetadataSource::OpenResult HDF5MetadataSource::Open(const std::string &filen
|
||||
total_flux.reset(); // negative value is an "unknown flux" sentinel; treat as absent
|
||||
dataset->experiment.TotalFlux(total_flux);
|
||||
|
||||
// NXmx incident_beam_size is one two-element array in the order x, y; the settings hold
|
||||
// it as two lengths in micrometres.
|
||||
if (master_file->Exists("/entry/instrument/beam/incident_beam_size")) {
|
||||
HDF5DataSet beam_size(*master_file, "/entry/instrument/beam/incident_beam_size");
|
||||
std::vector<float> size;
|
||||
beam_size.ReadVector(size);
|
||||
if (size.size() == 2) {
|
||||
const float to_um = LengthUnitFactor(beam_size, "incident_beam_size") * 1e6f;
|
||||
dataset->experiment.BeamSizeX_um(size[0] * to_um);
|
||||
dataset->experiment.BeamSizeY_um(size[1] * to_um);
|
||||
}
|
||||
}
|
||||
|
||||
if (master_file->Exists("/entry/azint") && master_file->Exists("/entry/azint/bin_to_q")) {
|
||||
HDF5DataSet bin_to_q_dataset(*master_file, "/entry/azint/bin_to_q");
|
||||
HDF5DataSpace bin_to_q_dataspace(bin_to_q_dataset);
|
||||
|
||||
@@ -28,6 +28,8 @@ TEST_CASE("CBORSerialize_Start", "[CBOR]") {
|
||||
.countrate_correction_enabled = true,
|
||||
.incident_energy = 12400,
|
||||
.incident_wavelength = 0.988,
|
||||
.beam_size_x = 8e-5,
|
||||
.beam_size_y = 3e-5,
|
||||
.frame_time = 0.0001,
|
||||
.count_time = 0.000098,
|
||||
.saturation_value = 65534,
|
||||
@@ -145,6 +147,10 @@ TEST_CASE("CBORSerialize_Start", "[CBOR]") {
|
||||
CHECK(output_message.unit_cell->beta == message.unit_cell->beta);
|
||||
CHECK(output_message.unit_cell->gamma == message.unit_cell->gamma);
|
||||
|
||||
REQUIRE(output_message.beam_size_x);
|
||||
CHECK(output_message.beam_size_x.value() == message.beam_size_x.value());
|
||||
REQUIRE(output_message.beam_size_y);
|
||||
CHECK(output_message.beam_size_y.value() == message.beam_size_y.value());
|
||||
REQUIRE(output_message.total_flux);
|
||||
CHECK(output_message.total_flux.value() == message.total_flux.value());
|
||||
REQUIRE(output_message.attenuator_transmission);
|
||||
|
||||
@@ -627,6 +627,11 @@ void NXmx::Beam(const StartMessage &start) {
|
||||
SaveScalar(group, "incident_wavelength_spread", start.incident_wavelength_spread.value())->Units("angstrom");
|
||||
if (start.total_flux)
|
||||
SaveScalar(group, "total_flux", start.total_flux.value())->Units("Hz");
|
||||
// NXmx asks for the beam size as one two-element array in the order x, y, so it is written
|
||||
// only when both have been given.
|
||||
if (start.beam_size_x && start.beam_size_y)
|
||||
group.SaveVector("incident_beam_size",
|
||||
std::vector<float>{start.beam_size_x.value(), start.beam_size_y.value()})->Units("m");
|
||||
}
|
||||
|
||||
void NXmx::Fluorescence(const StartMessage &start) {
|
||||
|
||||
Reference in new issue
Block a user