Skip to content

Application PseudoCode

Paul Moeller edited this page Jun 9, 2022 · 9 revisions

Pseudocode for parts of the SRW application.

//---- file: srw-view.json (or yml or ...)
// view schema much as before, with additional static info (ex. plotType)
//  or arbitrary constants, (ex. fluxPerUnitSurfaceTitle)
// the view schema could be kept separately from the model info which isn't
// needed by the server logic

// ex. view schema
{
    fluxAnimation: {
        title: "Spectral Flux",
        fluxPerUnitSurfaceTitle: "Spectral Flux per Unit Surface for Finite Emittance Electron Beam",
        plotType: "parameter",
        advanced: [
            ["Main", [
                "distanceFromSource",
                "initialEnergy",
                "finalEnergy",
                "photonEnergyPointCount",
                "numberOfMacroElectronsAvg",
                "savingPeriodicity",
                [
                    ["Horizontal", [
                        "horizontalApertureSize",
                        "horizontalPosition"
                    ]],
                    ["Vertical", [
                        "verticalApertureSize",
                        "verticalPosition"
                    ]]
                ],
                "fluxType",
                "polarization",
                "plotScale",
                "notes"
            ]],
            ["Accuracy", [
                "magneticField",
                "method",
                "precision",
                "numberOfMacroElectrons",
                "initialHarmonic",
                "finalHarmonic",
                "longitudinalPrecision",
                "azimuthalPrecision"
            ]]
        ]
    },
    ...
}


//---- file: srw.js
from enum import Flux, SourceType
// saved is the saved model state
//  (appState.applicationState() in the current app)
//  ex. saved.simulation is appState.applicationState().simulation
import saved
import util

// application specific business logic, similar to srwService
srw = {
    fluxTitle: panel => {
        // panel is an Panel instance (ReportPanel, EditorPanel, etc)
        // panel.model is a model instance
        // panel.title and other attrs come from view info in schema
        return self.titleWithPosition(
            panel,
            panel.model.fluxType == Flux.PerUnitSurface
                ? panel.fluxPerUnitSurfaceTitle
                : panel.title
        );
    },
    titleWithPosition: (panel, title) =>
        "{title || panel.title} "
        + util.formatNumberWithUnits(panel.model, 'distanceFromSource');
};

app.addTabContent(
    'source',
    // panel instances would be EditorPanel or ReportPanel based on the model type
    panels: [
       'electronBeam',
       'arbitraryMagField',
       'undulator',
       'tabulatedUndulator',
       'multipole',
       'gaussianBeam',
       'intensityReport',
       'trajectoryReport',
       'fluxReport',
       'fluxAnimation',
       'powerDensityReport',
       'sourceIntensityReport',
       'brillianceReport',
    ],
);

app.addTabContent(
    'beamline',
    Join([
        BeamlineToolbar(),
        BeamlineBuilder({
            leftButton: ModalEditorButton('simulationGrid'),
            rightButton: ModalEditorButton('propagationParameters'),
        }),
        Tabs([
            Tab('single', BeamlineAnimationPanels()),
            Tab('multi', Panels(
                ReportPanel('multiElectronAnimation'),
                If(() => saved.multiElectronAnimation.calcCoherence, [
                    ReportPanel('coherenceXAnimation'),
                    ReportPanel('coherenceYAnimation'),
                ]),
            )),
            Tab('beamline3d', ReportPanel('beamline3DReport')),
        ]),
    ]),
);

//--- file srw/undulatorView.js
import io
// "model" are schema models which are being edited, may be canceled
//  (appState.models in the current app)
//  ex. model.simulation is appState.models.simulation
from model import undulator
import saved
import ui
import util
import view

// view business logic, implementation is tied to schema view name
view.addView('undulator', {
    // private methods with leading underscore
    _compute: (undulatorDef, direction) => {
        const d = "{direction}DeflectionParameter";
        const a = "{direction}Amplitude";
        io.sendStatelessCompute(
            {
                method: 'process_undulator_definition',
                undulator_definition: undulatorDef,
                undulator_parameter: undulator[d],
                amplitude: undulator[a],
                undulator_period: undulator.period / 1000,
                methodSignature: 'process_undulator_definition' + d,
            }
            (reply) => {
                if (undulatorDef == 'K') {
                    undulator[a] = reply.amplitude;
                }
                else if (undulatorDefinition === 'B') {
                    undulator[d] = reply.undulator_parameter;
                }
                undulator.effectiveDeflectingParameter = util.formatNumber(
                    Math.sqrt(
                        Math.pow(undulator.horizontalDeflectingParameter, 2) +
                            Math.pow(undulator.verticalDeflectingParameter, 2)
                    ),
                    8,
                );
            },
        );
    _updateUndulator: () => {
        if (ui.isActiveField('undulator.horizontalAmplitude')) {
            _compute('B', 'horizontal');
        }
        elif (ui.isActiveField('undulator.verticalAmplitude')) {
            _compute('B', 'vertical');
        }
        elif (ui.isActiveField('undulator.period')) {
            _compute('B', 'horizontal');
            _compute('B', 'vertical');
        }
        elif (ui.isActiveField('undulator.horizontalDeflectingParameter')) {
            _compute('K', 'horizontal');
        }
        elif (ui.isActiveField('undulator.verticalDeflectingParameter')) {
            _compute('K', 'vertical');
        }
    },

    // could also have special methods for computed titles, ex. panelTitle()

    showPanel: () => saved.simulation.sourceType.isIdealizedUndulator(),
    // or the same thing:
    showPanel: saved.simulation.sourceType.isIdealizedUndulator,

    whenShown: () => {
        ui.enableField('undulator.effectiveDeflectingParameter', false);
    },
    watchFields: [
        ((
            'undulator.horizontalDeflectingParameter',
            'undulator.verticalDeflectingParameter'
            'undulator.horizontalAmplitude',
            'undulator.verticalAmplitude',
            'undulator.period',
        ), _updateUndulator),
    ],
});
Clone this wiki locally