Browse Source

add saving spectra to file

Konstantin Ladutenko 3 years ago
parent
commit
3c159fc932

+ 24 - 0
guiapp/package-lock.json

@@ -11,6 +11,7 @@
         "@quasar/extras": "^1.0.0",
         "core-js": "^3.6.5",
         "cubic-spline-ts": "^3.0.8",
+        "file-saver": "^2.0.5",
         "lodash": "^4.17.21",
         "mathjs": "^9.5.0",
         "plotly.js-dist-min": "^2.6.2",
@@ -22,6 +23,7 @@
         "@babel/eslint-parser": "^7.13.14",
         "@quasar/app": "^3.0.0",
         "@types/emscripten": "^1.39.5",
+        "@types/file-saver": "^2.0.4",
         "@types/lodash": "^4.14.175",
         "@types/node": "^12.20.21",
         "@types/plotly.js-dist-min": "^2.3.0",
@@ -2298,6 +2300,12 @@
         "@types/range-parser": "*"
       }
     },
+    "node_modules/@types/file-saver": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.4.tgz",
+      "integrity": "sha512-sPZYQEIF/SOnLAvaz9lTuydniP+afBMtElRTdYkeV1QtEgvtJ7qolCPjly6O32QI8CbEmP5O/fztMXEDWfEcrg==",
+      "dev": true
+    },
     "node_modules/@types/glob": {
       "version": "7.1.4",
       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
@@ -6713,6 +6721,11 @@
         "url": "https://opencollective.com/webpack"
       }
     },
+    "node_modules/file-saver": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+    },
     "node_modules/filename-reserved-regex": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
@@ -16412,6 +16425,12 @@
         "@types/range-parser": "*"
       }
     },
+    "@types/file-saver": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.4.tgz",
+      "integrity": "sha512-sPZYQEIF/SOnLAvaz9lTuydniP+afBMtElRTdYkeV1QtEgvtJ7qolCPjly6O32QI8CbEmP5O/fztMXEDWfEcrg==",
+      "dev": true
+    },
     "@types/glob": {
       "version": "7.1.4",
       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
@@ -19931,6 +19950,11 @@
         }
       }
     },
+    "file-saver": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+    },
     "filename-reserved-regex": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",

+ 2 - 0
guiapp/package.json

@@ -13,6 +13,7 @@
     "@quasar/extras": "^1.0.0",
     "core-js": "^3.6.5",
     "cubic-spline-ts": "^3.0.8",
+    "file-saver": "^2.0.5",
     "lodash": "^4.17.21",
     "mathjs": "^9.5.0",
     "plotly.js-dist-min": "^2.6.2",
@@ -24,6 +25,7 @@
     "@babel/eslint-parser": "^7.13.14",
     "@quasar/app": "^3.0.0",
     "@types/emscripten": "^1.39.5",
+    "@types/file-saver": "^2.0.4",
     "@types/lodash": "^4.14.175",
     "@types/node": "^12.20.21",
     "@types/plotly.js-dist-min": "^2.3.0",

+ 5 - 5
guiapp/src/components/PlotSpectra.vue

@@ -14,7 +14,7 @@ import {
   computed,
   watch
 } from 'vue'
