Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #4838 add SRW detector features for plotting #6640

Merged
merged 12 commits into from
Jan 16, 2024
2 changes: 1 addition & 1 deletion sirepo/package_data/static/html/plot3d.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@
<rect class="mouse-rect-x mouse-zoom" data-interactive-overlay="" data-report-id="reportId" data-focus-points="[focusPointX]" ng-attr-y="{{ canvasSize.height }}" ng-attr-width="{{ canvasSize.width }}" ng-attr-height="{{ bottomPanelHeight }}" style="pointer-events: all; fill: none;"></rect>
</g>
</svg></div>
<div style="display: flex; justify-content: flex-end">{{width}}x{{height}}</div>
<div data-ng-show="showPlotSize()" style="display: flex; justify-content: flex-end">plot resolution: {{width}}x{{height}}</div>
<div data-animation-buttons=""></div>
</div>
2 changes: 1 addition & 1 deletion sirepo/package_data/static/js/sirepo-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ SIREPO.app.directive('fieldEditor', function(appState, keypressService, panelSta
<div data-ng-switch-when="Bool" class="col-sm-7">
<input type="checkbox" data-ng-model="model[field]">
</div>
<div data-ng-switch-when="Boolean" class="fieldClass">
<div data-ng-switch-when="Boolean" data-ng-class="fieldClass">
<input class="sr-bs-toggle" data-ng-open="fieldDelegate.refreshChecked()" data-ng-model="model[field]" data-bootstrap-toggle="" data-model="model" data-field="field" data-field-delegate="fieldDelegate" data-info="info" type="checkbox">
</div>
<div data-ng-switch-when="ColorMap" class="col-sm-7">
Expand Down
6 changes: 5 additions & 1 deletion sirepo/package_data/static/js/sirepo-plotting.js
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ SIREPO.app.factory('plotting', function(appState, frameCache, panelState, utilit
},

getAspectRatio: function(modelName, json, defaultRatio) {
if (appState.isLoaded() && appState.applicationState()[modelName]) {
if (! json.aspectRatio && appState.isLoaded() && appState.applicationState()[modelName]) {
var ratioEnum = appState.applicationState()[modelName].aspectRatio;
if (ratioEnum) {
return parseFloat(ratioEnum);
Expand Down Expand Up @@ -3173,6 +3173,10 @@ SIREPO.app.directive('plot3d', function(appState, focusPointService, layoutServi
resizefocusPointText();
};

$scope.showPlotSize = () => {
return appState.models[$scope.modelName].showPlotSize == '1';
};

$scope.$on(SIREPO.PLOTTING_LINE_CSV_EVENT, function(evt, axisName) {
var title = $($scope.element).closest('.panel-body')
.parent().parent().find('.sr-panel-heading').text();
Expand Down
27 changes: 26 additions & 1 deletion sirepo/package_data/static/js/srw.js
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,11 @@ SIREPO.app.controller('BeamlineController', function (activeSection, appState, b
$scope.$on('simulation.changed', syncDistanceFromSourceToFirstElementPosition);
$scope.$on('multiElectronAnimation.changed', updateMultiElectronWatchpoint);
$scope.$on('beamlineAnimation0.changed', copyIntensityReportCharacteristics);
$scope.$on('modelChanged', (event, modelName) => {
if (modelName.indexOf('beamlineAnimation') >= 0) {
updateWatchpointReports();
}
});
srwService.addSummaryDataListener($scope);
var search = $location.search();
if (search) {
Expand Down Expand Up @@ -955,14 +960,31 @@ var srwGrazingAngleLogic = function(panelState, srwService, $scope) {

var srwIntensityLimitLogic = function(appState, panelState, srwService, $scope) {

const modelKey = $scope.modelData ? $scope.modelData.modelKey : $scope.modelName;

function hasSamplingMethod() {
return $scope.modelName == 'sourceIntensityReport' || $scope.modelName == 'coherentModesAnimation';
}

function updateDetector() {
if ($scope.modelName == 'powerDensityReport' || $scope.modelName == 'coherentModesAnimation') {
panelState.showField($scope.modelName, 'useDetector', false);
}
const m = appState.models[modelKey];
if (m.useDetector === '1') {
m.usePlotRange = '0';
}
panelState.showField($scope.modelName, 'intensityPlotsWidth', m.useDetector === '0');
panelState.showField($scope.modelName, 'useDetectorAspectRatio', m.useDetector === '1');
panelState.showRow($scope.modelName, 'd_rx', m.useDetector === '1');
}

function updateIntensityLimit() {
srwService.updateIntensityLimit(
$scope.modelName,
$scope.modelData ? $scope.modelData.modelKey : null);
}

function updatePlotRange() {
srwService.updatePlotRange(
$scope.modelName,
Expand All @@ -972,6 +994,7 @@ var srwIntensityLimitLogic = function(appState, panelState, srwService, $scope)
function updateSelected() {
updateIntensityLimit();
updatePlotRange();
updateDetector();
var schemaModel = SIREPO.APP_SCHEMA.model[$scope.modelName];
if (schemaModel.fieldUnits) {
panelState.showField($scope.modelName, 'fieldUnits', srwService.isGaussianBeam());
Expand Down Expand Up @@ -1004,7 +1027,6 @@ var srwIntensityLimitLogic = function(appState, panelState, srwService, $scope)
]);
panelState.showField('simulation', 'photonEnergy', isSource);
}
var modelKey = $scope.modelData ? $scope.modelData.modelKey : $scope.modelName;
$scope.whenSelected = updateSelected;
$scope.watchFields = [
[
Expand All @@ -1014,6 +1036,9 @@ var srwIntensityLimitLogic = function(appState, panelState, srwService, $scope)
($scope.modelData ? $scope.modelData.modelKey : $scope.modelName)
+ '.usePlotRange',
], updatePlotRange,
[
modelKey + '.useDetector',
], updateDetector,
];
if (hasSamplingMethod()) {
$scope.watchFields.push(
Expand Down
32 changes: 29 additions & 3 deletions sirepo/package_data/static/json/srw-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -432,10 +432,10 @@
}
},
"frameIdFields": {
"beamlineAnimation": ["characteristic", "polarization", "intensityPlotsWidth", "rotateAngle", "rotateReshape", "useIntensityLimits", "minIntensityLimit", "maxIntensityLimit", "usePlotRange", "horizontalSize", "verticalSize", "horizontalOffset", "verticalOffset"],
"beamlineAnimation": ["characteristic", "polarization", "intensityPlotsWidth", "rotateAngle", "rotateReshape", "useIntensityLimits", "minIntensityLimit", "maxIntensityLimit", "usePlotRange", "horizontalSize", "verticalSize", "horizontalOffset", "verticalOffset", "useDetector", "d_rx", "d_nx", "d_x", "d_ry", "d_ny", "d_y", "useDetectorAspectRatio"],
"coherenceXAnimation": ["intensityPlotsWidth", "rotateAngle", "rotateReshape"],
"coherenceYAnimation": ["intensityPlotsWidth", "rotateAngle", "rotateReshape"],
"coherentModesAnimation": ["characteristic", "polarization", "plotModesStart", "plotModesEnd", "intensityPlotsWidth", "rotateAngle", "rotateReshape", "useIntensityLimits", "minIntensityLimit", "maxIntensityLimit", "usePlotRange", "horizontalSize", "verticalSize", "horizontalOffset", "verticalOffset", "plotModesStart", "plotModesEnd"],
"coherentModesAnimation": ["characteristic", "polarization", "plotModesStart", "plotModesEnd", "intensityPlotsWidth", "rotateAngle", "rotateReshape", "useIntensityLimits", "minIntensityLimit", "maxIntensityLimit", "usePlotRange", "horizontalSize", "verticalSize", "horizontalOffset", "verticalOffset", "plotModesStart", "plotModesEnd", "useDetector", "d_rx", "d_nx", "d_x", "d_ry", "d_ny", "d_y", "useDetectorAspectRatio"],
"fluxAnimation": [],
"multiElectronAnimation": ["intensityPlotsWidth", "rotateAngle", "rotateReshape"]
},
Expand Down Expand Up @@ -478,6 +478,15 @@
"verticalSize": ["Vertical Size [mm]", "Float", 1, "", 1e-99],
"horizontalOffset": ["Horizontal Center Position [mm]", "Float", 0],
"verticalOffset": ["Vertical Center Position [mm]", "Float", 0],
"useDetector": ["Use Detector", "Boolean", "0"],
"showPlotSize": ["Show Result Dimensions on Plot", "Boolean", "0"],
"d_x": ["Horizontal Center Position [m]", "Float", 0],
"d_rx": ["Horizontal Detector Range [m]", "Float", 0.01],
"d_nx": ["Horizontal Pixel Count", "Integer", 1024],
"d_y": ["Vertical Center Position [m]", "Float", 0],
"d_ry": ["Vertical Detector Range [m]", "Float", 0.01],
"d_ny": ["Vertical Pixel Count", "Integer", 1024],
"useDetectorAspectRatio": ["Use Detector Aspect Ratio", "Boolean", "0"],
"notes": ["Notes", "Text", ""]
},
"aperture": {
Expand Down Expand Up @@ -1129,7 +1138,6 @@
"basic": [],
"advanced": [
["View", [
"intensityPlotsWidth",
"plotScale",
"useIntensityLimits",
"minIntensityLimit",
Expand All @@ -1148,6 +1156,24 @@
"rotateAngle",
"rotateReshape"
]],
["Plot Size", [
"useDetector",
"intensityPlotsWidth",
[
["Horizontal", [
"d_rx",
"d_nx",
"d_x"
]],
["Vertical", [
"d_ry",
"d_ny",
"d_y"
]]
],
"useDetectorAspectRatio",
"showPlotSize"
]],
["Other", [
"colorMap",
"aspectRatio"
Expand Down
14 changes: 14 additions & 0 deletions sirepo/package_data/template/srw/parameters.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,20 @@ varParam = [
{% if beamline3DReport %}
['op_fno', 's', '{{beamline3DReportFilename}}', 'file name for saving orientations of optical elements in the lab frame'],
{% endif %}
{% if useDetector == '1' %}
#Detector parameters
['d_x', 'f', {{detector_d_x}}, 'central horizontal position [m] of detector active area'],
['d_rx', 'f', {{detector_d_rx}}, 'range of horizontal position [m] of detector active area (should be >0 to be taken into account)'],
['d_nx', 'i', {{detector_d_nx}}, 'number of pixels vs horizontal position (should be >0 to be taken into account)'],
['d_dx', 'f', 0., 'horizontal size of pixel [m]'],
['d_y', 'f', {{detector_d_y}}, 'central vertical position [m] of detector active area'],
['d_ry', 'f', {{detector_d_ry}}, 'range of vertical position [m] of detector active area (should be >0 to be taken into account)'],
['d_ny', 'i', {{detector_d_ny}}, 'number of pixels vs vertical position (should be >0 to be taken into account)'],
['d_dy', 'f', 0., 'vertical size of pixel [m]'],
['d_or', 'f', 1, 'interpolation order (i.e. order of polynomials to be used at 2D interpolation)'],
['d_ifn', 's', '', 'file name with detector spectral efficiency data (on 1D mesh vs photon energy: _eStart, _eFin, _ne)'],

{% endif %}
# Former appParam:
['rs_type', 's', '{{rs_type}}', 'source type, (u) idealized undulator, (t), tabulated undulator, (m) multipole, (g) gaussian beam'],
{% if rs_type == 'm' %}
Expand Down
3 changes: 3 additions & 0 deletions sirepo/sim_data/srw.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class SimData(sirepo.sim_data.SimDataBase):
"plotScale",
"rotateAngle",
"rotateReshape",
"showPlotSize",
"useIntensityLimits",
"usePlotRange",
"verticalOffset",
Expand Down Expand Up @@ -138,6 +139,8 @@ def fixup_old_data(cls, data, qcall, **kwargs):
if "fieldUnits" in dm[m]:
dm.simulation.fieldUnits = dm[m].fieldUnits
del dm[m]["fieldUnits"]
if "beamlineAnimation" in m:
cls.update_model_defaults(dm[m], cls.WATCHPOINT_REPORT)
# default sourceIntensityReport.method based on source type
if "method" not in dm.sourceIntensityReport:
if cls.srw_is_undulator_source(dm.simulation):
Expand Down
27 changes: 25 additions & 2 deletions sirepo/template/srw.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,12 +513,24 @@ def sim_frame(frame_args):
frame_args.sim_in.report = "initialIntensityReport"
frame_args.sim_in.models.initialIntensityReport = m
data_file = _OUTPUT_FOR_MODEL.initialIntensityReport.filename
detector = None
m = frame_args.sim_in.models[r]
if str(m.get("useDetector", "0")) == "1":
detector = srwpy.srwl_bl.SRWLBeamline().set_detector(
_x=float(m.d_x),
_y=float(m.d_y),
_nx=int(m.d_nx),
_ny=int(m.d_ny),
_rx=float(m.d_rx),
_ry=float(m.d_ry),
)
srwpy.srwl_bl.SRWLBeamline().calc_int_from_wfr(
wfr,
_pol=int(frame_args.polarization),
_int_type=int(frame_args.characteristic),
_fname=data_file,
_pr=False,
_det=detector,
)
if "beamlineAnimation" not in r:
# some reports may be written at the same time as the reader
Expand Down Expand Up @@ -1996,6 +2008,10 @@ def _generate_parameters_file(data, plot_reports=False, run_dir=None, qcall=None
v.python_file = run_dir.join("user_python.py")
pkio.write_text(v.python_file, dm.backgroundImport.python)
return template_common.render_jinja(SIM_TYPE, v, "import.py")
if report in dm and str(dm[report].get("useDetector", "0")) == "1":
v.useDetector = "1"
for f in ("d_x", "d_rx", "d_nx", "d_y", "d_ry", "d_ny"):
v[f"detector_{f}"] = dm[report][f]
_set_parameters(v, data, plot_reports, run_dir, qcall=qcall)
v.in_server = run_dir is not None
return _trim(res + template_common.render_jinja(SIM_TYPE, v))
Expand Down Expand Up @@ -2244,7 +2260,7 @@ def _remap_3d(info, allrange, out, report):
z_range = [report.minIntensityLimit, report.maxIntensityLimit]
else:
z_range = [np.min(ar2d), np.max(ar2d)]
return PKDict(
res = PKDict(
x_range=x_range,
y_range=y_range,
x_label=info.x_label,
Expand All @@ -2256,6 +2272,13 @@ def _remap_3d(info, allrange, out, report):
z_range=z_range,
summaryData=info.summaryData,
)
if (
str(report.get("useDetector", "0")) == "1"
and str(report.get("useDetectorAspectRatio", "0")) == "1"
and float(report.d_rx) != 0
):
res.aspectRatio = float(report.d_ry) / float(report.d_rx)
return res


def _reshape_3d(ar1d, allrange, report):
Expand All @@ -2277,7 +2300,7 @@ def _reshape_3d(ar1d, allrange, report):

def _resize_report(report, ar2d, x_range, y_range):
width_pixels = int(report.get("intensityPlotsWidth", 0))
if not width_pixels:
if not width_pixels or str(report.get("useDetector", "0")) == "1":
# upper limit is browser's max html canvas size
width_pixels = _CANVAS_MAX_SIZE
# rescale width and height to maximum of width_pixels
Expand Down
Loading