Skip to content

Hello World Application

Paul Moeller edited this page Jan 22, 2018 · 21 revisions

Creating a new sirepo application

Let's add a new sirepo app, named "myapp". Full source for the application can be found in the sirepo branch hello-world.

First, create the schema for the application. The myapp schema contains a model named "dog" with a few basic attributes.

sirepo/package_data/static/json/myapp-schema.json

 {
    "enum": {
        "Gender": [
            ["male", "Male"],
            ["female", "Female"]
        ]
    },
    "model": {
        "dog": {
            "breed": ["Breed", "String"],
            "gender": ["Gender", "Gender"],
            "height": ["Height [cm]", "Float", null, "Distance from front paws to withers"],
            "weight": ["Weight [lbs]", "Float"]
        },
        "dogReport": {},
        "simulation": {
            "name": ["Name", "String"]
        },
        "simulationFolder": {
            "name": ["Folder Name", "String"]
        }
    },
    "view": {
        "dog": {
            "title": "Dog",
            "basic": [
                "breed",
                "weight",
                "height"
            ],
            "advanced": [
                "breed",
                "gender",
                "weight",
                "height"
            ]
        },
        "dogReport": {
            "title": "Dog Report",
            "advanced": []
        },
        "simulation": {
            "title": "Simulation",
            "advanced": [
                "name"
            ]
        },
        "simulationFolder": {
            "title": "New Folder",
            "advanced": [
                "name"
            ]
        }
    }
}

When a new simulation is created, the default-data.json file contains the initial values.

sirepo/package_data/template/myapp/default-data.json

{
    "models": {
        "dog": {
            "breed": "Labrador Retriever",
            "gender": "female",
            "height": 50,
            "weight": 60.5
        },
        "dogReport": {},
        "simulation": {
            "folder": "/",
            "isExample": false,
            "name": "example",
            "outOfSessionSimulationId": "",
            "simulationId": "gLicZdXs",
            "simulationSerial": 1487981155340231
        }
    },
    "simulationType": "myapp",
    "version": "20170720.000000"
}

Next we'll need the javascript application which contains an angularjs controller for the source page and the application header.

sirepo/package_data/static/js/myapp.js

'use strict';

var srlog = SIREPO.srlog;
var srdbg = SIREPO.srdbg;

SIREPO.app.config(function($routeProvider, localRoutesProvider) {
    if (SIREPO.IS_LOGGED_OUT) {
        return;
    }
    var localRoutes = localRoutesProvider.$get();
    $routeProvider
        .when(localRoutes.source, {
            controller: 'MyAppSourceController as source',
            templateUrl: '/static/html/myapp-source.html' + SIREPO.SOURCE_CACHE_KEY,
        });
});

SIREPO.app.controller('MyAppSourceController', function () {
    var self = this;
});

SIREPO.app.directive('appHeader', function(appState, panelState) {
    return {
        restrict: 'A',
        scope: {
            nav: '=appHeader',
        },
        template: [
            '<div data-app-header-brand="nav"></div>',
            '<div data-app-header-left="nav"></div>',
            '<div data-app-header-right="nav">',
              '<app-header-right-sim-loaded>',
		'<div data-sim-sections="">',
                  '<li class="sim-section" data-ng-class="{active: nav.isActive(\'source\')}"><a href data-ng-click="nav.openSection(\'source\')"><span class="glyphicon glyphicon-flash"></span> Source</a></li>',
                  '<li class="sim-section" data-ng-class="{active: nav.isActive(\'beamline\')}"><a href data-ng-click="nav.openSection(\'beamline\')"><span class="glyphicon glyphicon-option-horizontal"></span> Beamline</a></li>',
                '</div>',
              '</app-header-right-sim-loaded>',
              '<app-settings>',
		//  '<div>App-specific setting item</div>',
	      '</app-settings>',
              '<app-header-right-sim-list>',
              '</app-header-right-sim-list>',
            '</div>',
	].join(''),
    };
});

The myapp.js refers to the myapp-source.html file for the definition of the "Source" page.

sirepo/package_data/static/html/myapp-source.html

<div class="container-fluid">
  <div class="row">
    <div class="col-md-6">
        <div data-basic-editor-panel="" data-view-name="dog"></div>
    </div>
    <div class="col-md-6">
      <div data-report-panel="parameter" data-model-name="dogReport"></div>
    </div>
  </div>
</div>

The myapp-source.html will arrange the dog editor and report.


images/hello-world-myapp.png


The server components are comprised of the application code generator (template/myapp.py) and the executor (pkcli/myapp.py).

sirepo/template/myapp.py

# -*- coding: utf-8 -*-
u"""Myapp execution template.

:copyright: Copyright (c) 2017 RadiaSoft LLC.  All Rights Reserved.
:license: http://www.apache.org/licenses/LICENSE-2.0.html
"""

from __future__ import absolute_import, division, print_function
from pykern import pkcollections
from pykern import pkio
from pykern import pkjinja
from pykern.pkdebug import pkdc, pkdp
from sirepo.template import template_common

SIM_TYPE = 'myapp'

def fixup_old_data(data):
    pass


def models_related_to_report(data):
    r = data['report']
    return [
        r,
        'dog',
    ]


def python_source_for_model(data, model):
    return ''


def write_parameters(data, schema, run_dir, is_parallel):
    pkio.write_text(
        run_dir.join(template_common.PARAMETERS_PYTHON_FILE),
        '# python code goes here\n'
    )

sirepo/pkcli/myapp.py

# -*- coding: utf-8 -*-
"""Wrapper to run myapp from the command line.

:copyright: Copyright (c) 2017 RadiaSoft LLC.  All Rights Reserved.
:license: http://www.apache.org/licenses/LICENSE-2.0.html
"""
from __future__ import absolute_import, division, print_function
from pykern import pkio
from pykern.pkdebug import pkdp, pkdc
from sirepo import simulation_db
from sirepo.template import template_common
import sirepo.template.myapp as template

_SCHEMA = simulation_db.get_schema(template.SIM_TYPE)


def run(cfg_dir):
    with pkio.save_chdir(cfg_dir):
        exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals())
    data = simulation_db.read_json(template_common.INPUT_BASE_NAME)
    if data['report'] == 'dogReport':
        dog = data.models.dog
        res = {
            'title': 'Dog Height/Weight',
            'x_range': [0, 1],
            'y_label': 'y label',
            'x_label': 'x label',
            'x_points': [0, 1],
            'points': [
                [dog.height, dog.height],
                [dog.weight, dog.weight],
            ],
            'y_range': [0, max(dog.height, dog.weight)],
            'y1_title': _SCHEMA['model']['dog']['height'][0],
            'y2_title': _SCHEMA['model']['dog']['weight'][0],
        }
    else:
        raise RuntimeError('unknown report: {}'.format(data['report']))
    simulation_db.write_result(res)

Now the application is ready to be added to the sirepo configuration files:

sirepo/feature_config.py

...
#: All possible codes
_ALL_CODES = ('srw', 'warppba', 'elegant', 'shadow', 'hellweg', 'warpvnd', 'myapp')

sirepo/package_data/static/json/schema-common.json

    "appInfo": {
        "myapp": {
            "longName": "MyApp",
            "shortName": "MyApp"
        },
    ...

The app is ready to run. Start the sirepo server from the command line:

$ sirepo service http

Then open your web browser http://localhost:8000/myapp

Clone this wiki locally