Skip to content

Commit

Permalink
Merge 7bf0255 into db479d7
Browse files Browse the repository at this point in the history
  • Loading branch information
james-strauss-uwa committed Nov 5, 2020
2 parents db479d7 + 7bf0255 commit 7bf0408
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 34 deletions.
2 changes: 1 addition & 1 deletion OpenAPI/tests/translator_test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
lg_name='test', algo='metis', num_islands=1)
print(html_content)
html_content = translator.gen_pg(
pgt_id='test', dlg_mgr_host='127.0.0.1', dlg_mgr_port=8001)
pgt_id='test', dlg_mgr_host='127.0.0.1', dlg_mgr_port=8001, dlg_mgr_deploy='deploy')
4 changes: 4 additions & 0 deletions OpenAPI/translator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ paths:
type: integer
in: query
name: dlg_mgr_port
- schema:
type: string
in: query
name: dlg_mgr_deploy
37 changes: 23 additions & 14 deletions daliuge-translator/dlg/dropmake/web/lg_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,9 @@ def gen_pg():
RESTful interface to convert a PGT(P) into PG by mapping
PGT(P) onto a given set of available resources
"""
# if the 'deploy' checkbox is not checked, then the form submission will NOT contain a 'dlg_mgr_deploy' field
deploy = request.query.get("dlg_mgr_deploy") is not None

pgt_id = request.query.get("pgt_id")
pgtp = pg_mgr.get_pgt(pgt_id)
if pgtp is None:
Expand All @@ -355,20 +358,26 @@ def gen_pg():
node_list = mgr_client.nodes()
# 2. mapping PGTP to resources (node list)
pg_spec = pgtp.to_pg_spec([mhost] + node_list, ret_str=False)
dt = datetime.datetime.now().strftime("%Y-%m-%dT%H-%M-%S.%f")
ssid = "{0}_{1}".format(
pgt_id.split(".json")[0].split("_pgt")[0].split("/")[-1], dt
)
mgr_client.create_session(ssid)
# print "session created"
mgr_client.append_graph(ssid, pg_spec)
# print "graph appended"
completed_uids = common.get_roots(pg_spec)
mgr_client.deploy_session(ssid, completed_uids=completed_uids)
# mgr_client.deploy_session(ssid, completed_uids=[])
# print "session deployed"
# 3. redirect to the master drop manager
redirect("http://{0}:{1}/session?sessionId={2}".format(mhost, mport, ssid))

if deploy:
dt = datetime.datetime.now().strftime("%Y-%m-%dT%H-%M-%S.%f")
ssid = "{0}_{1}".format(
pgt_id.split(".json")[0].split("_pgt")[0].split("/")[-1], dt
)
mgr_client.create_session(ssid)
# print "session created"
mgr_client.append_graph(ssid, pg_spec)
# print "graph appended"
completed_uids = common.get_roots(pg_spec)
mgr_client.deploy_session(ssid, completed_uids=completed_uids)
# mgr_client.deploy_session(ssid, completed_uids=[])
# print "session deployed"
# 3. redirect to the master drop manager
redirect("http://{0}:{1}/session?sessionId={2}".format(mhost, mport, ssid))
else:
response.content_type = 'application/json'
response.set_header("Content-Disposition", "attachment; filename=%s" % (pgt_id))
return json.dumps(pg_spec)
except restutils.RestClientException as re:
response.status = 500
return "Fail to interact with DALiUGE Drop Manager: {0}".format(re)
Expand Down
85 changes: 66 additions & 19 deletions daliuge-translator/dlg/dropmake/web/pg_viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,17 @@
box.innerHTML = "";
}
}, false);

// add event listener to the "deploy" checkbox so that when the checkbox is used,
// the form submit button is updated to reflect the behaviour
var deployCheckbox = document.getElementById('dlg_mgr_deploy');
deployCheckbox.addEventListener("change", function(){
if (deployCheckbox.checked){
document.getElementById('gen_pg_button').value = "Generate & Deploy Physical Graph";
} else {
document.getElementById('gen_pg_button').value = "Generate Physical Graph";
}
});
} // end init

// Called when the mouse is over the diagram's background
Expand Down Expand Up @@ -454,6 +465,25 @@
window.open(url)
}

function makeJSON() {
console.log("makeJSON()");

$.ajax({
url: "/pgt_jsonbody?pgt_name={{pgt_view_json_name}}",
type: 'get',
error: function(XMLHttpRequest, textStatus, errorThrown) {
if (404 == XMLHttpRequest.status) {
console.error('Server cannot locate physical graph file {{pgt_view_json_name}}');
} else {
console.error('status:' + XMLHttpRequest.status + ', status text: ' + XMLHttpRequest.statusText);
}
},
success: function(data){
downloadText('{{pgt_view_json_name}}', data);
}
});
}

function makePNG() {
//zoomToFit();

Expand Down Expand Up @@ -481,39 +511,54 @@
}
}

function getCWLZipFilenameFromResponseURL(url){
const FILE_NAME_PREFIX = "pgt_name=";
return url.substring(url.lastIndexOf(FILE_NAME_PREFIX) + FILE_NAME_PREFIX.length, url.lastIndexOf('.graph')) + ".zip";
function createZipFilename(graph_name){
return graph_name.substr(0, graph_name.lastIndexOf('.graph')) + '.zip';
}

function downloadText(filename, text) {
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);

element.style.display = 'none';
document.body.appendChild(element);

element.click();

document.body.removeChild(element);
}

// build an object URL from the blob and 'download' it
function downloadBlob(filename, blob) {
const url = window.URL.createObjectURL(blob);

const element = document.createElement('a');
element.setAttribute('href', url);
element.setAttribute('download', filename);

element.style.display = 'none';
document.body.appendChild(element);

element.click();

window.URL.revokeObjectURL(url);
document.body.removeChild(element);
}

function makeCWL() {
var fileName = "";
var error = "";

fetch('/pgt_cwl?pgt_name={{pgt_view_json_name}}')
.then(async resp => {

// if fetch was not successful, await the error message in the body of the response
if (resp.status !== 200){
error = await resp.text();
return;
}

// otherwise, re-generate a filename for the download
filename = getCWLZipFilenameFromResponseURL(resp.url);

return resp.blob();
})
.then(blob => {
// build an object URL from the response and 'download' it
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
downloadBlob(createZipFilename('{{pgt_view_json_name}}'), blob);
})
.catch(() => alert(error)); // present error, if it occurred
}
Expand Down Expand Up @@ -588,6 +633,7 @@
<div>
<button id="gantt_button" class="button" onclick="genGanttChart()">Produce Gantt Chart</button>
<button id="schedule_button" class="button" onclick="genScheduleChart()">Produce Schedule Matrix</button>
<button id="json_button" class="button" onclick="makeJSON()">Export to JSON</button>
<button id="png_button" class="button" onclick="makePNG()">Export to PNG</button>
<button id="cwl_button" class="button" onclick="makeCWL()">Export to CWL</button>
<button id="zoom_button" class="button" onclick="zoomToFit()">Zoom to Fit</button>
Expand All @@ -603,8 +649,9 @@
DALiuGE Manager host:<input type="text" name="dlg_mgr_host" value="localhost" size="40" style="font-size:16px;">
<!-- DALiuGE Manager port:<input type="number" name="dlg_mgr_port" value="8097" style="font-size:16px;"> -->
DALiuGE Manager port:<input type="number" name="dlg_mgr_port" value="8001" style="font-size:16px;">
Deploy:<input type="checkbox" id="dlg_mgr_deploy" name="dlg_mgr_deploy" value="deploy" checked>
<br/>
<input type="submit" value="Generate &amp; Deploy Physical Graph" class="button">
<input id="gen_pg_button" type="submit" value="Generate &amp; Deploy Physical Graph" class="button">
<input type="hidden" name="pgt_id" value="{{pgt_view_json_name}}">
</form>
</div>
Expand Down
104 changes: 104 additions & 0 deletions docs/writing_an_application.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,107 @@ Application authors need only call one or more times the
:attr:`write <dlg.drop.AbstractDROP.write>` method
with the data that needs to be written.

Automatic EAGLE Component Generation
------------------------------

When writing an application, developers should add specific custom
`Doxygen <https://www.doxygen.nl/>`_ comments to the source code.
These comments describe the application and can
be used to automatically generate a DALiuGE component so that the
application can be used in the *EAGLE* Logical Graph Editor.

The comments should be contained within a *EAGLE_START* and *EAGLE_END*
pair.

The *category* param is should be set to *DynlibApp* for C/C++ code,
and *PythonApp* for Python code.

These comments describe both the input/output ports for a component,
and the parameters of a component. Shown below are example comments
for C/C++ and Python applications.

C/C++

.. code-block:: c
/*!
* \brief Load a CASA Measurement Set in the DaliugeApplication Framework
* \details We will build on the LoadParset structure - but use the contents
* of the parset to load a measurement set.
* \par EAGLE_START
* \param gitrepo $(GIT_REPO)
* \param version $(PROJECT_VERSION)
* \param category DynlibApp
* \param[in] param/start_frequency/500/Integer
* \~English the start frequency to read from\n
* \~Chinese 要读取的起始频率\n
* \~
* \param[in] param/end_frequency/500/Integer
* \~English the end frequency to read from\n
* \~Chinese 要读取的结束频率\n
* \~
* \param[in] param/channels/64/Integer
* \~English how many channels to load\n
* \~Chinese 需要加载的通道数量\n
* \~
* \param[in] port/config
* \~English the configuration of the input_port\n
* \~Chinese 输入端口的设置\n
* \~
* \param[in] port/event
* \~English the event of the input_port\n
* \~Chinese 输入端口的事件\n
* \~
* \param[out] port/File
* \~English the file of the output_port \n
* \~Chinese 输出端口的文件\n
* \~
* \par EAGLE_END
*/
Python

.. code-block:: python
##
# @brief Load a CASA Measurement Set in the DaliugeApplication Framework
# @details We will build on the LoadParset structure - but use the contents
# of the parset to load a measurement set.
# @par EAGLE_START
# @param gitrepo $(GIT_REPO)
# @param version $(PROJECT_VERSION)
# @param category PythonApp
# @param[in] param/start_frequency/500/Integer
# \~English the start frequency to read from\n
# \~Chinese 要读取的起始频率\n
# \~
# @param[in] param/end_frequency/500/Integer
# \~English the end frequency to read from\n
# \~Chinese 要读取的结束频率\n
# \~
# @param[in] param/channels/64/Integer
# \~English how many channels to load\n
# \~Chinese 需要加载的通道数量\n
# \~
# @param[in] port/config
# \~English the configuration of the input_port\n
# \~Chinese 输入端口的设置\n
# \~
# @param[in] port/event
# \~English the event of the input_port\n
# \~Chinese 输入端口的事件\n
# \~
# @param[out] port/File
# \~English the file of the output_port \n
# \~Chinese 输出端口的文件\n
# \~
# @par EAGLE_END
Once the comments are added to the source code and pushed to a repository
a continuous integration step should process the source code.
The processing will:

* combine the Doxygen output XML into a single XML file
* transform the XML into an EAGLE palette file
* push the palette file to the *ICRAR/EAGLE_test_repo* repository.

0 comments on commit 7bf0408

Please sign in to comment.