Modernize scan workflow and web deployment
This commit is contained in:
@@ -228,24 +228,52 @@ which matches how the packaged app currently handles simulation input/output.
|
||||
|
||||
###### Deploying on a web server ######
|
||||
|
||||
The browser version requires a server-side setup in addition to the static
|
||||
HTML/JavaScript files.
|
||||
The repository includes the browser assets, CGI runner, and a deployment
|
||||
script for an Apache-style server. With the default settings, run:
|
||||
|
||||
In particular:
|
||||
```bash
|
||||
sudo ./scripts/deploy-web.sh
|
||||
```
|
||||
|
||||
* the browser build uses `TrimSPweb.js` rather than the Electron-specific
|
||||
`TrimSPelec.js`
|
||||
* the simulation backend must be available on the server
|
||||
* a web-exposed helper/CGI layer is required to create input files, run the
|
||||
backend, and return the generated output
|
||||
The script builds the static Fortran engine and installs:
|
||||
|
||||
Notes:
|
||||
```text
|
||||
/var/www/html/TRIMSP-NL/ browser application
|
||||
/var/www/cgi-bin/singleTrimSP.cgi CGI runner
|
||||
/usr/local/bin/trimspNL TRIM.SP-NL engine
|
||||
```
|
||||
|
||||
* this repository does not currently include the CGI/backend helper used by
|
||||
the online deployment
|
||||
* a plain static web server is therefore not sufficient for running web
|
||||
simulations from this checkout
|
||||
* static hosting can still be used to test page loading only
|
||||
Deployment paths and ownership can be changed through environment variables:
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `TRIMSP_WEB_TARGET` | `/var/www/html/TRIMSP-NL` | Browser asset directory |
|
||||
| `TRIMSP_CGI_TARGET` | `/var/www/cgi-bin/singleTrimSP.cgi` | Installed CGI path |
|
||||
| `TRIMSP_BIN_TARGET` | `/usr/local/bin/trimspNL` | Installed engine path |
|
||||
| `TRIMSP_WEB_OWNER` | `apache` | Web file owner |
|
||||
| `TRIMSP_WEB_GROUP` | `apache` | Web file group |
|
||||
| `TRIMSP_BUILD_STATIC` | `1` | Build the static engine before deployment |
|
||||
| `TRIMSP_BINARY_SOURCE` | `fortran/trimspNL-static` | Binary used when installing |
|
||||
|
||||
For example, to deploy without rebuilding and use an existing binary:
|
||||
|
||||
```bash
|
||||
sudo TRIMSP_BUILD_STATIC=0 \
|
||||
TRIMSP_BINARY_SOURCE=/path/to/trimspNL \
|
||||
./scripts/deploy-web.sh
|
||||
```
|
||||
|
||||
The web server must execute the CGI through `/cgi-bin/singleTrimSP.cgi` and
|
||||
serve simulation files written below filesystem `/tmp` through URL `/tmp/`.
|
||||
Review that mapping carefully so it exposes only the intended simulation
|
||||
artifacts. On SELinux systems, inspect denied operations with:
|
||||
|
||||
```bash
|
||||
ausearch -m avc -ts recent
|
||||
```
|
||||
|
||||
The Apache account needs permission to execute the CGI and engine and to create
|
||||
the per-run directories in `/tmp`.
|
||||
|
||||
### Contact ###
|
||||
|
||||
|
||||
+38
-37
@@ -111,16 +111,27 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="Scans" class="tabcontent">
|
||||
<input type="checkbox" name="scanSeq" id="scanSeq" onChange="adjust_scans();"> Enable scan on
|
||||
<select name="scanType" id="scanType" onchange="adjust_scans();">
|
||||
<option value="scanLoop">Loop</option>
|
||||
<option value="scanVals">Set of values</option>
|
||||
</select>
|
||||
<div id="ScansControls" style="visibility: hidden;">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td colspan="1">Scan:
|
||||
<select name="comboScan" id="comboScan" onchange="">
|
||||
<section class="settings-panel scan-panel" aria-labelledby="scanPanelTitle">
|
||||
<div class="scan-heading">
|
||||
<div>
|
||||
<span class="section-eyebrow">Execution plan</span>
|
||||
<h2 id="scanPanelTitle">Parameter scan</h2>
|
||||
</div>
|
||||
<label class="scan-enable" for="scanSeq">
|
||||
<input type="checkbox" name="scanSeq" id="scanSeq" onchange="adjust_scans();">
|
||||
<span>Enable scan</span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="ScansControls" hidden>
|
||||
<div class="scan-controls-grid">
|
||||
<label class="settings-field" for="scanType"><span>Sequence</span>
|
||||
<select name="scanType" id="scanType" onchange="adjust_scans();">
|
||||
<option value="scanLoop">Range</option>
|
||||
<option value="scanVals">Set of values</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="settings-field" for="comboScan"><span>Parameter</span>
|
||||
<select name="comboScan" id="comboScan" onchange="updateScanSummary();">
|
||||
<option value="EScan">Energy [eV]</option>
|
||||
<option value="SigEScan">Energy sigma [eV]</option>
|
||||
<option value="AngleScan">Angle [deg]</option>
|
||||
@@ -128,33 +139,23 @@
|
||||
<option value="NProjScan">Number of projectiles</option>
|
||||
<option value="dScan">Thickness of layer # 1</option>
|
||||
</select>
|
||||
</td>
|
||||
<td colspan="1">
|
||||
Threads:
|
||||
<input name="scanThreads" id="scanThreads" type="number" min="1" step="1" value="" onchange="adjust_scans();">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="ScansLine" style="visibility: hidden;">
|
||||
<br>Set of values: <input name="scanList" id="scanList" type="text" value="1000">
|
||||
Corresponding depth increment: <input name="scanListdz" id="scanListdz" type="text" value="">
|
||||
</div>
|
||||
<table id="ScansTable" style="width: 100%;visibility: hidden;">
|
||||
<tr>
|
||||
<td>
|
||||
<!input type="radio" name="ScanType" value="Loop" checked onChange="">
|
||||
<!input type="radio" name="ScanType" value="ScanList" onChange="">
|
||||
From: <input name="scanFrom" id="scanFrom" type="text" value="1000">
|
||||
</td>
|
||||
<td>
|
||||
Step: <input name="scanStep" id="scanStep" type="text" value="2000">
|
||||
</td>
|
||||
<td>
|
||||
To: <input name="scanTo" id="scanTo" type="text" value="14000">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</label>
|
||||
<label class="settings-field" for="scanThreads"><span>Workers</span>
|
||||
<input name="scanThreads" id="scanThreads" type="number" min="1" step="1" value="" oninput="adjust_scans();">
|
||||
</label>
|
||||
</div>
|
||||
<div id="ScansTable" class="scan-values-panel scan-range-grid">
|
||||
<label class="settings-field" for="scanFrom"><span>From</span><input name="scanFrom" id="scanFrom" type="text" value="1000" oninput="updateScanSummary();"></label>
|
||||
<label class="settings-field" for="scanStep"><span>Step</span><input name="scanStep" id="scanStep" type="text" value="2000" oninput="updateScanSummary();"></label>
|
||||
<label class="settings-field" for="scanTo"><span>To</span><input name="scanTo" id="scanTo" type="text" value="14000" oninput="updateScanSummary();"></label>
|
||||
</div>
|
||||
<div id="ScansLine" class="scan-values-panel scan-list-grid" hidden>
|
||||
<label class="settings-field" for="scanList"><span>Values, separated by commas</span><input name="scanList" id="scanList" type="text" value="1000" oninput="updateScanSummary();"></label>
|
||||
<label class="settings-field" for="scanListdz"><span>Matching depth increments (optional)</span><input name="scanListdz" id="scanListdz" type="text" value="" oninput="updateScanSummary();"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="scanSummary" class="scan-summary" role="status" aria-live="polite">Single simulation using the Layers settings.</div>
|
||||
</section>
|
||||
</div>
|
||||
<div id="Plots" class="tabcontent">
|
||||
<table style="width: 100%;">
|
||||
|
||||
+82
-26
@@ -3351,11 +3351,12 @@ function adjust_table()
|
||||
|
||||
function adjust_scans()
|
||||
{
|
||||
// Deal with scans checkbox and type
|
||||
var scanSeq = document.getElementById("scanSeq").checked;
|
||||
var sender = document.getElementById("scanSeq");
|
||||
var scanType = document.getElementById("scanType").value;
|
||||
var scanThreads = document.getElementById("scanThreads");
|
||||
var scanControls = document.getElementById("ScansControls");
|
||||
var scanRange = document.getElementById("ScansTable");
|
||||
var scanList = document.getElementById("ScansLine");
|
||||
|
||||
// Default to half the available local worker slots, rounded down, while
|
||||
// keeping at least one process. Web mode keeps the default at 1 because
|
||||
@@ -3366,6 +3367,10 @@ function adjust_scans()
|
||||
availableThreads = Math.max(1, getParallelJobCount());
|
||||
}
|
||||
scanThreads.max = availableThreads;
|
||||
scanThreads.disabled = amIWeb();
|
||||
scanThreads.title = amIWeb()
|
||||
? 'The web backend currently runs scan points sequentially.'
|
||||
: `This computer provides up to ${availableThreads} worker slots.`;
|
||||
|
||||
if (scanThreads.value === "" || Number(scanThreads.value) < 1) {
|
||||
scanThreads.value = Math.max(1, Math.floor(availableThreads / 2));
|
||||
@@ -3374,23 +3379,85 @@ function adjust_scans()
|
||||
}
|
||||
}
|
||||
|
||||
// consider only if scans checkbox is checked
|
||||
if (scanSeq) {
|
||||
ShowHide(1,'ScansControls');
|
||||
// Which type of scan
|
||||
if (scanType == "scanLoop") {
|
||||
ShowHide(1,'ScansTable');
|
||||
ShowHide(0,'ScansLine');
|
||||
scanControls.hidden = !scanSeq;
|
||||
if (!scanSeq) {
|
||||
scanRange.hidden = true;
|
||||
scanList.hidden = true;
|
||||
} else if (scanType === "scanLoop") {
|
||||
scanRange.hidden = false;
|
||||
scanList.hidden = true;
|
||||
} else {
|
||||
scanRange.hidden = true;
|
||||
scanList.hidden = false;
|
||||
}
|
||||
|
||||
updateScanSummary();
|
||||
}
|
||||
|
||||
function updateScanSummary()
|
||||
{
|
||||
var summary = document.getElementById("scanSummary");
|
||||
if (!summary) { return; }
|
||||
|
||||
if (!document.getElementById("scanSeq").checked) {
|
||||
summary.dataset.level = "idle";
|
||||
summary.textContent = "Single simulation using the Layers settings.";
|
||||
return;
|
||||
}
|
||||
|
||||
var scanType = document.getElementById("scanType").value;
|
||||
var parameterSelect = document.getElementById("comboScan");
|
||||
var parameter = parameterSelect.options[parameterSelect.selectedIndex].text;
|
||||
var workers = Number(document.getElementById("scanThreads").value) || 1;
|
||||
var pointCount = 0;
|
||||
var detail = "";
|
||||
var warning = "";
|
||||
|
||||
if (scanType === "scanLoop") {
|
||||
var from = Number(document.getElementById("scanFrom").value);
|
||||
var step = Number(document.getElementById("scanStep").value);
|
||||
var to = Number(document.getElementById("scanTo").value);
|
||||
if (!Number.isFinite(from) || !Number.isFinite(step) || !Number.isFinite(to)) {
|
||||
warning = "Enter numeric From, Step, and To values.";
|
||||
} else if (step <= 0) {
|
||||
warning = "Step must be greater than zero.";
|
||||
} else if (to < from) {
|
||||
warning = "To must be greater than or equal to From.";
|
||||
} else {
|
||||
ShowHide(1,'ScansLine');
|
||||
ShowHide(0,'ScansTable');
|
||||
pointCount = Math.floor((to - from) / step) + 1;
|
||||
detail = `${from} to ${to}, step ${step}`;
|
||||
}
|
||||
} else {
|
||||
// Hide both
|
||||
ShowHide(0,'ScansControls');
|
||||
ShowHide(0,'ScansTable');
|
||||
ShowHide(0,'ScansLine');
|
||||
var values = document.getElementById("scanList").value
|
||||
.split(",")
|
||||
.map(value => value.trim())
|
||||
.filter(value => value !== "");
|
||||
var depthValues = document.getElementById("scanListdz").value
|
||||
.split(",")
|
||||
.map(value => value.trim())
|
||||
.filter(value => value !== "");
|
||||
if (values.length === 0) {
|
||||
warning = "Enter at least one scan value.";
|
||||
} else if (values.some(value => !Number.isFinite(Number(value)))) {
|
||||
warning = "Every scan value must be numeric.";
|
||||
} else if (depthValues.length > 0 && depthValues.length !== values.length) {
|
||||
warning = "Depth increments must match the number of scan values.";
|
||||
} else {
|
||||
pointCount = values.length;
|
||||
detail = values.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
summary.dataset.level = "warning";
|
||||
summary.textContent = warning;
|
||||
return;
|
||||
}
|
||||
|
||||
summary.dataset.level = "ready";
|
||||
var pointLabel = pointCount === 1 ? "point" : "points";
|
||||
var workerLabel = workers === 1 ? "worker" : "workers";
|
||||
summary.textContent = `${parameter} | ${pointCount} ${pointLabel} | ${workers} ${workerLabel} | ${detail}`;
|
||||
}
|
||||
|
||||
function ProjSmartDefaults()
|
||||
@@ -3419,17 +3486,6 @@ function ProjNumberLimit()
|
||||
}
|
||||
|
||||
|
||||
function ShowHide(onoff,item) {
|
||||
// this function can switch item to visible/hidden onoff=1/0
|
||||
if(onoff){
|
||||
// document.getElementById(item).style.display = 'block';
|
||||
document.getElementById(item).style.visibility = "visible";
|
||||
} else {
|
||||
// document.getElementById(item).style.display = 'none';
|
||||
document.getElementById(item).style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
|
||||
function prep_cfg(toggle) {
|
||||
// This function collects various values and returns
|
||||
// toggle=1 : returns object with all values
|
||||
|
||||
@@ -339,23 +339,90 @@ input[type="button"]:hover {
|
||||
background: #f5f8f5;
|
||||
}
|
||||
|
||||
#ScansControls,
|
||||
#ScansLine,
|
||||
#ScansTable {
|
||||
margin-top: 12px;
|
||||
.scan-panel {
|
||||
margin: 0 auto;
|
||||
max-width: 900px;
|
||||
padding: 12px 14px;
|
||||
}
|
||||
|
||||
#ScansControls table,
|
||||
#ScansTable {
|
||||
.scan-heading {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.scan-heading h2 {
|
||||
color: var(--trim-deep);
|
||||
font-family: Georgia, "Times New Roman", serif;
|
||||
font-size: 1.08rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.scan-enable {
|
||||
align-items: center;
|
||||
background: var(--trim-panel-soft);
|
||||
border: 1px solid var(--trim-border);
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
gap: 7px;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
.scan-enable input {
|
||||
accent-color: var(--trim-accent);
|
||||
height: 16px;
|
||||
margin: 0;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.scan-controls-grid {
|
||||
display: grid;
|
||||
gap: 9px;
|
||||
grid-template-columns: minmax(160px, 0.8fr) minmax(240px, 1.4fr) minmax(100px, 0.5fr);
|
||||
}
|
||||
|
||||
.scan-values-panel {
|
||||
background: var(--trim-panel-soft);
|
||||
border: 1px solid var(--trim-border);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
display: grid;
|
||||
gap: 9px;
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#ScansControls td,
|
||||
#ScansTable td {
|
||||
padding: 6px;
|
||||
.scan-range-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.scan-list-grid {
|
||||
grid-template-columns: minmax(260px, 1.5fr) minmax(220px, 1fr);
|
||||
}
|
||||
|
||||
.scan-summary {
|
||||
background: #eef4f4;
|
||||
border-left: 3px solid var(--trim-focus);
|
||||
border-radius: 5px;
|
||||
color: #31515a;
|
||||
font-size: 0.8rem;
|
||||
margin-top: 11px;
|
||||
min-height: 31px;
|
||||
padding: 7px 10px;
|
||||
}
|
||||
|
||||
.scan-summary[data-level="idle"] {
|
||||
border-left-color: #91a3a7;
|
||||
color: var(--trim-muted);
|
||||
}
|
||||
|
||||
.scan-summary[data-level="warning"] {
|
||||
background: #fff1c9;
|
||||
border-left-color: #c79824;
|
||||
color: #674c0a;
|
||||
}
|
||||
|
||||
#Plots > table td {
|
||||
@@ -566,7 +633,10 @@ input[type="button"]:hover {
|
||||
|
||||
.output-settings,
|
||||
.layers-workspace,
|
||||
.projectile-grid {
|
||||
.projectile-grid,
|
||||
.scan-controls-grid,
|
||||
.scan-range-grid,
|
||||
.scan-list-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (C) 2026 Zaher Salman
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
web_target="${TRIMSP_WEB_TARGET:-/var/www/html/TRIMSP-NL}"
|
||||
cgi_target="${TRIMSP_CGI_TARGET:-/var/www/cgi-bin/singleTrimSP.cgi}"
|
||||
trimsp_target="${TRIMSP_BIN_TARGET:-/usr/local/bin/trimspNL}"
|
||||
web_owner="${TRIMSP_WEB_OWNER:-apache}"
|
||||
web_group="${TRIMSP_WEB_GROUP:-apache}"
|
||||
build_static="${TRIMSP_BUILD_STATIC:-1}"
|
||||
binary_source="${TRIMSP_BINARY_SOURCE:-$project_root/fortran/trimspNL-static}"
|
||||
plotly_source="$project_root/node_modules/plotly.js-dist/plotly.js"
|
||||
|
||||
if [[ "$build_static" == "1" ]]; then
|
||||
make -C "$project_root/fortran" trimspNL-static
|
||||
elif [[ "$build_static" != "0" ]]; then
|
||||
printf 'TRIMSP_BUILD_STATIC must be 0 or 1, not %s\n' "$build_static" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ ! -f "$binary_source" ]]; then
|
||||
printf 'TRIM.SP-NL binary not found: %s\n' "$binary_source" >&2
|
||||
printf 'Build it first or set TRIMSP_BINARY_SOURCE.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$plotly_source" ]]; then
|
||||
printf 'Plotly browser bundle not found: %s\n' "$plotly_source" >&2
|
||||
printf 'Run npm install before deploying.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
perl -c "$project_root/singleTrimSP.cgi" >/dev/null
|
||||
|
||||
# Install only files used by the browser application. Electron-specific code,
|
||||
# package metadata, tests, and Fortran sources stay outside the document root.
|
||||
install -d -m 0755 "$web_target" "$(dirname "$cgi_target")" "$(dirname "$trimsp_target")"
|
||||
install -m 0644 \
|
||||
"$project_root/TrimSP.html" \
|
||||
"$project_root/TrimSPlib.js" \
|
||||
"$project_root/TrimSPweb.js" \
|
||||
"$project_root/myplots.js" \
|
||||
"$project_root/ZGUI.css" \
|
||||
"$project_root/plotly.css" \
|
||||
"$project_root/icon.png" \
|
||||
"$web_target/"
|
||||
install -m 0644 "$plotly_source" "$web_target/plotly.js"
|
||||
ln -sfn TrimSP.html "$web_target/index.html"
|
||||
|
||||
install -m 0755 "$binary_source" "$trimsp_target"
|
||||
|
||||
# Keep the repository CGI generic while embedding the selected installed
|
||||
# binary path in the deployed copy.
|
||||
cgi_stage="$(mktemp)"
|
||||
trap 'rm -f "$cgi_stage"' EXIT
|
||||
escaped_trimsp_target="${trimsp_target//\\/\\\\}"
|
||||
escaped_trimsp_target="${escaped_trimsp_target//&/\\&}"
|
||||
escaped_trimsp_target="${escaped_trimsp_target//|/\\|}"
|
||||
sed "s|^\\\$trimbin=.*|\$trimbin=\"timeout 300 $escaped_trimsp_target\";|" \
|
||||
"$project_root/singleTrimSP.cgi" > "$cgi_stage"
|
||||
install -m 0755 "$cgi_stage" "$cgi_target"
|
||||
|
||||
if getent passwd "$web_owner" >/dev/null 2>&1 && getent group "$web_group" >/dev/null 2>&1; then
|
||||
chown -R "$web_owner:$web_group" "$web_target"
|
||||
chown "$web_owner:$web_group" "$cgi_target"
|
||||
else
|
||||
printf 'Warning: owner/group %s:%s does not exist; ownership was not changed.\n' \
|
||||
"$web_owner" "$web_group" >&2
|
||||
fi
|
||||
|
||||
if command -v restorecon >/dev/null 2>&1; then
|
||||
restorecon -RF "$web_target" "$cgi_target" "$trimsp_target" || true
|
||||
fi
|
||||
|
||||
printf 'Installed TRIMSP-NL web assets in %s\n' "$web_target"
|
||||
printf 'Installed TRIMSP-NL CGI runner at %s\n' "$cgi_target"
|
||||
printf 'Installed TRIM.SP-NL engine at %s\n' "$trimsp_target"
|
||||
printf '\nThe web server must provide:\n'
|
||||
printf ' /cgi-bin/singleTrimSP.cgi -> %s\n' "$cgi_target"
|
||||
printf ' /tmp/ -> /tmp/ (simulation results and archives)\n'
|
||||
printf 'For SELinux deployments, verify CGI execution and write access with:\n'
|
||||
printf ' ausearch -m avc -ts recent\n'
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Copyright Zaher Salman 2023-.
|
||||
# zaher.salman@psi.ch
|
||||
|
||||
######## Relevant subdirectories and urls ########
|
||||
# May need modification on different servers
|
||||
$trimbin="timeout 300 /usr/local/bin/trimspNL";
|
||||
$workroot="/tmp";
|
||||
|
||||
# Nothing need to be changed from here on
|
||||
#######################################################################
|
||||
######## Main body of code ########
|
||||
use CGI;
|
||||
|
||||
my $in = new CGI;
|
||||
# Collect parameters and their values from CGI
|
||||
my ($name,$value);
|
||||
$content = "";
|
||||
my $filename = "";
|
||||
my $rngType = "pcg32";
|
||||
my $lcount = 0;
|
||||
foreach $name ($in->param) {
|
||||
$value=$in->param($name);
|
||||
if ($name eq "fn") {
|
||||
# This is the file name
|
||||
$filename = $value;
|
||||
@prefix = split(/\//,$filename);
|
||||
$randName = $prefix[2];
|
||||
$FILENAME = $prefix[3];
|
||||
} elsif ($name eq "rngType") {
|
||||
# RNG backend passed as the optional second trimspNL argument.
|
||||
if ($value =~ /^(ranlux|pcg32|xoshiro|xoshiro256)$/) {
|
||||
$rngType = $value;
|
||||
}
|
||||
} elsif ( index($name, "line") == 0) {
|
||||
# This is a line start counting
|
||||
#if ($lcount <=14) {
|
||||
# Limit number of lines (15) to avoid abuse
|
||||
$content = $content.$value."\n";
|
||||
#}
|
||||
$lcount++;
|
||||
}
|
||||
}
|
||||
$workPath = $workroot."/".$randName;
|
||||
if (-d $workPath) {
|
||||
# Directory exists, do nothing
|
||||
} else {
|
||||
$cmd="mkdir ".$workPath;
|
||||
system($cmd);
|
||||
}
|
||||
$filename = $workPath."/".$FILENAME;
|
||||
$fname = $filename;
|
||||
$fname =~ s/\.inp$//;
|
||||
$runBase = $FILENAME;
|
||||
$runBase =~ s/\.inp$//;
|
||||
open (OUTF,q{>}, $filename);
|
||||
print OUTF ($content);
|
||||
close(OUTF);
|
||||
|
||||
print ("Content-type: text/ascii \n\n");
|
||||
if (index($filename,"_Seq_Results.dat") != -1) {
|
||||
# This is the final call of a scan
|
||||
$cmd = "cd $workPath; rm -f edist;";
|
||||
$cmd = $cmd."tar -cvzf ../$randName.tgz *; cd ..; rm -rf $randName;";
|
||||
} elsif (index($filename,"TrimSP.cfg") != -1) {
|
||||
# Save config file only
|
||||
$cmd = "cd $workPath;";
|
||||
} else {
|
||||
# This is a call to simulate one step in a scan
|
||||
$cmd = "cd $workPath; $trimbin $runBase $rngType >> /tmp/debug;";
|
||||
}
|
||||
system($cmd);
|
||||
#print "Written file $filename\n";
|
||||
#print $content;
|
||||
print "command $cmd\n";
|
||||
foreach $name ($in->param) {
|
||||
$value=$in->param($name);
|
||||
print $name,"=",$value,"\n";
|
||||
}
|
||||
|
||||
exit(0);
|
||||
Reference in New Issue
Block a user