Commit 3a93056a authored by iquasere's avatar iquasere
Browse files

Fixed set config values

to default and empty values
parent e4abf563
......@@ -6544,30 +6544,30 @@
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"filename-reserved-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz",
"integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
"integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
"dev": true
},
"filenamify": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz",
"integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
"integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
"dev": true,
"requires": {
"filename-reserved-regex": "^1.0.0",
"strip-outer": "^1.0.0",
"filename-reserved-regex": "^2.0.0",
"strip-outer": "^1.0.1",
"trim-repeated": "^1.0.0"
}
},
"filenamify-url": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz",
"integrity": "sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-2.1.2.tgz",
"integrity": "sha512-3rMbAr7vDNMOGsj1aMniQFl749QjgM+lMJ/77ZRSPTIgxvolZwoQbn8dXLs7xfd+hAdli+oTnSWZNkJJLWQFEQ==",
"dev": true,
"requires": {
"filenamify": "^1.0.0",
"humanize-url": "^1.0.0"
"filenamify": "^4.3.0",
"humanize-url": "^2.1.1"
}
},
"filesize": {
......@@ -7106,15 +7106,15 @@
}
},
"gh-pages": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.1.0.tgz",
"integrity": "sha512-3b1rly9kuf3/dXsT8+ZxP0UhNLOo1CItj+3e31yUVcaph/yDsJ9RzD7JOw5o5zpBTJVQLlJAASNkUfepi9fe2w==",
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.1.tgz",
"integrity": "sha512-/JLALwM9vTSohmaO9RZSWS+oCcVkV4pMyUwdQPZuxeJN5mVwz2kRbT6RigqDoqM8Rber2sv+WIMLP/9ZPfc7oA==",
"dev": true,
"requires": {
"async": "^2.6.1",
"commander": "^2.18.0",
"email-addresses": "^3.0.1",
"filenamify-url": "^1.0.0",
"filenamify-url": "^2.1.1",
"find-cache-dir": "^3.3.1",
"fs-extra": "^8.1.0",
"globby": "^6.1.0"
......@@ -7955,13 +7955,20 @@
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="
},
"humanize-url": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz",
"integrity": "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-2.1.1.tgz",
"integrity": "sha512-V4nxsPGNE7mPjr1qDp471YfW8nhBiTRWrG/4usZlpvFU8I7gsV7Jvrrzv/snbLm5dWO3dr1ennu2YqnhTWFmYA==",
"dev": true,
"requires": {
"normalize-url": "^1.0.0",
"strip-url-auth": "^1.0.0"
"normalize-url": "^4.5.1"
},
"dependencies": {
"normalize-url": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
"integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
"dev": true
}
}
},
"hyphenate-style-name": {
......@@ -15117,12 +15124,6 @@
"escape-string-regexp": "^1.0.2"
}
},
"strip-url-auth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz",
"integrity": "sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=",
"dev": true
},
"style-loader": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz",
......
......@@ -66,7 +66,8 @@
]
},
"devDependencies": {
"gh-pages": "^3.1.0",
"@testing-library/react": "^11.2.7",
"gh-pages": "^3.2.1",
"html-loader": "^2.1.2"
}
}
import React, { useState } from 'react'
import YAML from 'yaml'
import {
Card,
CardContent,
CardActions,
Button,
Typography,
Divider
} from '@material-ui/core'
import LabelledTextField from "./components/LabelledTextField"
import LabelledNumberField from "./components/LabelledNumberField"
import LabelledCheckbox from "./components/LabelledCheckbox"
import LabelledSelect from "./components/LabelledSelect"
import ExperimentsTable from "./components/ExperimentsTable"
import { defaultValues } from './utils/defaultValues'
import { emptyValues } from './utils/emptyValues'
import { keggMaps } from './utils/keggMaps'
import { uniprotColumns } from "./utils/uniprotColumns"
import { uniprotDatabases } from "./utils/uniprotDatabases"
import download from './utils/download'
import {
assemblerOptions,
errorModelOptions,
markersetOptions,
normalizationMethodOptions,
keggcharterTaxaLevelOptions
} from './utils/options'
import './App.css'
import KeggMapsAccordion from './components/KeggMapsAccordion'
const Main = () => {
const [values, setValues] = useState(defaultValues)
const [experiments, setExperiments] = useState([])
const handleChange = (field, value) => {
const newValue = { ...values, [field]: value }
setValues(newValue)
}
const camelToSnakeCase = str => str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
const downloadJson = (ev) => {
ev.preventDefault()
console.log(JSON.stringify(values, null, 2).toString())
const snake_case_values = {}
Object.keys(values).map((key) => snake_case_values[camelToSnakeCase(key)] = values[key])
download(JSON.stringify(snake_case_values, null, 2), 'config.json', 'json')
}
const downloadYaml = (ev) => {
ev.preventDefault()
console.log(YAML.stringify(values))
const snake_case_values = {}
Object.keys(values).map((key) => snake_case_values[camelToSnakeCase(key)] = values[key])
download(YAML.stringify(snake_case_values, null, 2), 'config.yaml', 'yaml')
}
return (
<main className='main'>
<form className='form' >
<Card >
<CardContent>
<Typography variant='body1'>
To run MOSCA, you need both a configuration and an experiments files. MOSGUITO is used to obtained configuration files, and you can <a href='https://docs.google.com/spreadsheets/d/12BppOf32QPRl6Ey39ACWoOXPVWtTrGIUN2u-_BpwSvo/edit#gid=0' ><span style={{ color: 'red' }}>access</span></a> an example of experiments file from MOSCA's repository.
</Typography>
<Divider style={{ margin: '1rem 0' }} />
<LabelledTextField
label='Output directory'
value={values.output}
onChange={(ev) => handleChange('output', ev.target.value)}
placeholder={defaultValues.output}
/>
<LabelledTextField
label='Resources directory'
value={values.resourcesDirectory}
onChange={(ev) => handleChange('resourcesDirectory', ev.target.value)}
placeholder={defaultValues.resourcesDirectory}
/>
<LabelledTextField
label='Experiments filename'
value={values.experiments}
onChange={(ev) => handleChange('experiments', ev.target.value)}
placeholder={defaultValues.experiments}
/>
<LabelledNumberField
label='Number of threads to use'
value={values.threads}
onChange={(ev) => handleChange('threads', ev.target.valueAsNumber)}
/>
<LabelledCheckbox
label='Perform assembly'
checked={values.doAssembly}
setChecked={(ev) => handleChange('doAssembly', ev.target.checked)}
/>
{
values.doAssembly ? (
<LabelledSelect
label='Choose assembler'
value={values.assembler}
onChange={(ev) => handleChange('assembler', ev.target.value)}
options={assemblerOptions}
/>
) : (
<LabelledSelect
label='Choose error model'
value={values.errorModel}
onChange={(ev) => handleChange('errorModel', ev.target.value)}
options={errorModelOptions}
/>
)
}
<LabelledSelect
label='Choose markerset'
value={values.markerset}
onChange={(ev) => handleChange('markerset', ev.target.value)}
options={markersetOptions}
/>
<LabelledTextField
label='DIAMOND database'
value={values.diamondDatabase}
onChange={(ev) => handleChange('diamondDatabase', ev.target.value)}
placeholder={defaultValues.diamondDatabase}
/>
<LabelledCheckbox
label='Download UniProt'
checked={values.downloadUniprot}
setChecked={(ev) => handleChange('downloadUniprot', ev.target.checked)}
/>
<LabelledNumberField
label='Number of identifications per protein'
value={values.diamondMaxTargetSeqs}
onChange={(ev) => handleChange('diamondMaxTargetSeqs', ev.target.valueAsNumber)}
/>
<UniprotColumnsAccordion
columns={uniprotColumns}
uniprotColumnsList={values.uniprotColumns}
onChange={(value) => handleChange('uniprotColumns', value)}
/>
<UniprotDatabasesAccordion
columns={uniprotDatabases}
uniprotDatabasesList={values.uniprotDatabases}
onChange={(value) => handleChange('uniprotDatabases', value)}
/>
<LabelledSelect
label='Choose normalization method'
value={values.normalizationMethod}
onChange={(ev) => handleChange('normalizationMethod', ev.target.value)}
options={normalizationMethodOptions}
/>
<LabelledSelect
label='Choose the taxonomic level to represent with KEGGCharter'
value={values.keggcharterTaxaLevel}
onChange={(ev) => handleChange('keggcharterTaxaLevel', ev.target.value)}
options={keggcharterTaxaLevelOptions}
/>
<LabelledNumberField
label='Number of taxa to represent with KEGGCharter'
value={values.keggcharterNumberOfTaxa}
onChange={(ev) => handleChange('keggcharterNumberOfTaxa', ev.target.valueAsNumber)}
/>
<KeggMapsAccordion
maps={keggMaps}
keggMapList={values.keggcharterMaps}
onChange={(value) => handleChange('keggcharterMaps', value)}
/>
<ExperimentsTable
experiments={experiments}
onChange={(value) => setExperiments(value)}
/>
</CardContent>
<CardActions
style={{
display: 'flex',
justifyContent: 'flex-end'
}}
>
<Button
onClick={() => handleChange("output", defaultValues["output"])}
variant='contained'
color='primary'
>
Set to default values
</Button>
<Button
onClick={() => handleChange("output", emptyValues["output"])}
variant='contained'
color='primary'
>
Clear values
</Button>
<Button
onClick={(ev) => downloadYaml(ev)}
variant='contained'
color='secondary'
>
Download YAML
</Button>
<Button
onClick={(ev) => downloadJson(ev)}
variant='contained'
color='secondary'
>
Download JSON
</Button>
</CardActions>
</Card>
</form>
</main>
)
}
const Header = () => {
return (
<header className='header'>
<Typography variant='h4'>
MOSGUITO
</Typography>
<Typography variant='h6'>
MOSca's GUI TO generate config files
</Typography>
</header>
)
}
function App() {
return (
<div className='App'>
<Header />
<Main />
</div>
)
}
export default App
import { render, screen } from '@testing-library/react';
import App from './App';
import {App} from './pages/_app';
import React from "react";
test('renders learn react link', () => {
render(<App />);
......
......@@ -21,10 +21,16 @@ export const App = () => {
const newValue = { ...configData, [field]: value }
setConfig(newValue)
}
console.log(configData)
const onConfigOverwrite = (newConfigData) => {
const newValue = newConfigData
setConfig(newValue)
}
return <Routes
configData={configData}
onConfigChange={onConfigChange}
onConfigOverwrite={onConfigOverwrite}
nExperimentsRows={nExperimentsRows}
setExperimentsRows={setExperimentsRows}
experiments={experiments}
......
......@@ -23,7 +23,7 @@ import EntryReports from "./entryReport";
import GeneralReports from "./GeneralReports";
import ProteinReports from "./ProteinReports";
const Routes = ({ configData, onConfigChange, experiments, setExperiments,
const Routes = ({ configData, onConfigChange, onConfigOverwrite, experiments, setExperiments,
nExperimentsRows, setExperimentsRows,
outputsFiles, setOutputsFiles }) => {
return (
......@@ -33,6 +33,7 @@ const Routes = ({ configData, onConfigChange, experiments, setExperiments,
<Config
configData={configData}
onConfigChange={onConfigChange}
onConfigOverwrite={onConfigOverwrite}
/>
</Route>
......@@ -96,7 +97,7 @@ const Routes = ({ configData, onConfigChange, experiments, setExperiments,
<LoadResults
outputsFiles={outputsFiles}
setOutputsFiles={setOutputsFiles}
onConfigChange ={onConfigChange}
onConfigOverwrite ={onConfigOverwrite}
setExperiments = {setExperiments}
setExperimentsRows = {setExperimentsRows}
/>
......
......@@ -27,7 +27,7 @@ import './../App.css'
import {DashboardLayout} from "../components/Layout";
import Accordion from "../components/Accordion";
const Main = ({ configData, onConfigChange }) => {
const Main = ({ configData, onConfigChange, onConfigOverwrite }) => {
const camelToSnakeCase = str => str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
......@@ -227,7 +227,7 @@ const Main = ({ configData, onConfigChange }) => {
>
<Button
onClick={() => Object.keys(configData).map((key) => onConfigChange(key, defaultValues[key]))}
onClick={() => onConfigOverwrite(defaultValues)}
variant='contained'
color='primary'
>
......@@ -235,7 +235,7 @@ const Main = ({ configData, onConfigChange }) => {
</Button>
<Button
onClick={() => Object.keys(configData).map((key) => onConfigChange(key, emptyValues[key]))}
onClick={() => onConfigOverwrite(emptyValues)}
variant='contained'
color='primary'
>
......@@ -278,7 +278,7 @@ const Header = () => {
)
}
function Config({ configData, onConfigChange }) {
function Config({ configData, onConfigChange, onConfigOverwrite }) {
return (
<DashboardLayout>
<div className='App'>
......@@ -286,6 +286,7 @@ function Config({ configData, onConfigChange }) {
<Main
configData={configData}
onConfigChange={onConfigChange}
onConfigOverwrite={onConfigOverwrite}
/>
</div>
</DashboardLayout>
......
......@@ -14,6 +14,7 @@ const treatName = (name) =>{
}
export let ResultsDisposition = false;
async function ObtainBlobArray(event){
const file = event.target.files[0];
const blobReader = new zip.BlobReader(file);
......@@ -70,7 +71,6 @@ async function ObtainBlobArray(event){
const fileUrl = URL.createObjectURL(config)
$.getJSON(fileUrl, function(json){
configFile = json
console.log(configFile)
})
}
if(entries[i].filename.includes('experiments')){
......@@ -103,9 +103,15 @@ async function ObtainBlobArray(event){
}
const Main = ({ outputsFiles, setOutputsFiles, onConfigChange, setExperiments, setExperimentsRows }) => {
const Main = ({ outputsFiles, setOutputsFiles, onConfigOverwrite, setExperiments, setExperimentsRows }) => {
const snakeToCamelCase = str => {
return str.replace(/([-_][a-z])/ig, ($1) => {
return $1.toUpperCase()
.replace('-', '')
.replace('_', '');
});
};
const handleUploadClick = () => {
ResultsDisposition = true
......@@ -113,9 +119,11 @@ const Main = ({ outputsFiles, setOutputsFiles, onConfigChange, setExperiments, s
const handleZipChange = async (event) => {
let Output = await ObtainBlobArray(event)
setOutputsFiles(Output[0])
for(const[key, value] of Object.entries(Output[1])){
onConfigChange(key, value)
}
console.log(Output[1])
Object.keys(Output[1]).map(
(key) => delete Object.assign(Output[1], {[snakeToCamelCase(key)]: Output[1][key]})[key])
console.log(Output[1])
onConfigOverwrite(Output[1])
const readCsv = (csvUrl)=>{
Papa.parse(csvUrl,{
......@@ -140,23 +148,19 @@ const Main = ({ outputsFiles, setOutputsFiles, onConfigChange, setExperiments, s
component="label"
onClick={handleUploadClick}
>
Upload results folder
<input
Select results' ZIP archive
<input
type="file"
accept='application/zip'
onChange={handleZipChange}
hidden
/>
</Button>
<>{ReactHtmlParser()}</>
</>
)
};
export const LoadResults = ({ outputsFiles, setOutputsFiles, onConfigChange, setExperiments, setExperimentsRows }) => {
export const LoadResults = ({ outputsFiles, setOutputsFiles, onConfigOverwrite, setExperiments, setExperimentsRows }) => {
return (
<DashboardLayout>
<Toolbar>
......@@ -165,12 +169,11 @@ export const LoadResults = ({ outputsFiles, setOutputsFiles, onConfigChange, set
<Main
outputsFiles={outputsFiles}
setOutputsFiles={setOutputsFiles}
onConfigChange = {onConfigChange}
onConfigOverwrite = {onConfigOverwrite}
setExperiments = {setExperiments}
setExperimentsRows = {setExperimentsRows}
/>
</DashboardLayout>
)
}
......@@ -20,6 +20,7 @@ export const emptyValues = {
"downloadUniprot":true,
"uniprotColumns":[],
"uniprotDatabases":[],
"recognizerDatabases":[],
"normalizationMethod":normalizationMethodOptions[0],
"keggcharterMaps":[],
"keggcharterTaxaLevel":keggcharterTaxaLevelOptions[0],
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment