Skip to content

Commit

Permalink
feat: add chemspectra with ref peaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Lan Le committed Dec 1, 2023
1 parent d503a4c commit 83eb4de
Show file tree
Hide file tree
Showing 10 changed files with 435 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .service-dependencies
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#syntax=v1
CONVERTER=ComPlat/[email protected]
KETCHER=ptrxyz/chemotion-ketchersvc@main
SPECTRA=ComPlat/chem-spectra-app@0.14.0
SPECTRA=ComPlat/chem-spectra-app@0.15.0
NMRIUMWRAPPER=NFDI4Chem/[email protected]
1 change: 1 addition & 0 deletions app/api/chemotion/attachment_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ def remove_duplicated(att)
optional :cyclicvolta, type: String
optional :curveIdx, type: Integer
optional :simulatenmr, type: Boolean
optional :axesUnits, type: String
end
post 'save_spectrum' do
jcamp_att = @attachment.generate_spectrum(
Expand Down
58 changes: 58 additions & 0 deletions app/api/chemotion/chem_spectra_api.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

# Belong to Chemotion module

# rubocop:disable Metrics/ClassLength
module Chemotion
# API for ChemSpectra manipulation
class ChemSpectraAPI < Grape::API
Expand Down Expand Up @@ -145,6 +147,60 @@ def raw_file(att)
post 'refresh' do
convert_for_refresh(params)
end

desc 'Combine spectra'
params do
requires :spectra_ids, type: [Integer]
requires :front_spectra_idx, type: Integer # index of front spectra
end
post 'combine_spectra' do
pm = to_rails_snake_case(params)

list_file = []
list_file_names = []
container_id = -1
combined_image_filename = ''
Attachment.where(id: pm[:spectra_ids]).each do |att|
container = att.container
combined_image_filename = "#{container.name}.new_combined.png"
container_id = att.attachable_id
list_file_names.push(att.filename)
list_file.push(att.abs_path)
end

_, image = Chemotion::Jcamp::CombineImg.combine(
list_file, pm[:front_spectra_idx], list_file_names
)

content_type('application/json')
unless image.nil?
att = Attachment.find_by(filename: combined_image_filename, attachable_id: container_id)
if att.nil?
att = Attachment.new(
bucket: container_id,
filename: combined_image_filename,
key: SecureRandom.uuid,
created_by: current_user.id,
created_for: current_user.id,
content_type: 'image/png',
file_path: image.path,
attachable_type: 'Container',
attachable_id: container_id,
storage: Rails.configuration.storage.primary_store,
)
att.save!
else
att.update!(
storage: Rails.configuration.storage.primary_store,
file_path: image.path,
attachable_type: 'Container',
attachable_id: container_id,
)
end
end

{ status: true }
end
end

resource :predict do
Expand Down Expand Up @@ -208,3 +264,5 @@ def raw_file(att)
end
end
end

# rubocop:enable Metrics/ClassLength
23 changes: 15 additions & 8 deletions app/packs/src/apps/mydb/elements/details/ViewSpectra.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ class ViewSpectra extends React.Component {

writeCommon({
peaks, shift, scan, thres, analysis, layout, isAscend, decimal, body,
keepPred, isIntensity, multiplicity, integration, cyclicvoltaSt, curveSt, waveLength
keepPred, isIntensity, multiplicity, integration, cyclicvoltaSt, curveSt,
waveLength, axesUnitsSt,
}, isMpy = false) {
const { sample, handleSampleChanged } = this.props;
const si = this.getSpcInfo();
Expand Down Expand Up @@ -386,7 +387,7 @@ class ViewSpectra extends React.Component {

const cb = () => (
this.saveOp({
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, cyclicvoltaSt, curveSt, waveLength
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, cyclicvoltaSt, curveSt, waveLength, axesUnitsSt,
})
);
handleSampleChanged(sample, cb);
Expand All @@ -403,7 +404,7 @@ class ViewSpectra extends React.Component {
}

saveOp({
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, simulatenmr = false
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, simulatenmr = false, layout, axesUnitsSt,
}) {
const { handleSubmit } = this.props;
const { curveIdx } = curveSt;
Expand All @@ -414,14 +415,17 @@ class ViewSpectra extends React.Component {
const predict = JSON.stringify(rmRefreshed(analysis));
const waveLengthStr = JSON.stringify(waveLength);
const cyclicvolta = JSON.stringify(cyclicvoltaSt);
const axesUnitsStr = JSON.stringify(axesUnitsSt);

const { shifts } = shift;
const selectedShift = shifts[curveIdx];
const { integrations } = integration;
const selectedIntegration = integrations[curveIdx];
const { multiplicities } = multiplicity;
const selectedMutiplicity = multiplicities[curveIdx];


const isSaveCombined = FN.isCyclicVoltaLayout(layout);
const { spcInfos } = this.state;
LoadingActions.start.defer();
SpectraActions.SaveToFile.defer(
si,
Expand All @@ -438,14 +442,17 @@ class ViewSpectra extends React.Component {
cyclicvolta,
curveIdx,
simulatenmr,
spcInfos,
isSaveCombined,
axesUnitsStr,
);
}

refreshOp({
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt
peaks, shift, scan, thres, analysis, keepPred, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, axesUnitsSt,
}) {
this.saveOp({
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, simulatenmr: true
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, simulatenmr: true, axesUnitsSt
});
}

Expand All @@ -471,10 +478,10 @@ class ViewSpectra extends React.Component {
}

saveCloseOp({
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, layout, axesUnitsSt,
}) {
this.saveOp({
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt
peaks, shift, scan, thres, analysis, integration, multiplicity, waveLength, cyclicvoltaSt, curveSt, layout, axesUnitsSt,
});
this.closeOp();
}
Expand Down
54 changes: 52 additions & 2 deletions app/packs/src/fetchers/AttachmentFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,10 @@ export default class AttachmentFetcher {
waveLengthStr,
cyclicvolta,
curveIdx,
simulatenmr
simulatenmr,
previousSpcInfos,
isSaveCombined,
axesUnitsStr
) {
const params = {
attachmentId: attId,
Expand All @@ -529,6 +532,7 @@ export default class AttachmentFetcher {
cyclicvolta: cyclicvolta,
curveIdx: curveIdx,
simulatenmr: simulatenmr,
axesUnits: axesUnitsStr,
};

const promise = fetch('/api/v1/attachments/save_spectrum/', {
Expand All @@ -541,7 +545,23 @@ export default class AttachmentFetcher {
body: JSON.stringify(decamelizeKeys(params)),
})
.then(response => response.json())
.then(json => json)
.then((json) => {
if (!isSaveCombined) {
return json;
}
const oldSpcInfos = [...previousSpcInfos].filter((spc) => {
return spc.idx !== attId;
});
let jcampIds = oldSpcInfos.map((spc) => (spc.idx));
const fetchedFilesIdxs = json.files.map((file) => (file.id));
jcampIds = [...jcampIds, ...fetchedFilesIdxs];

return AttachmentFetcher.combineSpectra(jcampIds, curveIdx).then((res) => {
return json;
}).catch((errMsg) => {
console.log(errMsg); // eslint-disable-line
});
})
.catch(errorMessage => {
console.log(errorMessage);
});
Expand Down Expand Up @@ -640,4 +660,34 @@ export default class AttachmentFetcher {

return promise;
}

static combineSpectra(jcampIds, curveIdx) {
const promise = fetch(
'/api/v1/chemspectra/file/combine_spectra',
{
credentials: 'same-origin',
method: 'POST',
headers:
{
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
spectra_ids: jcampIds,
front_spectra_idx: curveIdx,
}),
},
)
.then((response) => {
return response.json();
})
.then((json) => {
return json;
})
.catch((errorMessage) => {
console.log(errorMessage);
});

return promise;
}
}
4 changes: 2 additions & 2 deletions app/packs/src/stores/alt/actions/SpectraActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class SpectraActions {
};
}

SaveToFile(spcInfo, peaksStr, shift, scan, thres, integration, multiplicity, predict, cb, keepPred = false, waveLengthStr, cyclicvolta, curveIdx = 0, simulatenmr = false) {
SaveToFile(spcInfo, peaksStr, shift, scan, thres, integration, multiplicity, predict, cb, keepPred = false, waveLengthStr, cyclicvolta, curveIdx = 0, simulatenmr = false, previousSpcInfos, isSaveCombined = false, axesUnitsStr) {
return (dispatch) => {
AttachmentFetcher.saveSpectrum(spcInfo.idx, peaksStr, shift, scan, thres, integration, multiplicity, predict, keepPred, waveLengthStr, cyclicvolta, curveIdx, simulatenmr)
AttachmentFetcher.saveSpectrum(spcInfo.idx, peaksStr, shift, scan, thres, integration, multiplicity, predict, keepPred, waveLengthStr, cyclicvolta, curveIdx, simulatenmr, previousSpcInfos, isSaveCombined, axesUnitsStr)
.then((fetchedFiles) => {
dispatch({ fetchedFiles, spcInfo });
cb();
Expand Down
42 changes: 42 additions & 0 deletions lib/chemotion/jcamp.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

# rubocop:disable Metrics/BlockLength

require 'net/http'

# Chemotion module
Expand Down Expand Up @@ -114,6 +116,7 @@ def self.build_body(
cyclic_volta: params[:cyclicvolta],
jcamp_idx: params[:curve_idx],
simulatenmr: params[:simulatenmr],
axes_units: params[:axes_units],
}
end

Expand Down Expand Up @@ -199,6 +202,43 @@ def self.spectrum_img_gene(path)
Util.extract_zip(rsp_io)
end
end

# Combine multiple jcamps in one image
module CombineImg
include HTTParty

def self.stub_request(files, curve_idx, list_file_names)
response = nil
url = Rails.configuration.spectra.chemspectra.url
api_endpoint = "#{url}/combine_images"

files_to_read = files.map { |fname| File.open(fname) }
begin
response = HTTParty.post(
api_endpoint,
body: {
multipart: true,
files: files_to_read,
jcamp_idx: curve_idx,
list_file_names: list_file_names,
},
)
ensure
files_to_read.each(&:close)
end
response
end

def self.combine(files, curve_idx, list_file_names)
rsp = stub_request(files, curve_idx, list_file_names)
if rsp.code == 200
rsp_io = StringIO.new(rsp.body.to_s)
Util.extract_zip(rsp_io)
else # rubocop:disable Style/EmptyElse
nil
end
end
end
end
end

Expand Down Expand Up @@ -403,3 +443,5 @@ def self.jcamp_from_nmrium(path)
end
end
end

# rubocop:enable Metrics/BlockLength
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@babel/preset-react": "7.10.4",
"@citation-js/plugin-isbn": "0.3.0",
"@complat/chem-spectra-client": "1.0.0-rc20.patch-1",
"@complat/react-spectra-editor": "1.0.0-rc20.patch-1",
"@complat/react-spectra-editor": "1.0.0-beta.1",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@novnc/novnc": "^1.2.0",
Expand Down
Loading

0 comments on commit 83eb4de

Please sign in to comment.