Calibration Catalog (CalCat)
Besides the standard RESTful APIs for CRUD (+ list/search) operations the CalCat exposes the following special APIs (per model):
Table of contents
- Operation Modes
- Detectors
- Physical Detector Units
- Conditions
- Calibration Constants
- Calibration Constant Versions
- Notes
Operation Modes
get_all_by_detector_type
HTTP Method: GET
HTTP Path: /api/operation_modes/get_all_by_detector_type_id
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
detector_type_id |
integer | QueryString | yes | - | detector_type_id=10 |
Output:
List of operation modes defined for the requested detector type, where flg_available is set to true ordered by position ascending (position is a field in the relation (many to many) between operation modes and detector type).
Internals:
- scope
by_detector_type(detector_type_id)of theOperationModemodel
Detectors
get_all_by_instrument
HTTP Method: GET
HTTP Path: /api/detectors/get_all_by_instrument
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
instrument_id |
integer | QueryString | yes | - | instrument_id=3 |
Output:
List of detectors belonging to the requested instrument (note that the relation is many to many: an instrument can have many detectors and a detector can belong to more than one instrument).
If the given instrument does not exists (wrong instrument_id) or exists but it is not associated to any detector, the HTTP response code will be in both cases a 404.
Internals:
- retrieve instrument by id
- direct use of
has_many throughrelation between the Instrument and the Detector models
Physical Detector Units (PDUs)
get_all_by_detector
HTTP Method: GET
HTTP Path: /physical_detector_units/get_all_by_detector
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
detector_id |
integer | QueryString | yes | - | detector_id=10 |
pdu_snapshot_at |
datetime | QueryString | no | - | pdu_snapshot_at=20210526T123000+0200 |
Output:
List of PDUs belonging to the requested detector.
If the pdu_snapshot_at parameter is passed, the list of PDUs belonging to the detector at the pdu_snapshot_at moment in time will be returned.
If the given detector does not exists (wrong detector_id) or exists but does not have any associated PDU (or did not have at the pdu_snapshot_at moment), the HTTP response code will be in both cases a 404.
The parameter snapshot_at (in place of pdu_snapshot_at) is still accepted for compatibility.
Internals:
- find the detector
-
get_pdus_by_detector(pdu_snapshot_at)method of the Detector model
Conditions
The following methods are exposed under the Conditions APIs, that is, under the base path: /api/conditions/
get_possible_conditions
A calibration condition is defined as a set of physical conditions each represented by some characteristic (e.g., a physical quantity), called parameter, the value of that characteristic, the physical unit of that value (where applicable), and allowable limits of variation for that value.
Parameters of type text (flg_text == true) also exist: in such case the limits of variations do not apply; the search on possible conditions for those parameters is limited to values which starts with a certain string.
This API searches for calibration conditions matching a list of parameters whose values are within certain boundaries (or text value starts with a certain string for text type parameters).
HTTP Method: POST | GET
HTTP Path: /api/conditions/get_possible_conditions
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
| condition | JSON | Request body | yes | - | read below |
For backward compatibility reasons this API allows the list of parameters and values in a JSON request's body with an HTTP GET request: this is a non standard usage of HTTP protocol.
A typical example of a request body to retrieve conditions using this API is the following:
{"condition":{
"event_at": "20210526T123000+0200",
"parameters_conditions_attributes":[
{
"parameter_id":"7",
"value":"352.0"
},
{
"parameter_id":"1",
"value":"300.0"
},
{
"parameter_id":"13",
"value":"512.0"
},
{
"parameter_id":"14",
"value":"128.0"
},
{
"parameter_id":"17",
"value":"1.1"
},
{
"parameter_id":"4",
"value":"0.0"
}
]
}
}Note that the key event_at is optional, while the parameters_conditions_attributes is mandatory.
The event_at parameter, if missing, is set as default to the current datetime.
For each of the the parameters_conditions_attributes:
- the key
parameter_idis mandatory. - the key
valueis not mandatory and it would be assumed equal to0.0as default if not present for float type parameters. However, such value will result in an error for logarithmic parameters, while, on the other side, for text type parameters (where theflg_txtis set totrue) it would have the effect of not filtering at all, being valid for any value of the parameter in the DB (i.e. every text starts with an empty string).
Note that in the example above all values are passed in the JSON body as strings but, for float parameters (where the flg_txt is set to false), the value is automatically converted to float. For float parameters, float or integer values can be passed directly in the JSON.
As an alternative to parameter_id, the parameter parameter_name can be used. In such case, the search of the ID will be performed immediately, with exact match of the name (case insensitive, though).
In case a parameter with the requested name is not returned a 404 error will be triggered.
In the example above, for instance, using parameter_name instead of parameter_id, will yield the following request body:
{"condition":{
"event_at": "20210526T123000+0200",
"parameters_conditions_attributes":[
{
"parameter_name":"Memory cells",
"value":"352.0"
},
{
"parameter_name":"Sensor Bias Voltage",
"value":"300.0"
},
{
"parameter_name":"Pixels X",
"value":"512.0"
},
{
"parameter_name":"Pixels Y",
"value":"128.0"
},
{
"parameter_name":"Acquisition rate",
"value":"1.1"
},
{
"parameter_name":"Gain Setting",
"value":"0.0"
}
]
}
}Remarks
The python calibration client, due to how the HTTP request's body JSON object is built internally in the client, will inject additional keys in the JSON, like, e.g. lower_deviation_value, flg_available and so on: some of those are actually required by other APIs (e.g. when injecting the conditions) but not for this particular API, where those additional keys will be simply ignored.
For the same reason, the python calibration client will inject the values of parameter_id and value as strings, despite they should normally be integers (the parameter_id values) and floats (the value values): this is also how they are stored in the database. For text parameters (flg_text set to true) having value passed as a string is needed, but actually, if a numeric value would be passed instead, this would be automatically converted to a string.
Output:
A list of conditions which respect the parameters within certain boundaries (read further for more details).
Each of the retrieved conditions MUST be identified by the entire set of parameters (conditions are defined also by the number of parameter conditions which identifies them: a subset of parameter conditions, even when matching a condition, would not be sufficient to retrieve it).
The conditions in the list are returned ordered by date of creation the nearest to the optional event_at parameter.
The criteria to identify the requested calibration conditions are the following:
- the calibration condition is identified by that exact number of parameters
- the calibration condition has the flag
flg_availableset totrue - for each of the requested parameter conditions:
- the parameter id matches
- if the parameter is of type text (
flg_text == true)- the stored value in the DB starts with the
valueparameter
- the stored value in the DB starts with the
- if the parameter is not text and not logarithmic (
flg_logarithmic == false)- as a lower bound, the
valueparameter...- if
cal_min_valueis defined- is greater than
cal_min_value(stored in the parameter condition)
- is greater than
- if
cal_min_valueis NOT defined (set to NULL) andparameters.def_lower_deviation_valueis defined (parameters.def_lower_deviation_valueis a default for the parameter)- is greater than
value - parameters.def_lower_deviation_value(wherevaluerefers to the value stored in the parameter condition)
- is greater than
- if both
cal_min_valueandparameters.def_lower_deviation_valueare NOT defined (set to NULL):- in such case any value would match
- if
- as an upper bound, the
valueparameter...- if
cal_max_valueis defined- is less than
cal_max_value(stored in the parameter condition)
- is less than
- if
cal_max_valueis NOT defined (set to NULL) andparameters.def_upper_deviation_valueis defined (parameters.def_upper_deviation_valueis a default for the parameter)- is less than
value + parameters.def_upper_deviation_value(wherevaluerefers to the value stored in the parameter condition)
- is less than
- if both
cal_max_valueandparameters.def_upper_deviation_valueare NOT defined (set to NULL):- in such case any value would match
- if
- as a lower bound, the
- if the parameter is logarithmic (
flg_logarithmic == true)- almost identical considerations apply, except that in case of
cal_min_valueset to NULL (cal_max_valuerespectively) the fallbackparameters.def_lower_deviation_value(parameters.def_upper_deviation_valuerespectively) is considered as the exponent of the power in base 10.
- almost identical considerations apply, except that in case of
Important: at the moment of writing this documentation (November 2022) there are almost NO parameter conditions registered in the production database with cal_min_value or cal_max_value set to NULL, so, in practice, this API will find those conditions whose parameter conditions have the requested values between cal_min_value and cal_max_value.
Internals:
-
conditions_ids = get_expected_conditions(params, false):-
get_expected_conditions_int(params, false): loop over parameters - for each parameter condition: call
get_match_param_cond_ids(param_cond, false, num_params, filter_condition_ids)- get the parameter by
parameter_id - call
ParametersCondition.get_possible_conditions(parameter, parameter_val, num_params, filter_condition_ids) - apply different rules depending on nature of the parameter (
flg_text,flg_logarithmic)ParametersCondition.get_possible_conditions_txt(parameter, value, num_parameters, filter_condition_ids)ParametersCondition.get_possible_conditions_log(parameter, value, num_parameters, filter_condition_ids)ParametersCondition.get_possible_conditions_non_log(parameter, value, num_parameters, filter_condition_ids)
- intersection of conditionids is performed at each step, as the `filtercondition_ids` is refined at each step and passed along
- get the parameter by
-
-
possible_conditions_by_closest_created_at(condtions_ids, event_at): all intersected conditions are retrieved (by id) and ordered by creation date the nearest to theevent_atparameter
get_expected_condition
For a definition of what a calibration condition is, please refer to the previous api get_possible_conditions.
HTTP Method: POST | GET
HTTP Path: /api/conditions/get_expected_condition
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
| condition | JSON | Request body | yes | - | read below |
As the previous API for backward compatibility reasons this one also allows the list of parameters and values in a JSON request's body with an HTTP GET request.
A typical example of a request body to retrieve conditions using this API is the following:
{
"condition":{
"parameters_conditions_attributes":[
{
"parameter_id":"7",
"value":"352.0",
"lower_deviation_value":"0.0",
"upper_deviation_value":"0.0"
},
{
"parameter_id":"1",
"value":"300.0",
"lower_deviation_value":"5.0",
"upper_deviation_value":"5.0"
},
{
"parameter_id":"13",
"value":"512.0",
"lower_deviation_value":"0.0",
"upper_deviation_value":"0.0"
},
{
"parameter_id":"14",
"value":"128.0",
"lower_deviation_value":"0.0",
"upper_deviation_value":"0.0"
},
{
"parameter_id":"17",
"value":"1.1",
"lower_deviation_value":"0.0",
"upper_deviation_value":"0.0"
},
{
"parameter_id":"4",
"value":"0.0",
"lower_deviation_value":"0.0",
"upper_deviation_value":"0.0"
},
{
"parameter_id":"30",
"value":"This is a text parameter"
},
{
"parameter_id":"12",
"value":"4.99006796365e-313",
"lower_deviation_value":"0.0",
"upper_deviation_value":"0.0"
}
]
}
}Note that in comparison with the previous API this one does not accept an event_at parameter and additionally, for each parameter condition, all keys (parameter_id, value, lower_deviation_value and upper_deviation_value) are required, except for text type parameters, where lower_deviation_value and upper_deviation_value are not required or, if passed, are simply ignored.
As for the previous API, also in this case parameter_name can be used in place of parameter_id, producing the same results in case of non existing parameter with the requested name.
Output:
The most recently created condition which respects the following criteria:
- the calibration condition is identified by that exact number of parameters
- the calibration condition has the flag
flg_availableset to true - for each of the requested parameter conditions
- if parameter is of type float (logarithmic or not):
- exact match between
value,lower_deviation_valueandupper_deviation_valuerequested parameters and database content
- exact match between
- if parameter is of text type:
- exact match of value and database text_value content
- if parameter is of type float (logarithmic or not):
Internals:
-
conditions_ids = get_expected_conditions(params, true):-
get_expected_conditions_int(params, true): loop over parameters - for each parameter condition: call
get_match_param_cond_ids(param_cond, true, num_params, filter_condition_ids)- get the parameter by parameter_id
- call
ParametersCondition.get_exact_conditions(parameter.id, parameter_val, parameter_lower_dev_val, parameter_upper_dev_val, num_params, filter_condition_ids)
- intersection of conditionids is performed at each step, as the `filtercondition_ids` is refined at each step and passed along
-
-
existing_conditions(condition_ids): returnsCondition.where(id: condition_ids).order(created_at: :desc).first(so only one: the most recently created condition)
set_expected_conditions
This API is used to create a new condition in the database or return the already existing one which already matches the same set of parameter conditions.
HTTP Method: POST
HTTP Path: /api/conditions/set_possible_conditions
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
| condition | JSON | Request body | yes | - | read below |
Similar considerations as for the previous API apply here, the major difference in the input JSON is that additional optional parameters (JSON "keys") can be sent.
In particular, under the main "condition" key the following additional keys/parameters can also be specified:
-
name(default: unix timestamp of current datetime) -
flg_available(default:true) -
description(default:NULL)
And under each of the parameter conditions attributes the following additional keys/parameters can be specified:
-
flg_available(default:true) -
description(default:NULL)
Again, also in this API parameter_name can be used in place of parameter_id.
Output:
The newly created condition (HTTP response status will be 201 Created in such case) or the condition which already matches perfectly the set of parameter condition as for the criteria of the get_expected_condition API (HTTP response status will be 200 OK). Please note: in the latter case the aforementioned optional parameters are simply ignored (the way to update the name, description and flg_available of a condition, if needed, are the standard RESTful APIs)
Internals:
- performs the same operations as the previous API and if any condition is found will return that condition
- if nothing is found call
create_condition_int(condition_params)which would create the condition and nested attributes (parameters conditions)
Calibration Constants (CCs)
These methods are actually exposed under the Calibrations (aka 'constant types') APIs, that is, under the base path:
/api/calibrations/:id/
get_calibration_constant
HTTP Method: GET
HTTP Path: /api/calibrations/:id/get_calibration_constant
Input parameters
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id |
integer | Path | yes | - | /1 |
detector_type_id |
integer | QueryString | yes | - | detector_type_id=10 |
condition_id |
integer | QueryString | yes | - | condition_id=20 |
Output:
One single calibration constant matching the criteria (constant_id = :id, detector type and condition) where the flg_available is set to true.
In case multiple calibration constants should match the criteria (same calibration, aka constant type, same detector type and same condition) only the first orderd by creation date descending (i.e., the most recent) is returned.
Internals
- scope
search_calibration_constantof CalibrationConstant model, returns first record
get_all_calibration_constants
HTTP Method: GET
HTTP Path: /api/calibrations/:id/get_all_calibration_constants
Input parameters
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id |
integer | Path | yes | - | /1 |
detector_type_id |
integer | QueryString | yes | - | detector_type_id=10 |
condition_ids |
array of integers | QueryString | yes | - | condition_ids=[1,2,3] |
Output:
List of calibration constants matching the criteria (constant_id = :id, detector type and condition) where the flg_available is set to true, ordered by creation date descending.
Internals
- scope
search_calibration_constantof CalibrationConstant model
Calibration Constant Versions (CCVs)
The following methods (with the exception of the last one) are actually exposed under the Calibration Constants APIs, that is, under the base path:
/api/calibration_constants/:id/
get_version
HTTP Method: GET
HTTP Path: /api/calibration_constants/:id/get_version
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id |
integer | Path | yes | - | /1 |
physical_detector_unit_id |
integer | QueryString | yes | - | physical_detector_unit_id=10 |
event_at |
datetime | QueryString | no | current datetime - 1 second¹ | event_at=20210526T123000+0200 |
snapshot_at |
datetime | QueryString | no | - | snapshot_at=20210526T123000+0200 |
Output:
One single Calibration Constant Version matching the criteria (CC and PDU by respective requested ids), with the flag flg_deployed set to true, where the param event_at is in the range of validity of the CCV (see "§ Notes / Range of validity of Calibration Constant Versions" for more details).
If the snapshot_at parameter is passed, the CCVs taken into account would be the ones which had the flag flg_deployed set to true in the database at the snapshot_at moment in time.
If more than one CCV should be "valid" at the event_at moment, the one with the most recent begin_at would be returned.
(1) The one second difference explained:
CCVs may be defined with end_validity_at set to NULL. In such case (see "§ Notes / Range of validity of Calibration Constant Versions" for more details) the end date would be considered the date of now, but with seconds resolution. Since the comparison for the validity is for an end_validity_at strictly greater than the event_at, removing one second guarantees we find such CCV.
Internals:
-
cc = CalibrationConstant.find(): retrieve a single calibration constant -
cc.get_deployed_version: returns one calibration constant version matching the criteria withevent_atin the range of validity of the CCV
get_closest_version
HTTP Method: GET
HTTP Path: /api/calibration_constants/:id/get_closest_version
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id² |
integer | Path | yes | - | /1 |
calibration_constant_ids |
array of integers | QueryString | yes | - | calibration_constant_ids=[1,2,3] |
physical_detector_unit_id |
integer | QueryString | yes | - | physical_detector_unit_id=10 |
event_at |
datetime | QueryString | no | current datetime - 1 second¹ | event_at=20210526T123000+0200 |
snapshot_at |
datetime | QueryString | no | - | snapshot_at=20210526T123000+0200 |
(2) Note that the id parameter is there for compatibility and historical reason. It is actually not used to filter the results but it must correspond to the id of an existing constant: it is advisable to pass the first id of the calibration_constant_ids list.
Output:
One single Calibration Constant Version matching the criteria (multiple CCs and single PDU by respective requested ids), with the flag flg_deployed set to true, where the begin_at is the closest to the event_at parameter (it may return a CCV which has a validity period in the future of the event_at).
If the snapshot_at parameter is passed, the CCVs taken into account would be the ones which had the flag flg_deployed set to true in the database at the snapshot_at moment in time.
Internals:
-
get_all_versions_ordered_by_closest(cc_ids, pdu_id, snap, event):- find CCs by cc_ids
- loop over the CCs
- collect CCVs ids of those CCs (here
snapshot_atis taken into account)
- returns one CCV (where
begin_atis the closest toevent_at)
get_prior_in_time_version
HTTP Method: GET
HTTP Path: /api/calibration_constants/:id/get_prior_in_time_version
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id² |
integer | Path | yes | - | /1 |
calibration_constant_ids |
array of integers | QueryString | yes | - | calibration_constant_ids=[1,2,3] |
physical_detector_unit_id |
integer | QueryString | yes | - | physical_detector_unit_id=10 |
event_at |
datetime | QueryString | no | current datetime - 1 second¹ | event_at=20210526T123000+0200 |
snapshot_at |
datetime | QueryString | no | - | snapshot_at=20210526T123000+0200 |
(2) Note that the id parameter is there for compatibility and historical reason. It is actually not used to filter the
results but it must correspond to the id of an existing constant: it is advisable to pass the first id of the calibration_constant_ids list.
Output:
One single Calibration Constant Version matching the criteria (multiple CCs and single PDU by respective requested ids),
with the flag flg_deployed set to true, where the begin_at is the closest to the event_at parameter BUT BEFORE the event_at.
If the snapshot_at parameter is passed, the CCVs taken into account would be the ones which had the flag flg_deployed
set to true in the database at the snapshot_at moment in time.
Internals:
-
get_prior_in_time_version_render(cc_ids, pdu_id, snap, event):- find CCs by cc_ids
- loop over the CCs
- collect CCVs of those CCs (here
snapshot_atis taken into account) - filter CCVs so that
event_atis in their range of validity - reorder filtered CCVs by
begin_atascending - returns the last CCV of so re-ordered CCVs
get_all_versions
HTTP Method: GET
HTTP Path: /api/calibration_constants/:id/get_all_versions
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id² |
integer | Path | yes | - | /1 |
calibration_constant_ids |
array of integers | QueryString | yes | - | calibration_constant_ids=[1,2,3] |
physical_detector_unit_id |
integer | QueryString | yes | - | physical_detector_unit_id=10 |
event_at |
datetime | QueryString | no | current datetime - 1 second¹ | event_at=20210526T123000+0200 |
snapshot_at |
datetime | QueryString | no | - | snapshot_at=20210526T123000+0200 |
(2) Note that the :id parameter is there for compatibility and historical reason. It is actually not used to filter the results but it must correspond to the id of an existing constant: it is advisable to pass the first id of the calibration_constant_ids list.
Output:
List of all Calibration Constant Versions matching the criteria (multiple CCs and single PDU by respective requested ids), with the flag flg_deployed set to true, ordered by begin_at closer to event_at parameter.
If the snapshot_at parameter is passed, the CCVs taken into account would be the ones having the flg_deployed set to true in the database at the snapshot_at moment in time.
Internals:
-
get_all_versions_ordered_by_closest(cc_ids, pdu_id, snap, event):- find CCs by cc_ids
- loop over the CCs
- collect CCVs ids of those CCs (here
snapshot_atis taken into account)
- returns all those CCVs (ordered by
begin_atcloser toevent_at)
get_closest_version_by_detector
HTTP Method: GET
HTTP Path: /api/calibration_constants/:id/get_closest_version_by_detector
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
:id² |
integer | Path | yes | - | /1 |
calibration_constant_ids |
array of integers | QueryString | yes | - | calibration_constant_ids=[1,2,3] |
detector_id |
integer | QueryString | yes | - | detector_id=28 |
karabo_da |
string | QueryString | no | - | karabo_da=KARABODA02 |
event_at |
datetime | QueryString | no | current datetime - 1 second¹ | event_at=20210526T123000+0200 |
snapshot_at |
datetime | QueryString | no | - | snapshot_at=20210526T123000+0200 |
(2) Note that the :id parameter is there for compatibility and historical reason. It is actually not used to filter the results but it must correspond to the id of an existing constant: it is advisable to pass the first id of the calibration_constant_ids list.
Output:
List of all Calibration Constant Versions (one per PDU) matching the criteria (multiple CCs and PDUs belonging to detector, if karabo_da is specified will select only one matching PDU), with the flag flg_deployed set to true, ordered by begin_at closer to event_at parameter.
If the snapshot_at parameter is passed:
- the PDUs taken into account would be the ones belonging to the detector at the
snapshot_atmoment in time - the CCVs taken into account would be the ones having the
flg_deployedset to true in the database at thesnapshot_atmoment in time
Internals:
- find the detector
- find the PDUs (could be just one if
karabo_dais specified) -
get_all_versions_by_pdu(cc_ids, pdus, snap, event):- loop over the PDUs and append the result of first
get_all_versions_ordered_by_closest(cc_ids, pdu_id, snap, event) - this is a nested loop (PDUs x CCs, so is pretty inefficient when each CCs is bound to a single PDU!)
- finally returns one CCV per PDU which has the closest
begin_attoevent_at
- loop over the PDUs and append the result of first
get_by_detector_conditions
Differently from the previous APIs, this one is exposed under the Calibration Constant Versions APIs that is, under the base path: /api/calibration_constant_versions/
This is a non-standard API which retrieves the calibration constant versions by detector identifier and by a set of parameters conditions. This API combines strategies from the previous APIs.
HTTP Method: POST | GET
HTTP Path: /api/calibration_constant_versions/get_by_detector_conditions
Input parameters:
| name | type | passed via | required | default | example |
|---|---|---|---|---|---|
detector_identifier |
string | QueryString | yes | - | detector_identifier=SPB_DET_AGIPD1M-1 |
calibration_id |
integer (or list of integers) | QueryString | no | - |
calibration_id=2 (calibration_id=[2,11,13]) |
karabo_da |
string | QueryString | no | - | karabo_da=AGIPD03 |
parameters_conditions_attributes |
JSON | Request body | yes | - | read below |
event_at |
datetime | QueryString | no | current datetime - 1 second¹ | event_at=20210526T123000+0200 |
pdu_snapshot_at |
datetime | QueryString | no | - | pdu_snapshot_at=20210526T105000+0200 |
begin_at_strategy |
string (either "prior" or "closest") | QueryString | no | closest | begin_at_strategy=prior |
Similarly to other APIs involving the conditions (e.g. get_possible_conditions), for backward compatibility reasons, this one allows the list of parameters and values in a JSON request's body with an HTTP GET request.
A typical example of a request body to retrieve CCVs using this API is the following:
{
"parameters_conditions_attributes":[
{
"parameter_id":"7",
"value":"352.0"
},
{
"parameter_id":"1",
"value":"300.0"
},
{
"parameter_id":"13",
"value":"512.0"
},
{
"parameter_id":"14",
"value":"128.0"
},
{
"parameter_id":"17",
"value":"1.1"
},
{
"parameter_id":"4",
"value":"0.0"
}
]
}As for the get_possible_conditions API, also in this case parameter_name can be used in place of parameter_id.
Output:
List of all Calibration Constant Versions (one per PDU) matching the criteria: PDUs belonging to detector specified by detector_identifier parameter, Calibration (aka constant type) matching the passed parameter (calibration_id), Calibration Constant matching the specified conditions, with the flag flg_deployed set to true, ordered (by default) by begin_at closer to event_at parameter.
If the pdu_snapshot_at parameter is passed, the PDUs taken into account would be the ones belonging to the detector at the pdu_snapshot_at moment in time
The optional begin_at_strategy parameter can assume the values prior or closest. If omitted, the default strategy is assumed to be closest: the retrieved CCVs are the ones where the begin_at
field is the closest to the event_at parameter (note that the event_at parameter is also optional: if empty the current timestamp is assumed).
In case of begin_at_strategy is set to the value prior the retrieved CCVs are the ones where the begin_at field is strictly before the event_at parameter.
If the given detector does not exists (wrong detector_identifier) or exists but does not have any associated PDU (or did not have at the snapshot_at moment), the HTTP response code will be in both cases a 404.
In case the detector and associated PDU exist but no CCVs could be retrieved (either because of non matching conditions or constant type), the HTTP response would be a 200 but the result would consist of an empty list.
Either a single calibration_id, a list of calibration_id(s) or an empty calibration_id are accepted: if multiple ids are passed, then the API will loop over them and retrieve one CCV per PDU per constant type (calibrationid = constant type). If an empty `calibrationid` is passed then the API will loop over all possible constant types.
Internals:
Get the detector:
det = Detector.find_by_identifier(detector_identifier)Get PDUs at
pdu_snapshot_at:pdus = det.get_pdus_by_detector(pdu_snapshot_at)orpdus = [det.get_pdu_by_detector_and_karabo_da(karabo_da, pdu_snapshot_at)].reject { |pdu| pdu.nil? }(ifkarabo_daparameter is passed)Get all conditions:
get_expected_conditions_int(parameters_conditions, false, num_params+1)-
For each PDU:
- For each constanttype (calibrationid):
- find CCs by
conditions_ids, PDU.detector_type_id,calibration_id:CalibrationConstant.search_calibration_constant - get the first CCV from list of CCVs ordered by
begin_atclosest atevent_at:get_all_versions_ordered_by_closest(calibration_constants.collect(&:id), pdu.id, nil, event_at)
- find CCs by
- For each constanttype (calibrationid):
curl request example (single constant_type, all PDUs):
curl -s -X GET -H 'Accept: application/json; version=2' \
-H "X-USER-EMAIL: $user_email" -H "Authorization: Bearer $token" \
-H "Content-type: application/json" \
"https://in.xfel.eu/calibration/api/calibration_constant_versions/get_by_detector_conditions?detector_identifier=SPB_DET_AGIPD1M-1&calibration_id=2" \
-d '{"parameters_conditions_attributes":[{"parameter_id":"7","value":"352.0"},{"parameter_id":"1","value":"300.0"},{"parameter_id":"13","value":"512.0"},{"parameter_id":"14","value":"128.0"},{"parameter_id":"17","value":"1.1"},{"parameter_id":"4","value":"0.0"}]}' \
| jq .curl request example (multiple constant_types, one PDU):
curl -s -X GET -H 'Accept: application/json; version=2' \
-H "X-USER-EMAIL: $user_email" -H "Authorization: Bearer $token" \
-H "Content-type: application/json" \
"https://in.xfel.eu/calibration/api/calibration_constant_versions/get_by_detector_conditions?detector_identifier=SPB_DET_AGIPD1M-1&karabo_da=AGIPD12&calibration_id=%5B2%2C11%5D" \
-d '{"parameters_conditions_attributes":[{"parameter_id":"7","value":"352.0"},{"parameter_id":"1","value":"300.0"},{"parameter_id":"13","value":"512.0"},{"parameter_id":"14","value":"128.0"},{"parameter_id":"17","value":"1.1"},{"parameter_id":"4","value":"0.0"}]}' \
| jq .Notes:
Serialization of Calibration Constant Versions (example):
{
"id": 81729,
"name": "20210716_162211_sIdx=0",
"file_name": "cal.1626452528.8961353.h5",
"path_to_file": "xfel/cal/agipd-type/agipd_siv1_agipdv11_m441/",
"data_set_name": "/AGIPD_SIV1_AGIPDV11_M441/ThresholdsDark/0",
"flg_deployed": true,
"flg_good_quality": true,
"begin_validity_at": "2021-07-16T17:46:36.000+02:00",
"end_validity_at": null,
"begin_at": "2021-07-16T17:46:36.000+02:00",
"start_idx": 0,
"end_idx": 0,
"raw_data_location": "proposal:p900214 runs:9 8 7",
"report_id": 594,
"description": "",
"view_url": "http://localhost:3004/dev_calibration/calibration_constant_versions/81729",
"calibration_constant": {
"id": 11042,
"name": "AGIPD-Type_ThresholdsDark_AGIPD DefXphmDHCWAd61WU1/N5h3qA==\n",
"flg_auto_approve": true,
"flg_available": true,
"description": "Per-pixel (per-memory cell) thresholds from dark runs",
"detector_type_id": 2,
"calibration_id": 11,
"condition_id": 3286,
"created_at": "2021-07-16T18:22:10.000+02:00"
},
"physical_detector_unit": {
"id": 106,
"physical_name": "AGIPD_SIV1_AGIPDV11_M441",
"karabo_da": "AGIPD04",
"virtual_device_name": "Q2M1",
"uuid": 303002300000,
"float_uuid": 1.49703027041e-312,
"detector_type_id": 2,
"detector_id": 4,
"flg_available": true,
"description": null
}
}Range of validity of Calibration Constant Versions:
Each Calibration Constant Version has the following date fields:
begin_atbegin_validity_atend_validity_at
At the moment of writing this documentation (first draft: September 2021, last update: May 2024) the field begin_validity_at is actually NOT used in CalCat.
The validity period of each CCV is normally calculated as the period between begin_at and end_validity_at.
However, the end_validity_at can be NULL: in such case the validity period of each CCV is calculated as the period between the currently examined CCV begin_at and the begin_at of the following CCV (in the list of CCVs belonging to the same PDU and CC ordered by begin_at). The last CCV in the list, having a NULL end_validity_at, would be considered be valid until the current datetime (now), however with the caveat that this calculated datetime has resolution of seconds.