From a354154d16dab637f493b41a64ec6fae9f1dded3 Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Thu, 16 Jan 2025 14:17:35 +0000 Subject: [PATCH 1/9] New DataBlockUI displaying every Datablock: Add Comment and XRD block --- webapp/src/components/DataBlockUI.vue | 112 ++++++++++++++++++++++++++ webapp/src/resources.js | 60 +++++++++----- 2 files changed, 152 insertions(+), 20 deletions(-) create mode 100644 webapp/src/components/DataBlockUI.vue diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue new file mode 100644 index 000000000..54f2b1e0b --- /dev/null +++ b/webapp/src/components/DataBlockUI.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/webapp/src/resources.js b/webapp/src/resources.js index bb452147a..1770a10d0 100644 --- a/webapp/src/resources.js +++ b/webapp/src/resources.js @@ -1,14 +1,15 @@ // Resources for the application -import DataBlockBase from "@/components/datablocks/DataBlockBase"; -import BokehBlock from "@/components/datablocks/BokehBlock"; -import MediaBlock from "@/components/datablocks/MediaBlock"; -import XRDBlock from "@/components/datablocks/XRDBlock"; -import ChatBlock from "@/components/datablocks/ChatBlock"; -import RamanBlock from "@/components/datablocks/RamanBlock"; -import CycleBlock from "@/components/datablocks/CycleBlock"; -import NMRBlock from "@/components/datablocks/NMRBlock"; -import EISBlock from "@/components/datablocks/EISBlock"; -import MassSpecBlock from "@/components/datablocks/MassSpecBlock"; +// import DataBlockBase from "@/components/datablocks/DataBlockBase"; +// import BokehBlock from "@/components/datablocks/BokehBlock"; +// import MediaBlock from "@/components/datablocks/MediaBlock"; +// import XRDBlock from "@/components/datablocks/XRDBlock"; +// import ChatBlock from "@/components/datablocks/ChatBlock"; +// import RamanBlock from "@/components/datablocks/RamanBlock"; +// import CycleBlock from "@/components/datablocks/CycleBlock"; +// import NMRBlock from "@/components/datablocks/NMRBlock"; +// import EISBlock from "@/components/datablocks/EISBlock"; +// import MassSpecBlock from "@/components/datablocks/MassSpecBlock"; +import DataBlockUI from "@/components/DataBlockUI"; import SampleInformation from "@/components/SampleInformation"; import StartingMaterialInformation from "@/components/StartingMaterialInformation"; @@ -59,16 +60,35 @@ export const UPPY_MAX_NUMBER_OF_FILES = export const debounceTime = 250; // time after user stops typing before request is sent export const blockTypes = { - comment: { description: "Comment", component: DataBlockBase, name: "Comment" }, - media: { description: "Media", component: MediaBlock, name: "Media" }, - tabular: { description: "Tabular Data", component: BokehBlock, name: "Tabular data" }, - xrd: { description: "Powder XRD", component: XRDBlock, name: "Powder XRD" }, - raman: { description: "Raman", component: RamanBlock, name: "Raman" }, - cycle: { description: "Electrochemistry", component: CycleBlock, name: "Electrochemistry" }, - eis: { description: "Electrochemical Impedance Spectroscopy", component: EISBlock, name: "EIS" }, - nmr: { description: "Nuclear Magnetic Resonance Spectroscopy", component: NMRBlock, name: "NMR" }, - ms: { description: "Mass Spectrometry", component: MassSpecBlock, name: "Mass Spectrometry" }, - chat: { description: "Virtual assistant", component: ChatBlock, name: "Virtual Assistant" }, + comment: { description: "Comment", component: DataBlockUI, name: "Comment" }, + media: { description: "Media", component: DataBlockUI, name: "Media" }, + tabular: { description: "Tabular Data", component: DataBlockUI, name: "Tabular data" }, + xrd: { + description: "Powder XRD", + component: DataBlockUI, + properties: { + wavelength: { label: "Wavelength (Å):" }, + }, + name: "Powder XRD", + }, + raman: { description: "Raman", component: DataBlockUI, name: "Raman" }, + cycle: { description: "Electrochemistry", component: DataBlockUI, name: "Electrochemistry" }, + eis: { + description: "Electrochemical Impedance Spectroscopy", + component: DataBlockUI, + name: "EIS", + }, + nmr: { + description: "Nuclear Magnetic Resonance Spectroscopy", + component: DataBlockUI, + name: "NMR", + }, + ms: { description: "Mass Spectrometry", component: DataBlockUI, name: "Mass Spectrometry" }, + chat: { + description: "Virtual assistant", + component: DataBlockUI, + name: "Virtual Assistant", + }, }; export const itemTypes = { From febae81cf173558ba18843bc35c1bdfdfaa501ef Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 10:15:30 +0000 Subject: [PATCH 2/9] DataBlockUI now support Media block --- webapp/src/components/DataBlockUI.vue | 102 ++++++++++++++++++-------- 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue index 54f2b1e0b..4310512fe 100644 --- a/webapp/src/components/DataBlockUI.vue +++ b/webapp/src/components/DataBlockUI.vue @@ -8,37 +8,46 @@ :extensions="blockInfo.attributes.accepted_file_extensions" update-block-on-change /> -
-
-
- - -
- {{ wavelengthParseError }} +
+
+
+
+ + +
+ {{ wavelengthParseError }} +
-
-
-
- +
+
+ +
+ +
@@ -48,7 +57,7 @@ import DataBlockBase from "@/components/datablocks/DataBlockBase"; import FileSelectDropdown from "@/components/FileSelectDropdown"; import BokehPlot from "@/components/BokehPlot"; -import { blockTypes } from "@/resources.js"; +import { blockTypes, API_URL } from "@/resources.js"; import { createComputedSetterForBlockField } from "@/field_utils.js"; import { updateBlockFromServer } from "@/server_fetch_utils.js"; @@ -74,19 +83,41 @@ export default { }; }, computed: { - block() { + all_files() { + return this.$store.state.all_item_data[this.item_id].files; + }, + block_data() { return this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id]; }, blockInfo() { - return this.$store.state.blocksInfos[this.block.blocktype]; + return this.$store.state.blocksInfos[this.block_data.blocktype]; }, properties() { - return blockTypes[this.block.blocktype].properties; + return blockTypes[this.block_data.blocktype].properties; }, bokehPlotData() { return this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id] .bokeh_plot_data; }, + haveWavelengthProperties() { + return this.properties && "wavelength" in this.properties; + }, + media_url() { + // If the API has already base64 encoded the image, then use it, + let b64_encoding = this.block_data["b64_encoded_image"] || null; + if ((b64_encoding != null && b64_encoding[this.file_id]) || null != null) { + return `data:image/png;base64,${b64_encoding[this.file_id]}`; + } + return `${API_URL}/files/${this.file_id}/${this.lookup_file_field("name", this.file_id)}`; + }, + isPhoto() { + return [".png", ".jpeg", ".jpg", ".tif", ".tiff"].includes( + this.lookup_file_field("extension", this.file_id), + ); + }, + isVideo() { + return [".mp4", ".mov", ".webm"].includes(this.lookup_file_field("extension", this.file_id)); + }, file_id: createComputedSetterForBlockField("file_id"), wavelength: createComputedSetterForBlockField("wavelength"), }, @@ -105,8 +136,17 @@ export default { this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id], ); }, + lookup_file_field(field, file_id) { + return this.all_files.find((file) => file.immutable_id === file_id)?.[field]; + }, }, }; - + From b2a91a2800ec9c6cfd39e464a2d1096e043fdaa3 Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 10:34:19 +0000 Subject: [PATCH 3/9] DataBlockUI now support Tabular block --- webapp/src/components/DataBlockUI.vue | 6 +++++- webapp/src/resources.js | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue index 4310512fe..18309c384 100644 --- a/webapp/src/components/DataBlockUI.vue +++ b/webapp/src/components/DataBlockUI.vue @@ -34,7 +34,8 @@
- +
+
@@ -99,6 +100,9 @@ export default { return this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id] .bokeh_plot_data; }, + haveBokehPlot() { + return this.properties && "bokehPlot" in this.properties; + }, haveWavelengthProperties() { return this.properties && "wavelength" in this.properties; }, diff --git a/webapp/src/resources.js b/webapp/src/resources.js index 1770a10d0..8f0b59c52 100644 --- a/webapp/src/resources.js +++ b/webapp/src/resources.js @@ -62,11 +62,17 @@ export const debounceTime = 250; // time after user stops typing before request export const blockTypes = { comment: { description: "Comment", component: DataBlockUI, name: "Comment" }, media: { description: "Media", component: DataBlockUI, name: "Media" }, - tabular: { description: "Tabular Data", component: DataBlockUI, name: "Tabular data" }, + tabular: { + description: "Tabular Data", + component: DataBlockUI, + properties: { bokehPlot: true }, + name: "Tabular data", + }, xrd: { description: "Powder XRD", component: DataBlockUI, properties: { + bokehPlot: true, wavelength: { label: "Wavelength (Å):" }, }, name: "Powder XRD", From 346792452c0e33c6a0d13369ae4f76311f52dc1c Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 10:51:12 +0000 Subject: [PATCH 4/9] DataBlockUI now support Raman block --- webapp/src/components/DataBlockUI.vue | 15 ++++++++++----- webapp/src/resources.js | 7 ++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue index 18309c384..b7166ba94 100644 --- a/webapp/src/components/DataBlockUI.vue +++ b/webapp/src/components/DataBlockUI.vue @@ -8,7 +8,7 @@ :extensions="blockInfo.attributes.accepted_file_extensions" update-block-on-change /> -
+
@@ -91,14 +91,19 @@ export default { return this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id]; }, blockInfo() { - return this.$store.state.blocksInfos[this.block_data.blocktype]; + return this.block_data?.blocktype + ? this.$store.state.blocksInfos[this.block_data.blocktype] + : null; }, properties() { - return blockTypes[this.block_data.blocktype].properties; + return this.block_data?.blocktype ? blockTypes[this.block_data.blocktype]?.properties : null; }, bokehPlotData() { - return this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id] - .bokeh_plot_data; + if (!this.file_id) return null; + return ( + this.$store.state.all_item_data[this.item_id]?.["blocks_obj"]?.[this.block_id] + ?.bokeh_plot_data || null + ); }, haveBokehPlot() { return this.properties && "bokehPlot" in this.properties; diff --git a/webapp/src/resources.js b/webapp/src/resources.js index 8f0b59c52..ad9ccd72c 100644 --- a/webapp/src/resources.js +++ b/webapp/src/resources.js @@ -77,7 +77,12 @@ export const blockTypes = { }, name: "Powder XRD", }, - raman: { description: "Raman", component: DataBlockUI, name: "Raman" }, + raman: { + description: "Raman", + component: DataBlockUI, + properties: { bokehPlot: true }, + name: "Raman", + }, cycle: { description: "Electrochemistry", component: DataBlockUI, name: "Electrochemistry" }, eis: { description: "Electrochemical Impedance Spectroscopy", From 25d354c7f4f3e36ddf7318db855455c6afd68691 Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 11:20:33 +0000 Subject: [PATCH 5/9] DataBlockUI now support Cycle block --- webapp/src/components/DataBlockUI.vue | 192 +++++++++++++++++++++++++- webapp/src/resources.js | 10 +- 2 files changed, 200 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue index b7166ba94..7740a0e85 100644 --- a/webapp/src/components/DataBlockUI.vue +++ b/webapp/src/components/DataBlockUI.vue @@ -35,6 +35,137 @@
+
+
+
+ + + Showing cycles: {{ parsedCycles }} +
+ +
+ {{ cycle_num_error }} +
+
+ +
+
+ +
+
+ Cycle Summary +
+
+ dQ/dV +
+
+ dV/dQ +
+
+
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

+ Smoothing parameter that determines how close the spline fits to the real data. Larger + values result in a smoother fit with decreased detail. +

+
+
+

Window size for the Savitzky-Golay filter to apply to the derivatives.

+
+
@@ -80,7 +211,15 @@ export default { }, data() { return { + // Wavelength: XRD wavelengthParseError: "", + // Cycle: Cycle + cycle_num_error: "", + cyclesString: "", + showDescription1: false, + showDescription2: false, + bokehPlotLimitedWidth: true, + isReplotButtonDisplayed: false, }; }, computed: { @@ -127,8 +266,25 @@ export default { isVideo() { return [".mp4", ".mov", ".webm"].includes(this.lookup_file_field("extension", this.file_id)); }, + haveCycleProperties() { + return this.properties && "cycle" in this.properties; + }, + numberOfCycles() { + return ( + this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id] + .number_of_cycles || null + ); + }, + parsedCycles() { + return this.all_cycles ? this.all_cycles : "all"; + }, file_id: createComputedSetterForBlockField("file_id"), wavelength: createComputedSetterForBlockField("wavelength"), + all_cycles: createComputedSetterForBlockField("cyclenumber"), + s_spline: createComputedSetterForBlockField("s_spline"), + win_size_1: createComputedSetterForBlockField("win_size_1"), + derivative_mode: createComputedSetterForBlockField("derivative_mode"), + characteristic_mass: createComputedSetterForBlockField("characteristic_mass"), }, methods: { parseWavelength() { @@ -143,7 +299,12 @@ export default { this.item_id, this.block_id, this.$store.state.all_item_data[this.item_id]["blocks_obj"][this.block_id], - ); + ).then(() => { + if (this.haveCycleProperties) { + this.bokehPlotLimitedWidth = this.derivative_mode != "dQ/dV"; + this.isReplotButtonDisplayed = false; + } + }); }, lookup_file_field(field, file_id) { return this.all_files.find((file) => file.immutable_id === file_id)?.[field]; @@ -158,4 +319,33 @@ video { display: block; max-height: 600px; } + +#list-of-cycles { + color: grey; +} + +#cycles-input { + max-width: 14em; +} + +.blurry { + filter: blur(5px); +} + +.limited-width { + max-width: 650px; +} + +.slider { + margin-top: 2rem; +} + +.btn-default:hover { + background-color: #eee; +} + +.slider span { + border-bottom: 2px dotted #0c5460; + text-decoration: none; +} diff --git a/webapp/src/resources.js b/webapp/src/resources.js index ad9ccd72c..1274f0d99 100644 --- a/webapp/src/resources.js +++ b/webapp/src/resources.js @@ -83,7 +83,15 @@ export const blockTypes = { properties: { bokehPlot: true }, name: "Raman", }, - cycle: { description: "Electrochemistry", component: DataBlockUI, name: "Electrochemistry" }, + cycle: { + description: "Electrochemistry", + component: DataBlockUI, + properties: { + bokehPlot: true, + cycle: { label: "Cycles to plot:" }, + }, + name: "Electrochemistry", + }, eis: { description: "Electrochemical Impedance Spectroscopy", component: DataBlockUI, From 0aaf03efdaa822a09eeca03c574536a93b7638df Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 14:06:43 +0000 Subject: [PATCH 6/9] DataBlockUI now support NMR block --- webapp/src/components/DataBlockUI.vue | 115 +++++++++++++++++++++++++- webapp/src/resources.js | 5 ++ 2 files changed, 118 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue index 7740a0e85..ff3e51581 100644 --- a/webapp/src/components/DataBlockUI.vue +++ b/webapp/src/components/DataBlockUI.vue @@ -166,11 +166,101 @@

Window size for the Savitzky-Golay filter to apply to the derivatives.

+
+
+
+ + +
+
+ + +
+
+ {{ block_data.topspin_title }} +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
nucleus
pulse program{{ block_data.pulse_program_name }}
Data shape + {{ block_data.processed_data_shape }} (d = + {{ block_data.processed_data_shape.length }}) +
probe{{ block_data.probe_name }} s
# of scans{{ block_data.nscans }}
recycle delay{{ block_data.recycle_delay }} s
carrier frequency{{ block_data.carrier_frequency_MHz }} MHz
carrier offset + {{ + (block_data.carrier_offset_Hz / block_data.carrier_frequency_MHz).toFixed(1) + }} + ppm +
cnst31{{ block_data.CNST31 }}
+
diff --git a/webapp/src/resources.js b/webapp/src/resources.js index 1274f0d99..999ee30fe 100644 --- a/webapp/src/resources.js +++ b/webapp/src/resources.js @@ -95,11 +95,16 @@ export const blockTypes = { eis: { description: "Electrochemical Impedance Spectroscopy", component: DataBlockUI, + properties: { bokehPlot: true }, name: "EIS", }, nmr: { description: "Nuclear Magnetic Resonance Spectroscopy", component: DataBlockUI, + properties: { + bokehPlot: true, + processNumber: { label: "Process number:" }, + }, name: "NMR", }, ms: { description: "Mass Spectrometry", component: DataBlockUI, name: "Mass Spectrometry" }, From 440cd9c30d545a5f3a7138e524ea96086cce09f3 Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 14:15:53 +0000 Subject: [PATCH 7/9] DataBlockUI now support MS block --- webapp/src/resources.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/webapp/src/resources.js b/webapp/src/resources.js index 999ee30fe..c993f715f 100644 --- a/webapp/src/resources.js +++ b/webapp/src/resources.js @@ -107,7 +107,12 @@ export const blockTypes = { }, name: "NMR", }, - ms: { description: "Mass Spectrometry", component: DataBlockUI, name: "Mass Spectrometry" }, + ms: { + description: "Mass Spectrometry", + component: DataBlockUI, + properties: { bokehPlot: true }, + name: "Mass Spectrometry", + }, chat: { description: "Virtual assistant", component: DataBlockUI, From 36c5f9cd2782ab6f6060c97bad9a8a1897b97f55 Mon Sep 17 00:00:00 2001 From: Benjamin CHARMES Date: Fri, 17 Jan 2025 16:38:07 +0000 Subject: [PATCH 8/9] DataBlockUI now support Whinchat block --- webapp/src/components/DataBlockUI.vue | 226 +++++++++++++++++++++++++- webapp/src/resources.js | 1 + 2 files changed, 218 insertions(+), 9 deletions(-) diff --git a/webapp/src/components/DataBlockUI.vue b/webapp/src/components/DataBlockUI.vue index ff3e51581..377e3bba1 100644 --- a/webapp/src/components/DataBlockUI.vue +++ b/webapp/src/components/DataBlockUI.vue @@ -1,7 +1,7 @@