Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit 837d99f

Browse files
authored
3454 report categories and types (#1170)
1 parent e592916 commit 837d99f

File tree

14 files changed

+242
-89
lines changed

14 files changed

+242
-89
lines changed

cypress/e2e/AnalysisPlugin.cy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ describe('Report (formerly Analysis) Plugin', () => {
8080
'This is where we can add a nice long description relating to why my report is better than yours.'
8181
);
8282
// set category and type
83-
cy.findByRole('button', { name: 'Anatomical' }).click();
84-
cy.findByRole('button', { name: 'Analysis' }).click();
83+
cy.findByRole('button', { name: /Anatomical/ }).click();
84+
cy.findByRole('button', { name: /Analysis/ }).click();
8585

8686
cy.findByText(/Drag and drop files/i).click();
8787
cy.get('input[type=file]').attachFile('sample1.png');

src/constants/index.ts

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,76 @@
11
// Report Constants
22
export const DEFAULT_SCALE = 50;
33

4-
export const REPORT_CATEGORIES = {
5-
circuit: [
6-
'Anatomical',
7-
'Connectivity',
8-
'Volumetric',
9-
'Morphometric',
10-
'Synapse',
4+
export const DEFAULT_REPORT_TYPES = [
5+
{
6+
label: 'Analysis',
7+
description:
8+
'Any other report that is neither "Validation" not "Prediction".',
9+
},
10+
{
11+
label: 'Validation',
12+
description:
13+
'A report that compares a property against a target value that is derived from experimental data.',
14+
},
15+
];
16+
17+
export const DEFAULT_REPORT_CATEGORIES = {
18+
DetailedCircuit: [
19+
{
20+
label: 'Anatomical',
21+
description:
22+
'A report relating to the cellular contents and placement of the circuit. For example, to neurons and the locations of their somata or dendrites.',
23+
},
24+
{
25+
label: 'Connectivity',
26+
description:
27+
'A report relating to the structure and topology of synaptic connections, analyzing the underlying directed connectivity graph.',
28+
},
29+
{
30+
label: 'Volumetric',
31+
description:
32+
'A report that explicitly considers the volume and/or shape of the modeled space. For example, the density of dendrites of synapses within a cubic volume.',
33+
},
34+
{
35+
label: 'Morphometric',
36+
description:
37+
'A report relating to the shape or morphology of the cells in the circuit. For example, counting the number of dendrite bifurcations.',
38+
},
39+
{
40+
label: 'Synapse',
41+
description:
42+
'A report relating to properties of synaptic connections. Unlike Connectivity it does not reduce them to a graph and instead considers properties of individual synapses, such as their dendritic locations or physiological parameters',
43+
},
44+
],
45+
Simulation: [
46+
{
47+
label: 'Spiking',
48+
description:
49+
'An analysis report based on the spiking activity of the simulated neurons.',
50+
},
51+
{
52+
label: 'Soma voltage',
53+
description:
54+
'An analysis report based on the (subthreshold) soma voltage traces of the simulated neurons.',
55+
},
56+
{
57+
label: 'LFP',
58+
description:
59+
'An analysis report based on traces of extracellular potential calculated from the simulations.',
60+
},
61+
{
62+
label: 'VSD',
63+
description:
64+
'An analysis report based on predicted VSD images calculated from the simulations.',
65+
},
66+
{
67+
label: 'Plasticity',
68+
description:
69+
'An analysis report based on the temporal evolution of plasticity-related synapse parameters.',
70+
},
1171
],
12-
simulation: ['Spiking', 'Soma voltage', 'LFP', 'VSD', 'Plasticity'],
1372
};
1473

15-
export const REPORT_TYPES = ['Validation', 'Analysis'];
16-
1774
export const DEFAULT_ANALYSIS_DATA_SPARQL_QUERY = `PREFIX s:<http://schema.org/>
1875
PREFIX prov:<http://www.w3.org/ns/prov#>
1976
PREFIX nsg:<https://neuroshapes.org/>

src/server/index.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ import {
1414
DEFAULT_SERVICE_ACCOUNTS_REALM,
1515
} from '../shared/store/reducers/config';
1616
import { DEFAULT_SEARCH_STATE } from '../shared/store/reducers/search';
17-
import { DEFAULT_ANALYSIS_DATA_SPARQL_QUERY } from '../constants';
17+
import {
18+
DEFAULT_ANALYSIS_DATA_SPARQL_QUERY,
19+
DEFAULT_REPORT_CATEGORIES,
20+
DEFAULT_REPORT_TYPES,
21+
} from '../constants';
1822

1923
const PORT_NUMBER = 8000;
2024

@@ -117,6 +121,12 @@ app.get('*', async (req: express.Request, res: express.Response) => {
117121
analysisPluginSparqlDataQuery:
118122
process.env.ANALYSIS_PLUGIN_SPARQL_DATA_QUERY ||
119123
DEFAULT_ANALYSIS_DATA_SPARQL_QUERY,
124+
analysisPluginCategories: process.env.ANALYSIS_PLUGIN_CATEGORIES
125+
? JSON.parse(process.env.ANALYSIS_PLUGIN_CATEGORIES)
126+
: DEFAULT_REPORT_CATEGORIES,
127+
analysisPluginTypes: process.env.ANALYSIS_PLUGIN_TYPES
128+
? JSON.parse(process.env.ANALYSIS_PLUGIN_TYPES)
129+
: DEFAULT_REPORT_TYPES,
120130
httpHeaderForInaccessibleDueToVPN:
121131
process.env.HTTP_HEADER_WHERE_INACCESSIBLE_OUTSIDE_OF_VPN ||
122132
'x-requires-vpn',

src/shared/components/AnalysisPlugin/AnalysisPlugin.tsx

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
SyncOutlined,
88
} from '@ant-design/icons';
99
import { Button, Collapse, Input, Modal } from 'antd';
10-
import { without, intersection } from 'lodash';
10+
import { without, intersection, uniq, flatten, map } from 'lodash';
1111
import * as React from 'react';
1212
import { getUsername } from '../../../shared/utils';
1313
import FriendlyTimeAgo from '../FriendlyDate';
@@ -38,10 +38,13 @@ import {
3838
} from '../../types/plugins/report';
3939
import Tools from './Tools';
4040
import ToolsEdit from './ToolsEdit';
41+
import { useSelector } from 'react-redux';
42+
import { RootState } from 'shared/store/reducers';
4143

4244
const AnalysisPlugin = ({
4345
analysisResourceType,
4446
containerId,
47+
containerResourceTypes,
4548
analysisReports,
4649
onSave,
4750
onDelete,
@@ -88,11 +91,46 @@ const AnalysisPlugin = ({
8891
{FileUpload(currentlyBeingEditedAnalysisReportId)}
8992
</Modal>
9093
);
94+
const {
95+
analysisPluginTypes: allReportTypes,
96+
analysisPluginCategories: allReportCategories,
97+
} = useSelector((state: RootState) => state.config);
98+
99+
const availableReportTypes = (intersection(
100+
uniq(flatten(map(analysisReports, 'types'))),
101+
allReportTypes.map(({ label }) => label)
102+
) as string[]).map(l => {
103+
const typeDescription = allReportTypes.find(t => t.label === l)
104+
?.description as string;
105+
return { label: l, description: typeDescription };
106+
});
107+
108+
const categoriesDefinedForContainerTypes = intersection(
109+
Object.keys(allReportCategories),
110+
containerResourceTypes
111+
);
112+
113+
const allReportCategoriesMatchingContainerType =
114+
categoriesDefinedForContainerTypes.length > 0
115+
? allReportCategories[categoriesDefinedForContainerTypes[0]]
116+
: [];
117+
118+
const availableReportCategories = (intersection(
119+
uniq(flatten(map(analysisReports, 'categories'))),
120+
allReportCategoriesMatchingContainerType.map(({ label }) => label)
121+
) as string[]).map(l => {
122+
const categoryDescription = allReportCategoriesMatchingContainerType.find(
123+
c => c.label === l
124+
)?.description as string;
125+
return { label: l, description: categoryDescription };
126+
});
91127

92128
return (
93129
<>
94130
{mode === 'create' && (
95131
<NewReportForm
132+
categories={allReportCategoriesMatchingContainerType}
133+
types={allReportTypes}
96134
dispatch={dispatch}
97135
onSave={onSave}
98136
FileUpload={FileUpload}
@@ -121,18 +159,19 @@ const AnalysisPlugin = ({
121159
<FolderAddOutlined />
122160
</Button>
123161
<CategoryWidget
124-
dispatch={dispatch}
162+
allCategories={allReportCategoriesMatchingContainerType}
163+
availableCategories={availableReportCategories}
125164
mode={mode}
126165
selectedCategories={selectedCategories}
127-
selectCategory={selectCategory}
128-
analysisReports={analysisReports}
166+
toggleSelectCategory={selectCategory}
129167
/>
168+
130169
<TypeWidget
131-
dispatch={dispatch}
170+
allTypes={allReportTypes}
171+
availableTypes={availableReportTypes}
132172
mode={mode}
133173
selectedTypes={selectedTypes}
134-
selectType={selectType}
135-
analysisReports={analysisReports}
174+
toggleSelectType={selectType}
136175
/>
137176
</>
138177
)}
@@ -341,7 +380,6 @@ const AnalysisPlugin = ({
341380
aria-label="Edit Report"
342381
style={{
343382
background: 'transparent',
344-
padding: '12px',
345383
}}
346384
icon={<EditOutlined />}
347385
title="Edit report"
@@ -480,6 +518,9 @@ const AnalysisPlugin = ({
480518
{mode === 'edit' && (
481519
<section>
482520
<CategoryEditWidget
521+
allCategories={
522+
allReportCategoriesMatchingContainerType
523+
}
483524
dispatch={dispatch}
484525
currentlyBeingEditedAnalysisReportCategories={
485526
currentlyBeingEditedAnalysisReportCategories

src/shared/components/AnalysisPlugin/CategoryEditWidget.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { Select, Form } from 'antd';
33
import './CategoryTypeEdits.less';
44
import { CategoryEditWidgetProps } from '../../types/plugins/report';
55
import { changeAnalysisCategories } from '../../slices/plugins/report';
6-
import { REPORT_CATEGORIES as CATEGORIES } from '../../../constants';
76

87
const CategoryEditWidget = ({
8+
allCategories,
99
dispatch,
1010
currentlyBeingEditedAnalysisReportCategories,
1111
}: CategoryEditWidgetProps) => {
@@ -18,7 +18,7 @@ const CategoryEditWidget = ({
1818
};
1919
return (
2020
<>
21-
{CATEGORIES.circuit && CATEGORIES.circuit.length > 0 && (
21+
{allCategories && allCategories.length > 0 && (
2222
<div style={{ margin: '20px 0' }} className={'categoryEdits'}>
2323
<h4 style={{ marginTop: '10px', color: '#003A8C' }}>Categories</h4>
2424
<Form layout={'vertical'}>
@@ -30,9 +30,9 @@ const CategoryEditWidget = ({
3030
onChange={selectedCategories}
3131
style={{ maxWidth: '900px' }}
3232
>
33-
{CATEGORIES.circuit.map(item => (
34-
<Select.Option key={item} value={item}>
35-
{item}
33+
{allCategories.map(cat => (
34+
<Select.Option key={cat.label} value={cat.label}>
35+
{cat.label}
3636
</Select.Option>
3737
))}
3838
</Select>

src/shared/components/AnalysisPlugin/CategoryWidget.tsx

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,43 @@
11
import * as React from 'react';
2-
import { Button } from 'antd';
3-
import { flatten, map, uniq, intersection } from 'lodash';
2+
import { Button, Tooltip } from 'antd';
43
import './Categories.less';
54
import { CategoryWidgetProps } from '../../types/plugins/report';
6-
7-
import { REPORT_CATEGORIES as CATEGORIES } from '../../../constants';
5+
import { InfoCircleOutlined } from '@ant-design/icons';
86

97
const CategoryWidget = ({
10-
dispatch,
11-
analysisReports,
8+
allCategories,
9+
availableCategories,
1210
selectedCategories,
1311
mode,
14-
selectCategory,
12+
toggleSelectCategory: selectCategory,
1513
}: CategoryWidgetProps) => {
16-
const availableCategories =
17-
mode === 'create'
18-
? CATEGORIES.circuit
19-
: intersection(
20-
uniq(flatten(map(analysisReports, 'categories'))),
21-
CATEGORIES.circuit
22-
);
14+
const categoriesToDisplay =
15+
mode === 'create' || availableCategories === undefined
16+
? allCategories
17+
: availableCategories;
2318

2419
return (
2520
<>
26-
{availableCategories && availableCategories.length > 1 && (
21+
{categoriesToDisplay && categoriesToDisplay.length > 1 && (
2722
<div className="categories-filter">
2823
{mode !== 'create' && <h3>Categories</h3>}
2924
<p>You may select one or multiple from the list</p>
3025
<div className="categories">
31-
{CATEGORIES.circuit
32-
.filter(o => availableCategories.includes(o))
33-
.map((object, i) => (
34-
<Button
35-
key={i}
36-
type="default"
37-
onClick={() => selectCategory(object)}
38-
className={`group-buttons ${
39-
selectedCategories.includes(object) ? 'active' : ''
40-
}`}
41-
>
42-
{object}
43-
</Button>
44-
))}
26+
{categoriesToDisplay.map((cat, i) => (
27+
<Button
28+
key={i}
29+
type="default"
30+
onClick={() => selectCategory(cat.label)}
31+
className={`group-buttons ${
32+
selectedCategories.includes(cat.label) ? 'active' : ''
33+
}`}
34+
>
35+
{cat.label}
36+
<Tooltip title={cat.description}>
37+
<InfoCircleOutlined />
38+
</Tooltip>
39+
</Button>
40+
))}
4541
</div>
4642
</div>
4743
)}

src/shared/components/AnalysisPlugin/NewReportForm.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ const NewReportForm = ({
1818
onSave,
1919
FileUpload,
2020
imagePreviewScale,
21+
categories,
22+
types,
2123
}: NewReportFormProps) => {
2224
const [form] = Form.useForm();
2325
const [selectedCategories, setSelectedCategories] = React.useState<string[]>(
@@ -54,6 +56,7 @@ const NewReportForm = ({
5456
reportGeneration
5557
);
5658
};
59+
5760
return (
5861
<Form layout={'vertical'} onFinish={onFinish} className="new-report-form">
5962
<Form.Item label="1. Report Name" name="name">
@@ -68,18 +71,18 @@ const NewReportForm = ({
6871
</Form.Item>
6972
<Form.Item label="3. Categories" aria-label="Analysis Categories">
7073
<CategoryWidget
71-
dispatch={dispatch}
74+
allCategories={categories}
7275
mode={'create'}
7376
selectedCategories={selectedCategories}
74-
selectCategory={selectCategory}
77+
toggleSelectCategory={selectCategory}
7578
/>
7679
</Form.Item>
7780
<Form.Item label="4. Types" aria-label="Analysis Types">
7881
<TypeWidget
79-
dispatch={dispatch}
82+
allTypes={types}
8083
mode={'create'}
8184
selectedTypes={selectedTypes}
82-
selectType={selectType}
85+
toggleSelectType={selectType}
8386
/>
8487
</Form.Item>
8588
<Form.Item label="5. Add Assets">

0 commit comments

Comments
 (0)