-import { toUnits } from 'components/utils'
+// import { toUnits } from 'components/utils'
 
 export default defineComponent({
   name: 'PlotSpectra',
@@ -46,13 +46,13 @@ export default defineComponent({
     function setPlotTitle() {
       let title=''
       if (sourceUnits.value.endsWith('Hz')) {
-        title = 'Frequency, ' + sourceUnits.value;
+        title = 'Frequency [' + sourceUnits.value + ']'
       } else if (sourceUnits.value.endsWith('eV')) {
-        title = 'Energy, ' + sourceUnits.value;
+        title = 'Energy [' + sourceUnits.value + ']'
       } else if (sourceUnits.value.endsWith('s')) {
-        title = 'Period, ' + sourceUnits.value;
+        title = 'Period [' + sourceUnits.value + ']'
       } else {
-        title = 'Wavelength, ' + sourceUnits.value;
+        title = 'Wavelength [' + sourceUnits.value + ']'
       }
       $store.commit('plotRuntime/updateXAxisTitle', title)
     }

+ 77 - 2
guiapp/src/components/RunSimulationSpectrum.vue

@@ -16,6 +16,10 @@
       <div class="row justify-xs-center justify-sm-start items-baseline">
 
         <div class="col-auto">
+          <q-btn
+              no-caps
+              @click="saveSpectrumSimulation"
+          >Save</q-btn>
         </div>
 
       </div>
@@ -29,8 +33,9 @@ import {
   computed, watch,
 } from 'vue'
 import { useStore } from 'src/store'
-import {range, rangeInt, toUnits} from 'components/utils'
+import { getModeName, range, rangeInt} from 'components/utils'
 import { cloneDeep } from 'lodash'
+import { saveAs } from 'file-saver'
 
 export default defineComponent({
   name: 'RunSimulationSpectrum',
@@ -155,7 +160,77 @@ export default defineComponent({
     })
 
     return { isRunning, isNmieLoaded,
-      runSpectrumSimulation
+      runSpectrumSimulation,
+      saveSpectrumSimulation(){
+        const fileHeader = '# # You can open and plot this file using Python\n' +
+            '# # (without manually removing this header, it will be skipped), see example below.\n' +
+            '# import numpy as np\n' +
+            '# from matplotlib import pyplot as plt\n' +
+            '# data = np.genfromtxt(\'scattnlay-spectra.txt\', skip_header=21, names=True, delimiter=\', \')\n' +
+            '# x = data[data.dtype.names[0]] # x-axis has units\n' +
+            '# # Possible labels for spectrum data: Qsca, Qabs, Qext,\n' +
+            '# # Qsca_E_dipole, etc. (see last comment before spectra data)\n' +
+            '# a = data[\'Qsca\']\n' +
+            '# b = data[\'Qsca_E_dipole\']\n' +
+            '# c = data[\'Qsca_H_dipole\']\n' +
+            '# \n' +
+            '# plt.figure()\n' +
+            '# plt.plot(x, a, label=\'Qsca\')\n' +
+            '# plt.plot(x, b, label=\'Qsca E dipole\')\n' +
+            '# plt.plot(x, c, label=\'Qsca H dipole\')\n' +
+            '# plt.legend()\n' +
+            '# plt.xlabel(data.dtype.names[0].replace(\'_\', \', \'))\n' +
+            '# plt.ylabel(\'Normalized cross-sections\')\n' +
+            '# plt.show()\n\n'
+        let xTitle = 'x'
+        if ( $store.state.plotRuntime.spectraPlot.layout.xaxis ) {
+          xTitle = String($store.state.plotRuntime.spectraPlot.layout.xaxis.title)
+        }
+
+        let columnNames = '# ' + xTitle + ', Qsca, Qabs, Qext, '
+        const mode_n = rangeInt($store.state.simulationSetup.current.numberOfModesToPlot, 1);
+        const mode_types = range(0, 1);
+        for (const n of mode_n) {
+          for (const mode_type of mode_types) {
+            const modeTypeName = mode_type == 0 ? 'E' : 'H'
+            columnNames += 'Qsca_' + modeTypeName + '_' +getModeName(n)+', '
+            columnNames += 'Qabs_' + modeTypeName + '_' +getModeName(n)+', '
+            columnNames += 'Qext_' + modeTypeName + '_' +getModeName(n)+', '
+          }
+        }
+        columnNames = columnNames.slice(0, -2)
+        columnNames += '\n'
+        let body = ''
+        const WLs = $store.state.plotRuntime.WLsInUnits
+        const Qsca = $store.state.plotRuntime.Qsca
+        const Qabs = $store.state.plotRuntime.Qabs
+        const Qext = $store.state.plotRuntime.Qext
+        const Qsca_n = $store.state.plotRuntime.Qsca_n
+        const Qabs_n = $store.state.plotRuntime.Qabs_n
+        const Qext_n = $store.state.plotRuntime.Qext_n
+        for (let i = 0; i < WLs.length; ++i) {
+          let row = WLs[i].toString() + ', '
+              + Qsca[i].toString() + ', '
+              + Qabs[i].toString() + ', '
+              + Qext[i].toString() + ', '
+          for (const n of mode_n) {
+            for (const mode_type of mode_types) {
+              row += Qsca_n[mode_type][n - 1][i].toString() + ', '
+              row += Qabs_n[mode_type][n - 1][i].toString() + ', '
+              row += Qext_n[mode_type][n - 1][i].toString() + ', '
+            }
+          }
+          row = row.slice(0, -2)
+          row += '\n'
+          body += row
+        }
+
+        const scattnlaySpectra = new Blob([fileHeader+columnNames+body],
+            {type: 'text/plain;charset=utf-8',
+              endings: 'native'}  //TODO test if newline is correctly written in Windows, MacOS
+        )
+        saveAs(scattnlaySpectra, 'scattnlay-spectra.txt');
+      }
     }
   },
 })

+ 3 - 2
guiapp/src/store/plot-runtime/mutations.ts

@@ -17,8 +17,9 @@ const mutation: MutationTree<prsi> = {
   },
 
   setWLsInUnits (state:prsi, sourceUnits:string) {
-    state.WLsInUnits.length = 0
-    for (const WL of state.WLs) state.WLsInUnits.push(toUnits(WL, sourceUnits))
+    const converted:number[] = []
+    for (const WL of state.WLs) converted.push(toUnits(WL, sourceUnits))
+    state.WLsInUnits = converted //assign it once to avoid multiple reactivity updates of the spectra plot
   },
 
   setQscaPlotToggle (state: prsi, val: boolean) {state.isPlotQsca = val},