+
{sampleDropzone(singleScanDropRef, 'Single Scan (weighing only compound)')}
-
+
{sampleDropzone(doubleScanDropRef, 'Double Scan (weighing vessel and vessel+compound to calculate difference')}
- {openSampleTasks()}
+
+ {openSampleTasks()}
+
diff --git a/app/packs/src/components/sampleTaskInbox/SampleTaskNavigationElement.js b/app/packs/src/components/sampleTaskInbox/SampleTaskNavigationElement.js
new file mode 100644
index 0000000000..a0ac366aca
--- /dev/null
+++ b/app/packs/src/components/sampleTaskInbox/SampleTaskNavigationElement.js
@@ -0,0 +1,52 @@
+import React, { useContext, useEffect } from 'react';
+import { observer } from 'mobx-react';
+import { Button } from 'react-bootstrap';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+const SampleTaskNavigationElement = ({}) => {
+ const sampleTasksStore = useContext(StoreContext).sampleTasks;
+
+ const loadSampleTasks = () => {
+ sampleTasksStore.load();
+ }
+
+ useEffect(loadSampleTasks, []) // do this once at the creation of the component
+
+ const title = `${sampleTasksStore.openSampleTaskCount} open Sample Tasks`
+
+ return (
+
+
+
+ {sampleTasksStore.openSampleTaskCount > 0 && (
+
+ {sampleTasksStore.openSampleTaskCount}
+
+ )}
+
+
+ );
+}
+
+export default observer(SampleTaskNavigationElement);
diff --git a/app/packs/src/components/sampleTaskInbox/SampleTaskReloadButton.js b/app/packs/src/components/sampleTaskInbox/SampleTaskReloadButton.js
new file mode 100644
index 0000000000..df1b516135
--- /dev/null
+++ b/app/packs/src/components/sampleTaskInbox/SampleTaskReloadButton.js
@@ -0,0 +1,19 @@
+import React, { useContext } from 'react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+import { Glyphicon } from 'react-bootstrap';
+import { observer } from 'mobx-react';
+
+const SampleTaskReloadButton = ({}) => {
+ const sampleTasksStore = useContext(StoreContext).sampleTasks;
+
+ return (
+
+ );
+}
+export default observer(SampleTaskReloadButton);
diff --git a/app/packs/src/components/searchModal/SearchModal.js b/app/packs/src/components/searchModal/SearchModal.js
new file mode 100644
index 0000000000..5abee2425f
--- /dev/null
+++ b/app/packs/src/components/searchModal/SearchModal.js
@@ -0,0 +1,128 @@
+import React, { useContext } from 'react';
+import { Button, ButtonGroup, Modal } from 'react-bootstrap';
+import Draggable from "react-draggable";
+import { observer } from 'mobx-react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+import TextSearch from './forms/TextSearch';
+import KetcherRailsForm from './forms/KetcherRailsForm';
+import PublicationSearch from './forms/PublicationSearch';
+import NoFormSelected from './forms/NoFormSelected';
+
+const Components = {
+ advanced: TextSearch,
+ ketcher: KetcherRailsForm,
+ publication: PublicationSearch,
+ empty: NoFormSelected
+}
+
+const SearchModal = () => {
+ const searchStore = useContext(StoreContext).search;
+
+ let FormData = [
+ {
+ value: 'advanced',
+ label: 'Text search',
+ id: 0,
+ },
+ {
+ value: 'ketcher',
+ label: 'Structure search',
+ id: 1,
+ },
+ {
+ value: 'publication',
+ label: 'PublicationSearch',
+ id: 2,
+ },
+ ];
+
+ const FormComponent = (block) => {
+ let value = block.value.includes('generic') ? 'generic' : block.value;
+ if (typeof Components[value] !== "undefined") {
+ return React.createElement(Components[value], {
+ key: `${block.id}-${value}`
+ });
+ }
+ return React.createElement(Components['empty'], {
+ key: 'empty'
+ });
+ };
+
+ const Spinner = () => {
+ return (
+
+ );
+ }
+
+ let minimizedClass = searchStore.searchModalMinimized ? ' minimized' : '';
+ let searchTypeTextClass = searchStore.searchModalSelectedForm.value === 'advanced' ? 'active' : '';
+ let searchTypePublicationClass = searchStore.searchModalSelectedForm.value === 'publication' ? 'active' : '';
+ let searchTypeStructureClass = searchStore.searchModalSelectedForm.value === 'ketcher' ? 'active' : '';
+
+ return (
+
+ searchStore.handleCancel()}
+ backdrop={false}
+ dialogas="full-search"
+ dialogClassName="searching"
+ >
+
+
+
+
+ Please select your search criteria
+
+
+
+
+ searchStore.changeSearchModalSelectedForm(FormData[0])}
+ className={searchTypeTextClass}
+ >
+
+
+
+ Text search
+
+ searchStore.changeSearchModalSelectedForm(FormData[2])}
+ className={searchTypePublicationClass}
+ >
+
+
+
+ Publication search
+
+ searchStore.changeSearchModalSelectedForm(FormData[1])}
+ className={searchTypeStructureClass}
+ >
+
+
+
+ Structure search
+
+
+
+
+ searchStore.toggleSearchModalMinimized()} />
+
+
+
+ }>
+
+ {FormComponent(searchStore.searchModalSelectedForm)}
+
+
+
+
+
+ );
+}
+
+export default observer(SearchModal);
diff --git a/app/packs/src/components/searchModal/forms/AdvancedSearchRow.js b/app/packs/src/components/searchModal/forms/AdvancedSearchRow.js
new file mode 100644
index 0000000000..1c3dd543c0
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/AdvancedSearchRow.js
@@ -0,0 +1,249 @@
+import React, { useContext } from 'react';
+import { FormControl } from 'react-bootstrap'
+import Select from 'react-select3';
+import TreeSelect from 'antd/lib/tree-select';
+import UserStore from 'src/stores/alt/stores/UserStore';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+import SelectFieldData from './SelectFieldData';
+import { mapperFields, unitMapperFields } from './SelectMapperData';
+import { statusOptions, temperatureOptions, durationOptions } from 'src/components/staticDropdownOptions/options';
+
+const AdvancedSearchRow = ({ idx }) => {
+ const searchStore = useContext(StoreContext).search;
+ let selection = searchStore.advancedSearchValues[idx];
+ let searchElement = searchStore.searchElement;
+ let mapperOptions = mapperFields;
+ let fieldOptions = SelectFieldData.fields[searchElement.table];
+ fieldOptions = fieldOptions.filter(f => {
+ return f.value.advanced === true && f.value.advanced !== undefined
+ });
+
+ const specialMatcherFields = ['temperature', 'duration'];
+ if (specialMatcherFields.includes(selection.field.column)) {
+ mapperOptions = unitMapperFields;
+ }
+
+ let display = selection.link == '' ? 'none' : 'table';
+ let selectedFieldOption = selection.field.label == 'Name' && selection.table == 'samples' ? fieldOptions[0].value : selection.field;
+
+ const logicalOperators = [
+ { value: "AND", label: "AND" },
+ { value: "OR", label: "OR" }
+ ];
+
+ const { rxnos } = UserStore.getState();
+
+ const formElementValue = (formElement, e) => {
+ switch (formElement) {
+ case 'value':
+ const value = typeof e.target !== 'undefined' ? e.target.value : (typeof e.value !== 'undefined' ? e.value : e);
+ return value;
+ case 'field':
+ case 'link':
+ case 'match':
+ case 'unit':
+ return e.value;
+ default:
+ return e;
+ }
+ }
+
+ const temperatureConditions = (searchValues, column) => {
+ if (searchValues['unit'] == '' || column == 'temperature') {
+ searchValues['unit'] = '°C';
+ }
+ if (searchValues['match'] != '=') {
+ searchValues['match'] = '=';
+ }
+ return searchValues;
+ }
+
+ const durationConditions = (searchValues, column) => {
+ if (searchValues['unit'] == '' || column == 'duration') {
+ searchValues['unit'] = 'Hour(s)';
+ }
+ if (searchValues['match'] != '=') {
+ searchValues['match'] = '=';
+ }
+ return searchValues;
+ }
+
+ const checkValueForNumber = (value) => {
+ let message = 'Only numbers are allowed';
+ searchStore.removeErrorMessage(message);
+
+ if (isNaN(Number(value))) {
+ searchStore.addErrorMessage(message);
+ }
+ }
+
+ const onChange = (formElement) => (e) => {
+ let searchValues = { ...searchStore.advancedSearchValues[idx] };
+
+ if (e === undefined) {
+ searchValues[formElement] = '';
+ searchStore.addAdvancedSearchValue(idx, searchValues);
+ return;
+ }
+
+ let value = formElementValue(formElement, e, e.currentTarget);
+ searchValues[formElement] = value;
+ searchValues['table'] = searchElement.table;
+ searchValues['element_id'] = searchElement.element_id
+
+ const fieldColumn = searchValues.field.column;
+ if (value.column == 'temperature') { searchValues = temperatureConditions(searchValues, value.column) }
+ if (value.column == 'duration') { searchValues = durationConditions(searchValues, value.column) }
+ if (specialMatcherFields.includes(fieldColumn) && formElement == 'value') { checkValueForNumber(value) }
+ if (!specialMatcherFields.includes(fieldColumn) && formElement != 'unit' && !specialMatcherFields.includes(value.column)) {
+ searchValues['unit'] = '';
+ }
+ if (!specialMatcherFields.includes(fieldColumn) && ['>', '<'].includes(searchValues['match']) && formElement != 'match') {
+ searchValues['match'] = '=';
+ }
+ if (value.opt == 'rows' && searchValues['match'] !== 'ILIKE') { searchValues['match'] = 'ILIKE' }
+ searchStore.addAdvancedSearchValue(idx, searchValues);
+ }
+
+ const filterTreeNode = (input, child) => {
+ return String(child.props.search && child.props.search.toLowerCase()).indexOf(input && input.toLowerCase()) !== -1;
+ };
+
+ const defaultValueField = (
+
+ );
+
+ const valueField = () => {
+ if (selection.field == '') { return defaultValueField }
+
+ switch (selection.field.column) {
+ case 'status':
+ return (
+
+ value == selection.value)}
+ isClearable={false}
+ onChange={onChange('value')}
+ />
+
+ );
+ break;
+ case 'rxno':
+ return (
+
+
+
+ );
+ break;
+ case 'temperature':
+ return (
+ <>
+
+ value == selection.unit)}
+ isClearable={false}
+ onChange={onChange('unit')}
+ />
+
+
+
+
+ >
+ );
+ break;
+ case 'duration':
+ return (
+ <>
+
+ value == selection.unit)}
+ isClearable={false}
+ onChange={onChange('unit')}
+ />
+
+
+
+
+ >
+ );
+ break;
+ default:
+ return defaultValueField;
+ }
+ }
+
+ return (
+
+
+
+ value == selection.link)}
+ isClearable={false}
+ onChange={onChange('link')}
+ />
+
+
+
+ value == selection.match)}
+ isClearable={false}
+ className="match-select-options"
+ onChange={onChange('match')} />
+
+
+
+
+ {valueField()}
+
+ )
+}
+
+export default AdvancedSearchRow;
diff --git a/app/packs/src/components/searchModal/forms/AnalysesFieldData.js b/app/packs/src/components/searchModal/forms/AnalysesFieldData.js
new file mode 100644
index 0000000000..05bcfd68a9
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/AnalysesFieldData.js
@@ -0,0 +1,50 @@
+export default {
+ containers: [
+ {
+ label: 'Analyses',
+ value: [
+ {
+ label: '',
+ value: [
+ {
+ column: 'name',
+ label: 'Name',
+ key: 'analyses',
+ table: 'containers',
+ type: 'text',
+ },
+ {
+ column: 'status',
+ label: 'Status',
+ key: 'analyses',
+ table: 'containers',
+ type: 'select',
+ option_layers: 'confirmOptions',
+ },
+ {
+ column: 'kind',
+ label: 'Type (Chemical Methods Ontology)',
+ key: 'analyses',
+ table: 'containers',
+ type: 'chmos',
+ },
+ {
+ column: 'plain_text_content',
+ label: 'Content',
+ key: 'analyses',
+ table: 'containers',
+ type: 'text',
+ },
+ {
+ column: 'description',
+ label: 'Description',
+ key: 'analyses',
+ table: 'containers',
+ type: 'text',
+ },
+ ],
+ },
+ ],
+ },
+ ]
+}
diff --git a/app/packs/src/components/searchModal/forms/DetailSearch.js b/app/packs/src/components/searchModal/forms/DetailSearch.js
new file mode 100644
index 0000000000..6d954d51f2
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/DetailSearch.js
@@ -0,0 +1,733 @@
+import React, { useContext } from 'react';
+import { Button, Checkbox, FormControl, FormGroup, ControlLabel, InputGroup, Tabs, Tab, OverlayTrigger, Tooltip } from 'react-bootstrap'
+import Select from 'react-select3';
+import TreeSelect from 'antd/lib/tree-select';
+import SelectFieldData from './SelectFieldData';
+import SampleInventoryFieldData from './SampleInventoryFieldData';
+import AnalysesFieldData from './AnalysesFieldData';
+import MeasurementFieldData from './MeasurementFieldData';
+import UserStore from 'src/stores/alt/stores/UserStore';
+import UIStore from 'src/stores/alt/stores/UIStore';
+import { observer } from 'mobx-react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+import { ionic_liquids } from 'src/components/staticDropdownOptions/ionic_liquids';
+import * as FieldOptions from 'src/components/staticDropdownOptions/options';
+
+const DetailSearch = () => {
+ const searchStore = useContext(StoreContext).search;
+ let selection = searchStore.searchElement;
+ let fieldOptions = SelectFieldData.fields[selection.table];
+ const { rxnos, chmos, unitsSystem, segmentKlasses, genericEls, profile } = UserStore.getState();
+ const layoutTabs = profile.data[`layout_detail_${selection.table.slice(0, -1)}`];
+ const currentCollection = UIStore.getState().currentCollection;
+ let tabSegment = currentCollection?.tabs_segment;
+ let tabs = tabSegment && tabSegment[selection.table.slice(0, -1)] ? tabSegment[selection.table.slice(0, -1)] : layoutTabs;
+ let genericFields = [];
+ let genericSelectOptions = [];
+ let fieldsByTab = [];
+ let inventoryData = SampleInventoryFieldData.chemicals;
+ let analysesData = AnalysesFieldData.containers;
+ let measurementData = MeasurementFieldData.measurements;
+ let validFieldTypes = ['text', 'select', 'checkbox', 'system-defined', 'textarea', 'input-group', 'formula-field', 'table'];
+
+ const defaultDetailSearchValues = [{
+ link: 'AND',
+ match: 'ILIKE',
+ table: selection.table,
+ element_id: selection.element_id,
+ field: {
+ column: '',
+ label: '',
+ },
+ value: '',
+ smiles: '',
+ sub_values: [],
+ unit: '',
+ validationState: null
+ }];
+
+ const addGenericFieldsByLayers = (layers, fields, segment) => {
+ Object.entries(layers)
+ .sort((a, b) => a[1].position - b[1].position)
+ .map((value) => {
+ let label = value[1].label || '';
+ let values = value[1].fields.filter((f) => { return validFieldTypes.includes(f.type) });
+ let mappedValues = [];
+ if (values.length >= 1) {
+ values.map((v) => {
+ if (segment.id != undefined && v.table == undefined) {
+ Object.assign(v, { table: 'segments', element_id: segment.id });
+ }
+ if (v.key == undefined) {
+ Object.assign(v, { key: value[1].key });
+ }
+ mappedValues.push(v);
+ });
+ fields.push({ label: label, value: mappedValues });
+ }
+ });
+ }
+
+ const pushSegmentToSegmentField = (segment) => {
+ let layers = segment.properties_template.layers;
+ let options = segment.properties_template.select_options;
+ if (options) {
+ Object.assign(genericSelectOptions, options);
+ }
+ if (layers) {
+ let segments = [];
+ addGenericFieldsByLayers(layers, segments, segment);
+ fieldsByTab.push({ label: segment.label, value: segments });
+ }
+ }
+
+ if (genericEls) {
+ let currentGenericElement = genericEls.find((e) => { return e.name === selection.element_table.slice(0, -1) });
+ if (currentGenericElement) {
+ let layers = currentGenericElement.properties_template.layers;
+ let options = currentGenericElement.properties_template.select_options;
+ if (options) {
+ Object.assign(genericSelectOptions, options);
+ }
+
+ fieldOptions.map((o) => { genericFields.push(o) });
+ addGenericFieldsByLayers(layers, genericFields, {});
+ fieldsByTab.push({ label: 'Properties', value: genericFields });
+ fieldsByTab.push(...analysesData);
+ }
+ }
+
+ if (tabs) {
+ Object.entries(tabs)
+ .filter((value) => { return value[1] > 0 })
+ .sort((a, b) => a[1] - b[1])
+ .map((value) => {
+ if (['properties', 'research_plan'].includes(value[0])) {
+ fieldsByTab.push({ label: 'Properties', value: fieldOptions });
+ }
+ if (value[0] === 'analyses') {
+ fieldsByTab.push(...analysesData);
+ }
+ if (value[0] === 'inventory') {
+ fieldsByTab.push(...inventoryData);
+ }
+ if (value[0] === 'measurements') {
+ fieldsByTab.push(...measurementData);
+ }
+ if (segmentKlasses) {
+ segmentKlasses.filter((s) => {
+ if (s.element_klass.name == selection.table.slice(0, -1) && s.label == value[0]) {
+ pushSegmentToSegmentField(s);
+ }
+ });
+ }
+ });
+ }
+
+ const labelWithInfo = (option) => {
+ let infoButton = ''
+ if (option.info) {
+ infoButton = (
+
{option.info}
+ }
+ >
+
+
+ );
+ }
+
+ return (
+
{option.label}{infoButton}
+ );
+ }
+
+ const textInput = (option, type, selectedValue, column, keyLabel) => {
+ let validationState = selectedValue !== undefined ? selectedValue[column].validationState : null;
+ return (
+
+ {labelWithInfo(option)}
+
+
+ );
+ }
+
+ const checkboxInput = (option, type, selectedValue, column, keyLabel) => {
+ return (
+
+ {option.label}
+
+ );
+ }
+
+ const optionsForSelect = (option) => {
+ let options = [];
+ let genericOptions = [];
+
+ if (option.field !== undefined) {
+ genericOptions = genericFields.length >= 1 ? genericFields : fieldsByTab;
+ }
+
+ if (option.type == 'system-defined') {
+ let systemOptions = unitsSystem.fields.find((u) => { return u.field === option.option_layers });
+
+ if (option.column && option.column == 'duration') {
+ options = FieldOptions.durationOptions;
+ } else if (option.column && option.column == 'target_amount_value') {
+ options = FieldOptions.amountSearchOptions;
+ } else {
+ options = systemOptions.units;
+ }
+ } else if (genericOptions.length >= 1 && genericSelectOptions[option.option_layers]) {
+ Object.values(genericSelectOptions[option.option_layers].options).forEach((option) => {
+ option.value = option.label;
+ options.push(option);
+ });
+ } else {
+ options = FieldOptions[option.option_layers];
+ }
+ if (options && options[0] && options[0].value !== '' && option.type !== 'system-defined') {
+ options.unshift({ label: '', value: '' });
+ }
+ return options;
+ }
+
+ const selectInput = (option, type, selectedValue, columnName, keyLabel) => {
+ let options = optionsForSelect(option);
+ return (
+
+ {labelWithInfo(option)}
+ { return f.value == selectedValue[columnName].value }) : ''}
+ />
+
+ );
+ }
+
+ const solventOptions = Object.keys(ionic_liquids).reduce(
+ (solvents, ionicLiquid) => solvents.concat({
+ label: ionicLiquid,
+ value: {
+ external_label: ionicLiquid,
+ smiles: ionic_liquids[ionicLiquid],
+ density: 1.0
+ }
+ }), FieldOptions.defaultMultiSolventsSmilesOptions
+ );
+
+ const solventSelect = (option, type, selectedValue, columnName, keyLabel) => {
+ let options = solventOptions;
+ options.unshift({ label: '', value: '' });
+ return (
+
+ {labelWithInfo(option)}
+ { return f.label == selectedValue[columnName].value }) : ''}
+ />
+
+ );
+ }
+
+ const filterTreeNode = (input, child) => {
+ return String(child.props.search && child.props.search.toLowerCase()).indexOf(input && input.toLowerCase()) !== -1;
+ };
+
+ const rxnoChmosInput = (option, type, selectedValue, column) => {
+ let options = type == 'chmos' ? chmos : rxnos;
+ return (
+
+ {labelWithInfo(option)}
+
+
+ );
+ }
+
+ const textWithAddOnInput = (option, type, selectedValue, keyLabel) => {
+ let column = option.column || option.field;
+ let validationState = selectedValue !== undefined ? selectedValue[column].validationState : null;
+ return (
+
+ {labelWithInfo(option)}
+
+
+ {option.addon}
+
+
+ );
+ }
+
+ const ButtonOrAddOn = (units, value, column, option, subFieldId) => {
+ if (units.length > 1) {
+ return (
+
+
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ }
+
+ const systemDefinedInput = (option, type, selectedValue, column, keyLabel) => {
+ let units = optionsForSelect(option);
+ let value = selectedValue ? selectedValue[column].unit : units[0].label;
+ let validationState = selectedValue !== undefined ? selectedValue[column].validationState : null;
+ return (
+
+ {labelWithInfo(option)}
+
+
+ {ButtonOrAddOn(units, value, column, option, '')}
+
+
+ );
+ }
+
+ const inputGroupInput = (option, type, selectedValue, column, keyLabel) => {
+ let subFields = [];
+ option.sub_fields.map((field) => {
+ if (field.type == 'label') {
+ subFields.push(
{field.value} );
+ }
+ if (field.type == 'text') {
+ let subValue = selectedValue && selectedValue[column].sub_values[0][field.id] !== undefined ? selectedValue[column].sub_values[0][field.id] : '';
+ subFields.push(
+
+ );
+ }
+ });
+
+ return (
+
+ {labelWithInfo(option)}
+
+ {subFields}
+
+
+ );
+ }
+
+ const tableInputFields = (option, type, selectedValue, column, keyLabel) => {
+ let subFields = [];
+
+ option.sub_fields.map((field) => {
+ let condition =
+ selectedValue && selectedValue[column].sub_values !== undefined
+ && selectedValue[column].sub_values[0][field.id] !== undefined;
+ let selectedFieldValue = condition ? selectedValue[column].sub_values[0][field.id] : '';
+ let selectedUnitValue = typeof selectedFieldValue === 'object' ? selectedFieldValue.value_system : field.value_system;
+ selectedFieldValue = typeof selectedFieldValue === 'object' ? selectedFieldValue.value : selectedFieldValue;
+ let validationState = selectedValue !== undefined ? selectedValue[column].validationState : null;
+ let units = optionsForSelect(field);
+ let formElement = '';
+
+ if (field.type == 'text') {
+ formElement = (
+
+ );
+ }
+ if (field.type == 'system-defined') {
+ formElement = (
+
+
+ {ButtonOrAddOn(units, selectedUnitValue, column, option, field.id)}
+
+ );
+ }
+ if (formElement) {
+ subFields.push(
+
+ {field.col_name}
+ {formElement}
+
+ );
+ }
+ });
+ return subFields;
+ }
+
+ const subGroupWithAddOnFields = (option, type, selectedValue, column, keyLabel) => {
+ let subFields = [];
+
+ option.sub_fields.map((field) => {
+ let subValue = selectedValue && selectedValue[column].sub_values[0][field.key] !== undefined ? selectedValue[column].sub_values[0][field.key] : '';
+ let validationState = selectedValue !== undefined ? selectedValue[column].validationState : null;
+ subFields.push(
+
+
+ {field.addon}
+
+
+
+ );
+ });
+
+ return (
+
+ {labelWithInfo(option)}
+
+ {subFields}
+
+
+ );
+ }
+
+ const componentHeadline = (label, i, className) => {
+ if (label === '') { return '' }
+
+ return (
+
{label}
+ );
+ }
+
+ const valueByType = (type, e) => {
+ switch (type) {
+ case 'text':
+ case 'textarea':
+ case 'textWithAddOn':
+ case 'system-defined':
+ case 'formula-field':
+ case 'subGroupWithAddOn':
+ return e.target.value;
+ case 'checkbox':
+ return e.target.checked;
+ case 'select':
+ return e.value ? e.value : e.label;
+ case 'solventSelect':
+ return e.label;
+ default:
+ return e;
+ }
+ }
+
+ const matchByField = (field, type) => {
+ switch (field) {
+ case 'boiling_point':
+ case 'melting_point':
+ return '<@';
+ case 'density':
+ case 'molarity_value':
+ case 'target_amount_value':
+ case 'temperature':
+ case 'duration':
+ case 'purity':
+ case 'value_measurement':
+ case 'solvent_ratio':
+ case 'molecular_mass':
+ return '>=';
+ case 'unit_measurement':
+ case 'solvent_smiles':
+ return '=';
+ default:
+ return type == 'system-defined' ? '>=' : 'ILIKE';
+ }
+ }
+
+ const checkValueForNumber = (label, value) => {
+ if (value === '') { return null; }
+
+ let validationState = null;
+ let message = `${label}: Only numbers are allowed`;
+ searchStore.removeErrorMessage(message);
+
+ const regex = /^[0-9\s\-]+$/;
+ let numericCheck = label.includes('point') ? !regex.test(value) : isNaN(Number(value));
+
+ if (numericCheck) {
+ searchStore.addErrorMessage(message);
+ validationState = 'error';
+ }
+
+ return validationState;
+ }
+
+ const searchValueByStoreOrDefaultValue = (column) => {
+ let index = searchStore.detailSearchValues.findIndex((f) => { return Object.keys(f).indexOf(column) != -1; });
+ return (index !== -1 ? { ...searchStore.detailSearchValues[index][column] } : defaultDetailSearchValues[0]);
+ }
+
+ const handleSubFieldChanged = (id, option, column, type) => (e) => {
+ let sub_values = { id: id, value: e.target.value };
+ setSearchStoreValues(e.target.value, option, column, type, sub_values, '');
+ }
+
+ const handleTableFieldChanged = (id, option, column, type) => (e) => {
+ let value = e.target.value;
+ let subValue = {};
+ let optionField = option.sub_fields.find((f) => { return f.id == id });
+ let searchValue = searchValueByStoreOrDefaultValue(column);
+
+ if (optionField.value_system) {
+ let valueSystem =
+ searchValue.sub_values.length >= 1 && searchValue.sub_values[0][id] ? searchValue.sub_values[0][id].value_system : optionField.value_system;
+ subValue = { id: id, value: { value: value, value_system: valueSystem } };
+ } else {
+ subValue = { id: id, value: value };
+ }
+ setSearchStoreValues(e.target.value, option, column, type, subValue, '');
+ }
+
+ const handleFieldChanged = (option, column, type) => (e) => {
+ let value = valueByType(type, e);
+ let smiles = column == 'solvent_smiles' ? e.value.smiles : '';
+
+ setSearchStoreValues(value, option, column, type, {}, smiles);
+ }
+
+ const setSearchStoreValues = (value, option, column, type, subValue, smiles) => {
+ let searchValue = searchValueByStoreOrDefaultValue(column);
+ let cleanedValue = ['>=', '<@'].includes(searchValue.match) ? value.replace(/,/g, '.') : value;
+ searchValue.field = option;
+ searchValue.value = cleanedValue;
+ searchValue.sub_values = subValuesForSearchValue(searchValue, subValue, cleanedValue);
+ searchValue.match = matchByField(column, type);
+ searchValue.smiles = smiles;
+
+ if (['>=', '<@'].includes(searchValue.match)) {
+ searchValue.validationState = checkValueForNumber(option.label, cleanedValue);
+ }
+
+ if (type == 'system-defined' && searchValue.unit === '') {
+ let units = optionsForSelect(option);
+ searchValue.unit = units[0].label;
+ }
+ let searchSubValuesLength = searchValue.sub_values.length >= 1 ? Object.keys(searchValue.sub_values[0]).length : 0;
+ let typesWithSubValues = ['input-group', 'table'];
+
+ if (((value === '' || value === false) && !typesWithSubValues.includes(type)) || (searchSubValuesLength === 0 && typesWithSubValues.includes(type) && value === '')) {
+ searchStore.removeDetailSearchValue(column);
+ } else {
+ searchStore.addDetailSearchValue(column, searchValue);
+ }
+ }
+
+ const subValuesForSearchValue = (searchValue, subValue, value) => {
+ let subValues = searchValue.sub_values;
+ if (Object.keys(subValue).length === 0) { return subValues; }
+
+ if (subValues.length == 0) {
+ subValues.push({ [subValue.id]: subValue.value })
+ } else {
+ subValues[0][subValue.id] = subValue.value;
+ }
+
+ if (subValues[0][subValue.id] == '' && value == '') {
+ delete subValues[0][subValue.id];
+ }
+
+ return subValues;
+ }
+
+ const changeUnit = (units, value, column, option, subFieldId) => (e) => {
+ let activeUnitIndex = units.findIndex((f) => { return f.label.replace('°', '') === value || f.label === value });
+ let nextUnitIndex = activeUnitIndex === units.length - 1 ? 0 : activeUnitIndex + 1;
+ let newUnit = units[nextUnitIndex].label;
+ let searchValue = searchValueByStoreOrDefaultValue(column);
+
+ if (option.sub_fields && subFieldId) {
+ if (searchValue.sub_values.length >= 1 && searchValue.sub_values[0][subFieldId]) {
+ searchValue.sub_values[0][subFieldId].value_system = newUnit;
+ } else if (searchValue.sub_values.length >= 1 && !searchValue.sub_values[0][subFieldId]) {
+ searchValue.sub_values[0][subFieldId] = { value: '', value_system: newUnit };
+ } else {
+ searchValue.sub_values.push({ [subFieldId]: { value: '', value_system: newUnit } });
+ }
+ }
+
+ searchValue.unit = newUnit;
+ searchStore.addDetailSearchValue(column, searchValue);
+ }
+
+ const fieldsByType = (option, fields, keyLabel, i) => {
+ let multi_fields = ['stereo', 'xref', 'solvent', 'body'];
+ let column = multi_fields.includes(option.column) ? `${option.column}_${option.opt}` : (option.column || option.field);
+ column = option.key !== undefined ? `${column}_${option.key}` : column;
+ const selectedValue = searchStore.detailSearchValues.find((f) => { return Object.keys(f).indexOf(column) != -1 });
+
+ switch (option.type) {
+ case 'text':
+ case 'textarea':
+ case 'formula-field':
+ fields.push(textInput(option, 'text', selectedValue, column, keyLabel));
+ break;
+ case 'checkbox':
+ fields.push(checkboxInput(option, 'checkbox', selectedValue, column, keyLabel));
+ break;
+ case 'select':
+ fields.push(selectInput(option, 'select', selectedValue, column, keyLabel));
+ break;
+ case 'textWithAddOn':
+ fields.push(textWithAddOnInput(option, 'textWithAddOn', selectedValue, keyLabel));
+ break;
+ case 'rxnos':
+ case 'chmos':
+ fields.push(rxnoChmosInput(option, option.type, selectedValue, column));
+ break;
+ case 'system-defined':
+ fields.push(systemDefinedInput(option, 'system-defined', selectedValue, column, keyLabel));
+ break;
+ case 'input-group':
+ fields.push(inputGroupInput(option, 'input-group', selectedValue, column, keyLabel));
+ break;
+ case 'table':
+ fields.push(componentHeadline(option.label, 'table', 'detail-search-headline'));
+ fields.push(tableInputFields(option, 'table', selectedValue, column, keyLabel));
+ break;
+ case 'subGroupWithAddOn':
+ fields.push(subGroupWithAddOnFields(option, 'subGroupWithAddOn', selectedValue, column, keyLabel));
+ break;
+ case 'solventSelect':
+ fields.push(solventSelect(option, 'solventSelect', selectedValue, column, keyLabel));
+ break;
+ case 'spacer':
+ fields.push(
);
+ break;
+ case 'headline':
+ fields.push(componentHeadline(option.label, 'headline', 'detail-search-headline'));
+ break;
+ case 'hr':
+ fields.push(
);
+ break;
+ }
+ return fields;
+ }
+
+ const mapOptions = (options, fields) => {
+ options.map((field, i) => {
+ if (Array.isArray(field.value)) {
+ if (field.label) {
+ fields.push(componentHeadline(field.label, i, 'detail-search-headline'));
+ } else if (i != 0 && field.value[0].type !== 'table') {
+ fields.push(
);
+ }
+
+ field.value.map((option) => {
+ fields = fieldsByType(option, fields, field.label, i);
+ });
+ } else {
+ fields = fieldsByType(field.value, fields, selection.table, i);
+ }
+ });
+ return fields;
+ }
+
+ const handleSelectTab = (e) => {
+ searchStore.changeActiveTabKey(e);
+ }
+
+ const addTabToTabFields = (title, value, i, tabFields) => {
+ tabFields.push(
+
+ {mapOptions(value, [])}
+
+ );
+ return tabFields;
+ }
+
+ const FormElementTabs = () => {
+ let tabFields = [];
+
+ if (fieldsByTab.length >= 1) {
+ fieldsByTab.map((field, i) => {
+ addTabToTabFields(field.label, field.value, i, tabFields)
+ });
+ }
+
+ return (
+
+ {tabFields}
+
+ );
+ }
+
+ return (
+
+ {FormElementTabs()}
+
+ );
+}
+export default observer(DetailSearch);
diff --git a/app/packs/src/components/searchModal/forms/KetcherRailsForm.js b/app/packs/src/components/searchModal/forms/KetcherRailsForm.js
new file mode 100644
index 0000000000..6792869212
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/KetcherRailsForm.js
@@ -0,0 +1,188 @@
+import React, { useContext } from 'react';
+import { Button, ButtonToolbar, Form, FormControl, Radio, Grid, Row, Col, Panel } from 'react-bootstrap';
+import { togglePanel, showErrorMessage, panelVariables } from './SearchModalFunctions';
+import UIStore from 'src/stores/alt/stores/UIStore';
+import StructureEditor from 'src/models/StructureEditor';
+import SearchResult from './SearchResult';
+import { observer } from 'mobx-react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+const KetcherRailsform = () => {
+ const ketcherStructure = {
+ structure: {
+ path: 'ketcher',
+ setMolfileInFrame: false,
+ setMfFuncName: 'setMolecule',
+ getMfFuncName: 'getMolfile',
+ getMfWithCallback: false,
+ getSVGFuncName: 'getSVG',
+ getSVGWithCallback: false
+ }
+ }
+ const editor = new StructureEditor({ ...ketcherStructure, id: 'ketcher' });
+
+ const searchStore = useContext(StoreContext).search;
+ const panelVars = panelVariables(searchStore);
+
+ const handleSearchTypeChange = (e) => {
+ searchStore.changeKetcherRailsValue('searchType', e.target.value);
+ }
+
+ const handleTanimotoChange = (e) => {
+ const val = e.target && e.target.value;
+ if (!isNaN(val - val)) {
+ searchStore.changeKetcherRailsValue('tanimotoThreshold', e.target.value);
+ }
+ }
+
+ const handleSearch = () => {
+ const structure = editor.structureDef;
+ const { molfile } = structure;
+ handleStructureEditorSave(molfile);
+ }
+
+ const handleStructureEditorSave = (molfile) => {
+ if (molfile) {
+ searchStore.changeKetcherRailsValue('queryMolfile', molfile);
+ }
+ let message = 'Please add a drawing. The drawing is empty';
+ searchStore.addErrorMessage(message);
+
+ //// Check if blank molfile
+ const molfileLines = molfile.match(/[^\r\n]+/g);
+ //// If the first character ~ num of atoms is 0, we will not search
+ if (molfileLines[1].trim()[0] != 0) {
+ searchStore.showSearchResults();
+ searchStore.removeErrorMessage(message);
+ structureSearch(molfile);
+ }
+ }
+
+ const structureSearch = (molfile) => {
+ const uiState = UIStore.getState();
+ const { currentCollection } = uiState;
+ const collectionId = currentCollection ? currentCollection.id : null;
+ const isSync = currentCollection ? currentCollection.is_sync_to_me : false;
+ let tanimoto = searchStore.ketcherRailsValues.tanimotoThreshold;
+ if (tanimoto <= 0 || tanimoto > 1) { tanimoto = 0.3; }
+
+ const selection = {
+ elementType: 'structure',
+ molfile,
+ search_type: searchStore.ketcherRailsValues.searchType,
+ tanimoto_threshold: tanimoto,
+ page_size: uiState.number_of_results,
+ search_by_method: 'structure',
+ structure_search: true
+ };
+ searchStore.loadSearchResults({
+ selection, collectionId, isSync, moleculeSort: true
+ });
+ searchStore.clearSearchAndTabResults();
+ searchValuesByMolfile();
+ }
+
+ const handleClear = () => {
+ searchStore.clearSearchResults();
+
+ const iframe = document.querySelector('#ketcher').contentWindow;
+ iframe.document.querySelector('#new').click();
+ }
+
+ const searchValuesByMolfile = () => {
+ searchStore.changeSearchValues([searchStore.ketcherRailsValues.queryMolfile]);
+ }
+
+ return (
+ <>
+
+
+
+ {panelVars.searchTitle}
+
+
+
+
+
+ {showErrorMessage(searchStore)}
+
+
+
+
+
+ searchStore.handleCancel()}>
+ Cancel
+
+
+ Search
+
+
+
+
+
+
+
+
+ Substructure Search
+
+
+
+
+
+
+
+
+
+
+ {panelVars.resultTitle}
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+export default observer(KetcherRailsform);
diff --git a/app/packs/src/components/searchModal/forms/MeasurementFieldData.js b/app/packs/src/components/searchModal/forms/MeasurementFieldData.js
new file mode 100644
index 0000000000..cc2af55a02
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/MeasurementFieldData.js
@@ -0,0 +1,36 @@
+export default {
+ measurements: [
+ {
+ label: 'Measurements',
+ value: [
+ {
+ label: '',
+ value: [
+ {
+ column: 'description',
+ label: 'Description',
+ key: 'measurement',
+ table: 'measurements',
+ type: 'text',
+ },
+ {
+ column: 'value',
+ label: 'Value',
+ key: 'measurement',
+ table: 'measurements',
+ info: 'Only numbers are allowed',
+ type: 'text',
+ },
+ {
+ column: 'unit',
+ label: 'Unit',
+ key: 'measurement',
+ table: 'measurements',
+ type: 'text',
+ },
+ ],
+ },
+ ],
+ },
+ ]
+}
diff --git a/app/packs/src/components/searchModal/forms/NoFormSelected.js b/app/packs/src/components/searchModal/forms/NoFormSelected.js
new file mode 100644
index 0000000000..c5903e0085
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/NoFormSelected.js
@@ -0,0 +1,7 @@
+import React from 'react';
+
+export default () => (
+
+ Please select a search.
+
+);
diff --git a/app/packs/src/components/searchModal/forms/PublicationFieldData.js b/app/packs/src/components/searchModal/forms/PublicationFieldData.js
new file mode 100644
index 0000000000..aaf6516f1c
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/PublicationFieldData.js
@@ -0,0 +1,41 @@
+export default {
+ references: [
+ {
+ value: {
+ column: 'doi',
+ label: 'DOI',
+ type: 'text',
+ table: 'literatures',
+ },
+ label: 'DOI',
+ },
+ {
+ value: {
+ column: 'litype',
+ label: 'Type',
+ type: 'select',
+ option_layers: "CitationTypeMap",
+ table: 'literals',
+ },
+ label: 'Type',
+ },
+ {
+ value: {
+ column: 'title',
+ label: 'Title',
+ type: 'text',
+ table: 'literatures',
+ },
+ label: 'Title',
+ },
+ {
+ value: {
+ column: 'url',
+ label: 'URL',
+ type: 'text',
+ table: 'literatures',
+ },
+ label: 'URL',
+ },
+ ]
+}
diff --git a/app/packs/src/components/searchModal/forms/PublicationSearch.js b/app/packs/src/components/searchModal/forms/PublicationSearch.js
new file mode 100644
index 0000000000..437c7bf5ac
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/PublicationSearch.js
@@ -0,0 +1,111 @@
+import React, { useEffect, useContext } from 'react';
+import { Button, ButtonToolbar, Form, FormControl, Radio, Grid, Row, Col, Panel } from 'react-bootstrap';
+import { togglePanel, handleClear, showErrorMessage, handleSearch, panelVariables } from './SearchModalFunctions';
+import SearchResult from './SearchResult';
+import PublicationSearchRow from './PublicationSearchRow';
+import UIStore from 'src/stores/alt/stores/UIStore';
+import { observer } from 'mobx-react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+const PublicationSearch = () => {
+ const searchStore = useContext(StoreContext).search;
+ const panelVars = panelVariables(searchStore);
+
+ useEffect(() => {
+ let referenceValues = searchStore.publicationSearchValues;
+ const length = referenceValues.length - 1;
+ const lastInputRow = searchStore.publicationSearchValues[length];
+
+ const checkSelectedElements =
+ (lastInputRow.field && lastInputRow.value && lastInputRow.link) ||
+ (length == 0 && lastInputRow.field && lastInputRow.value);
+
+ if (checkSelectedElements) {
+ let searchValues = {
+ link: 'OR', match: 'ILIKE',
+ table: referenceValues[0].table,
+ field: '', value: ''
+ };
+ searchStore.addPublicationSearchValue(length + 1, searchValues);
+ }
+ }, [searchStore.publicationSearchValues]);
+
+ const renderDynamicRow = () => {
+ let dynamicRow = (
);
+
+ if (searchStore.publicationSearchValues.length > 1) {
+ let addedSelections = searchStore.publicationSearchValues.filter((val, idx) => idx > 0);
+
+ dynamicRow = addedSelections.map((_, idx) => {
+ let id = idx + 1;
+ return (
+
+ );
+ });
+ }
+
+ return dynamicRow;
+ }
+
+ return (
+ <>
+
+
+
+ {panelVars.searchTitle}
+
+
+
+
+
+
+
+ {showErrorMessage(searchStore)}
+
+ {renderDynamicRow()}
+
+
+
+ searchStore.handleCancel()}>
+ Cancel
+
+ handleClear(searchStore)}>
+ Reset
+
+ handleSearch(searchStore, UIStore.getState())} style={{ marginRight: '20px' }} >
+ Search
+
+
+
+
+
+
+
+
+ {panelVars.resultTitle}
+
+
+
+
+
+ handleClear(searchStore)}
+ />
+
+
+
+ >
+ );
+}
+
+export default observer(PublicationSearch);
diff --git a/app/packs/src/components/searchModal/forms/PublicationSearchRow.js b/app/packs/src/components/searchModal/forms/PublicationSearchRow.js
new file mode 100644
index 0000000000..6317f84195
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/PublicationSearchRow.js
@@ -0,0 +1,124 @@
+import React, { useContext } from 'react';
+import { FormControl } from 'react-bootstrap'
+import Select from 'react-select3';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+import PublicationFieldData from './PublicationFieldData';
+import { mapperFields } from './SelectMapperData';
+import { CitationTypeMap } from 'src/apps/mydb/elements/details/literature/CitationType';
+
+
+const PublicationSearchRow = ({ idx }) => {
+ const searchStore = useContext(StoreContext).search;
+ let selection = searchStore.publicationSearchValues[idx];
+ let mapperOptions = mapperFields;
+ let fieldOptions = PublicationFieldData.references;
+
+ const logicalOperators = [
+ { value: "AND", label: "AND" },
+ { value: "OR", label: "OR" }
+ ];
+
+ let citationOptions = [];
+ Object.entries(CitationTypeMap).forEach(([key, value]) => {
+ if (key == 'uncategorized') { return; }
+ citationOptions.push({ value: key, label: value.short, def: value.def });
+ });
+
+ const formElementValue = (formElement, e) => {
+ switch (formElement) {
+ case 'value':
+ const value = typeof e.target !== 'undefined' ? e.target.value : (typeof e.value !== 'undefined' ? e.value : e);
+ return value;
+ case 'field':
+ case 'link':
+ case 'match':
+ case 'unit':
+ return e.value;
+ default:
+ return e;
+ }
+ }
+
+ const onChange = (formElement) => (e) => {
+ let searchValues = { ...searchStore.publicationSearchValues[idx] };
+
+ if (e === undefined) {
+ searchValues[formElement] = '';
+ searchStore.addPublicationSearchValue(idx, searchValues);
+ return;
+ }
+
+ let value = formElementValue(formElement, e, e.currentTarget);
+ searchValues[formElement] = value;
+ searchStore.addPublicationSearchValue(idx, searchValues);
+ }
+
+ const defaultValueField = (
+
+ );
+
+ const valueField = () => {
+ if (selection.field == '' || selection.field.column != 'litype') {
+ return defaultValueField;
+ }
+
+ return (
+
+ value == selection.value)}
+ isClearable={false}
+ onChange={onChange('value')}
+ />
+
+ );
+ }
+
+ let display = selection.link == '' ? 'none' : 'table';
+
+ return (
+
+
+
+ value == selection.link)}
+ isClearable={false}
+ onChange={onChange('link')}
+ />
+
+
+
+ value == selection.match)}
+ isClearable={false}
+ className="match-select-options"
+ onChange={onChange('match')} />
+
+
+
+
+ {valueField()}
+
+ )
+}
+
+export default PublicationSearchRow;
diff --git a/app/packs/src/components/searchModal/forms/SampleInventoryFieldData.js b/app/packs/src/components/searchModal/forms/SampleInventoryFieldData.js
new file mode 100644
index 0000000000..250332c89a
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/SampleInventoryFieldData.js
@@ -0,0 +1,195 @@
+export default {
+ chemicals: [
+ {
+ label: 'Inventory',
+ value: [
+ {
+ label: 'Inventory Information',
+ value: [
+ {
+ column: 'status',
+ label: 'Status',
+ key: 'information',
+ table: 'chemicals',
+ type: 'select',
+ option_layers: "chemicalStatusOptions",
+ },
+ {
+ column: 'vendor',
+ label: 'Vendor',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ {
+ column: 'order_number',
+ label: 'Order number',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ {
+ column: 'amount',
+ label: 'Amount',
+ key: 'information',
+ table: 'chemicals',
+ type: 'system-defined',
+ option_layers: "mass",
+ info: 'Works only with the correct unit. Only numbers are allowed'
+ },
+ {
+ column: 'price',
+ label: 'Price',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ {
+ column: 'person',
+ label: 'Person',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ {
+ column: 'required_date',
+ label: 'Required date',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ {
+ column: 'ordered_date',
+ label: 'Ordered date',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ {
+ column: 'required_by',
+ label: 'Required by',
+ key: 'information',
+ table: 'chemicals',
+ type: 'text',
+ },
+ ],
+ },
+ {
+ label: 'Location and Information',
+ value: [
+ {
+ label: 'Host location',
+ column: 'host_location',
+ key: 'location',
+ table: 'chemicals',
+ type: 'subGroupWithAddOn',
+ sub_fields: [
+ {
+ key: 'host_building',
+ type: 'textWithAddOn',
+ addon: 'building',
+ label: 'building',
+ },
+ {
+ key: 'host_room',
+ type: 'textWithAddOn',
+ addon: 'room',
+ label: 'room',
+ },
+ {
+ key: 'host_cabinet',
+ type: 'textWithAddOn',
+ addon: 'cabinet',
+ label: 'cabinet',
+ },
+ ],
+ },
+ {
+ label: 'Host group',
+ column: 'host_group',
+ key: 'location',
+ table: 'chemicals',
+ type: 'subGroupWithAddOn',
+ sub_fields: [
+ {
+ key: 'host_group',
+ type: 'textWithAddOn',
+ addon: 'group',
+ label: 'group',
+ },
+ {
+ key: 'host_owner',
+ type: 'textWithAddOn',
+ addon: 'owner',
+ label: 'owner',
+ },
+ ],
+ },
+ {
+ label: 'Current location',
+ column: 'current_location',
+ key: 'location',
+ table: 'chemicals',
+ type: 'subGroupWithAddOn',
+ sub_fields: [
+ {
+ key: 'current_building',
+ type: 'textWithAddOn',
+ addon: 'building',
+ label: 'building',
+ },
+ {
+ key: 'current_room',
+ type: 'textWithAddOn',
+ addon: 'room',
+ label: 'room',
+ },
+ {
+ key: 'current_cabinet',
+ type: 'textWithAddOn',
+ addon: 'cabinet',
+ label: 'cabinet',
+ },
+ ],
+ },
+ {
+ label: 'Current group',
+ column: 'current_group',
+ key: 'location',
+ table: 'chemicals',
+ type: 'subGroupWithAddOn',
+ sub_fields: [
+ {
+ key: 'current_group',
+ type: 'textWithAddOn',
+ addon: 'group',
+ label: 'group',
+ },
+ {
+ key: 'borrowed_by',
+ type: 'textWithAddOn',
+ addon: 'by',
+ label: 'by',
+ },
+ ],
+ },
+ {
+ column: 'disposal_info',
+ label: 'Disposal information',
+ key: 'location',
+ type: 'text',
+ table: 'chemicals',
+ },
+ {
+ column: 'important_notes',
+ label: 'Important notes',
+ key: 'location',
+ type: 'text',
+ table: 'chemicals',
+ },
+ ],
+ }
+ ],
+ },
+ ],
+}
diff --git a/app/packs/src/components/searchModal/forms/SearchModalFunctions.js b/app/packs/src/components/searchModal/forms/SearchModalFunctions.js
new file mode 100644
index 0000000000..12e4189e20
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/SearchModalFunctions.js
@@ -0,0 +1,146 @@
+import React from 'react';
+import { Alert } from 'react-bootstrap';
+
+const togglePanel = (store) => () => {
+ if (store.searchResultsCount > 0) {
+ store.toggleSearch();
+ store.toggleSearchResults();
+ store.clearTabCurrentPage();
+ }
+}
+
+const handleClear = (store) => {
+ store.clearSearchResults();
+}
+
+const showErrorMessage = (store) => {
+ if (store.errorMessages.length >= 1) {
+ return
{store.errorMessages.join(', ')} ;
+ }
+}
+
+const filterSearchValues = (store) => {
+ let filteredOptions = [];
+
+ if (store.detail_search_values.length >= 1) {
+ store.detailSearchValues.map((f, i) => {
+ let values = { ...Object.values(f)[0] };
+ if (values.value != '') {
+ filteredOptions.push(values);
+ }
+ });
+ if (filteredOptions[0]) {
+ filteredOptions[0].link = '';
+ }
+ } else {
+ let searchValues =
+ store.searchModalSelectedForm.value == 'publication' ? store.publicationSearchValues : store.advancedSearchValues;
+ filteredOptions = searchValues.filter((f, id) => {
+ return (f.field && f.link && f.value) ||
+ (id == 0 && f.field && f.value)
+ });
+ }
+ store.changeSearchFilter(filteredOptions);
+ const storedFilter = store.searchFilters;
+ return storedFilter.length == 0 ? [] : storedFilter[0].filters;
+}
+
+const handleSearch = (store, uiState) => {
+ const { currentCollection } = uiState;
+ const collectionId = currentCollection ? currentCollection.id : null;
+ const filters = filterSearchValues(store);
+ let message = 'Please fill out all needed fields';
+ store.addErrorMessage(message);
+
+ if (filters.length > 0 && store.errorMessages.length == 1) {
+ store.showSearchResults();
+ store.removeErrorMessage(message);
+
+ const selection = {
+ elementType: 'advanced',
+ advanced_params: filters,
+ search_by_method: 'advanced',
+ page_size: uiState.number_of_results
+ };
+
+ store.loadSearchResults({
+ selection,
+ collectionId: collectionId,
+ isSync: uiState.isSync,
+ moleculeSort: true,
+ });
+ store.clearSearchAndTabResults();
+ searchValuesByFilters(store);
+ }
+}
+
+const searchValuesBySubFields = (val, table) => {
+ let label = '';
+ let value = '';
+ let unit = '';
+ let match = val.match;
+ let searchValues = [];
+
+ val.field.sub_fields.map((sub) => {
+ if (sub.type == 'label') {
+ label = sub.value;
+ } else if (val.sub_values[0][sub.id]) {
+ let subContent = val.sub_values[0][sub.id];
+ if (subContent.value !== undefined) {
+ value = subContent.value;
+ unit = subContent.value_system;
+ label = sub.col_name;
+ match = '>=';
+ } else {
+ value = subContent;
+ label = label === '' ? sub.col_name : label;
+ }
+ searchValues.push([val.link, table, `${val.field.label.toLowerCase()}: ${label.toLowerCase()}`, match, value, unit].join(" "));
+ } else if (val.sub_values[0][sub.key]) {
+ value = val.sub_values[0][sub.key];
+ searchValues.push([val.link, table, `${val.field.label.toLowerCase()}: ${sub.label.toLowerCase()}`, val.match, value, unit].join(" "));
+ }
+ });
+ return searchValues;
+}
+
+const searchValuesByFilters = (store) => {
+ const storedFilter = store.searchFilters;
+ const filters = storedFilter.length == 0 ? [] : storedFilter[0].filters;
+ let searchValues = [];
+
+ if (store.searchResultVisible && filters.length > 0) {
+ filters.map((val) => {
+ let table = val.field.table || val.table;
+ let value = val.value;
+ table = table.charAt(0).toUpperCase() + table.slice(1, -1).replace('_', ' ');
+ value = value != true ? value.replace(/[\n\r]/g, ' OR ') : value;
+
+ if (val.field.sub_fields && val.field.sub_fields.length >= 1 && val.sub_values.length >= 1) {
+ let values = searchValuesBySubFields(val, table);
+ searchValues.push(...values);
+ } else {
+ searchValues.push([val.link, table, val.field.label.toLowerCase(), val.match, value, val.unit].join(" "));
+ }
+ });
+ }
+ store.changeSearchValues(searchValues);
+}
+
+const panelVariables = (store) => {
+ let variables = [
+ {
+ defaultClassName: 'collapsible-search-result',
+ invisibleClassName: (store.search_result_panel_visible ? '' : ' inactive'),
+ inactiveSearchClass: (!store.searchVisible ? 'inactive' : ''),
+ inactiveResultClass: (!store.searchResultVisible ? 'inactive' : ''),
+ searchIcon: `fa fa-chevron-${store.search_icon} icon-right`,
+ resultIcon: `fa fa-chevron-${store.result_icon} icon-right`,
+ searchTitle: (store.searchVisible ? 'Search' : 'Refine search'),
+ resultTitle: (store.searchResultVisible ? 'Result' : 'Back to result'),
+ }
+ ];
+ return variables[0];
+}
+
+export { togglePanel, handleClear, showErrorMessage, handleSearch, panelVariables }
diff --git a/app/packs/src/components/searchModal/forms/SearchResult.js b/app/packs/src/components/searchModal/forms/SearchResult.js
new file mode 100644
index 0000000000..ad6bb91d83
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/SearchResult.js
@@ -0,0 +1,221 @@
+import React, { useContext, useState, useEffect } from 'react';
+import { Col, Navbar, Nav, NavItem, Row, Tab, OverlayTrigger, Tooltip, ButtonToolbar, Button, Alert } from 'react-bootstrap';
+import UIActions from 'src/stores/alt/actions/UIActions';
+import ElementActions from 'src/stores/alt/actions/ElementActions';
+import { observer } from 'mobx-react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+import UserStore from 'src/stores/alt/stores/UserStore';
+import SearchResultTabContent from './SearchResultTabContent';
+
+const SearchResult = ({ handleClear }) => {
+ const searchStore = useContext(StoreContext).search;
+ const results = searchStore.searchResultValues;
+ const userState = UserStore.getState();
+ const profile = userState.profile || {};
+ const genericElements = userState.genericEls || [];
+ const [visibleTabs, setVisibleTabs] = useState([]);
+ const [currentTabIndex, setCurrentTabIndex] = useState(0);
+
+ useEffect(() => {
+ if (typeof (profile) !== 'undefined' && profile &&
+ typeof (profile.data) !== 'undefined' && profile.data) {
+ const visible = [];
+
+ Object.entries(profile.data.layout).filter((value) => {
+ return value[1] > 0;
+ })
+ .sort((a, b) => a[1] - b[1])
+ .map((value, i) => {
+ let tab = results.find(val => val.id.indexOf(value[0]) !== -1);
+ let totalElements = tab === undefined ? 0 : tab.results.total_elements;
+ if (value[1] > 0) {
+ visible.push({ key: value[0], index: i, totalElements: totalElements });
+ }
+ });
+ setVisibleTabs(visible);
+ let activeTab = visible.find((v) => { return v.totalElements != 0 });
+ activeTab = activeTab !== undefined ? activeTab.index : 0;
+ setCurrentTabIndex(activeTab);
+ }
+ }, [results]);
+
+ const handleTabSelect = (e) => {
+ setCurrentTabIndex(e);
+ }
+
+ const handleAdoptResult = () => {
+ const preparedResult = prepareResultForDispatch();
+ UIActions.setSearchById(preparedResult);
+ ElementActions.changeSorting(true);
+ ElementActions.dispatchSearchResult(preparedResult);
+ searchStore.handleAdopt();
+ }
+
+ const prepareResultForDispatch = () => {
+ let resultObject = {};
+ results.map((val, i) => {
+ let firstElements = searchStore.tabSearchResultValues.find(tab => tab.id == `${val.id}-1`);
+ resultObject[val.id] = {
+ elements: firstElements.results.elements,
+ ids: val.results.ids,
+ page: val.results.page,
+ pages: val.results.pages,
+ perPage: val.results.per_page,
+ totalElements: val.results.total_elements
+ }
+ });
+ return resultObject;
+ }
+
+ const showResultErrorMessage = () => {
+ if (searchStore.resultErrorMessage.length >= 1) {
+ return
{searchStore.resultErrorMessage.join(', ')} ;
+ }
+ }
+
+ const SearchValuesList = () => {
+ if (searchStore.searchResultVisible && searchStore.searchValues.length > 0) {
+ return (
+
+
Your Search
+ {
+ searchStore.searchValues.map((val, i) => {
+ return
{val.replace('ILIKE', 'LIKE')}
+ })
+ }
+ {
+ searchStore.searchResultsCount > 0 ? null : (
+
+ )
+ }
+ {showResultErrorMessage()}
+
+ );
+ } else {
+ return null;
+ }
+ }
+
+ const ResultsCount = () => {
+ if (searchStore.searchResultsCount === 0) { return null }
+
+ const counts = results.map((val) => {
+ if (val.id == 'literatures') { return 0; }
+
+ return val.results.total_elements;
+ });
+ const sum = counts.reduce((a, b) => a + b, 0);
+
+ return (
+
{sum} results
+ );
+ }
+
+ const searchResultNavItem = (list, tabResult) => {
+ if (searchStore.searchResultsCount === 0) { return null }
+
+ const elnElements = ['sample', 'reaction', 'screen', 'wellplate', 'research_plan'];
+ let iconClass = `icon-${list.key}`;
+ let tooltipText = list.key && (list.key.replace('_', ' ').replace(/(^\w|\s\w)/g, m => m.toUpperCase()));
+
+ if (!elnElements.includes(list.key)) {
+ const genericElement = (genericElements && genericElements.find(el => el.name === list.key)) || {};
+ iconClass = `${genericElement.icon_name} icon_generic_nav`;
+ tooltipText = `${genericElement.label}
${genericElement.desc}`;
+ }
+ let tooltip = (
+
+ {tooltipText}
+
+ );
+ let itemClass = tabResult.total_elements == 0 ? ' no-result' : '';
+
+ return (
+
+
+
+
+
+ ({tabResult.total_elements})
+
+
+
+
+ );
+ }
+
+ const SearchResultTabContainer = () => {
+ if (searchStore.searchResultsCount === 0) { return null }
+
+ const navItems = [];
+ const tabContents = [];
+
+ visibleTabs.map((list) => {
+ const tab = results.find(val => val.id.indexOf(list.key) !== -1);
+ if (tab === undefined) { return; }
+ const tabResult = tab.results;
+
+ const navItem = searchResultNavItem(list, tabResult);
+ const tabContent =
+
+
+ navItems.push(navItem);
+ tabContents.push(tabContent);
+ });
+
+ return (
+
+
+
+
+
+ {navItems}
+
+
+
+
+
+ {tabContents}
+
+
+
+
+ );
+ }
+
+ const ResultButtons = () => {
+ if (searchStore.searchResultsCount === 0) { return null }
+
+ return (
+
+ searchStore.handleCancel()}>
+ Cancel
+
+
+ Reset
+
+
+ Adopt Result
+
+
+ );
+ }
+
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
+
+export default observer(SearchResult);
diff --git a/app/packs/src/components/searchModal/forms/SearchResultTabContent.js b/app/packs/src/components/searchModal/forms/SearchResultTabContent.js
new file mode 100644
index 0000000000..8bafc06572
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/SearchResultTabContent.js
@@ -0,0 +1,183 @@
+import React, { useContext, useEffect } from 'react';
+import { Tab, Pagination } from 'react-bootstrap';
+import { observer } from 'mobx-react';
+import UIStore from 'src/stores/alt/stores/UIStore';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+import SampleName from 'src/components/common/SampleName';
+import SvgWithPopover from 'src/components/common/SvgWithPopover';
+
+const SearchResultTabContent = ({ list, tabResult }) => {
+ const searchStore = useContext(StoreContext).search;
+ let currentPage = searchStore.tabCurrentPage.length >= 1 ? searchStore.tab_current_page[list.index] : undefined;
+ let currentPageNumber = currentPage === undefined ? 1 : currentPage[list.key];
+
+ useEffect(() => {
+ if (currentPage === undefined) {
+ searchStore.changeTabCurrentPage(list.key, 1, list.index);
+ }
+ }, []);
+
+ const handlePaginationSelect = (index, ids, key) => {
+ searchStore.changeTabCurrentPage(key, index, list.index);
+
+ const search_result = searchStore.tabSearchResultValues.find(val => val.id == `${key}s-${index}`);
+ if (search_result === undefined) {
+ searchByIds(index, ids, key);
+ }
+ }
+
+ const searchByIds = (index, ids, key) => {
+ const uiState = UIStore.getState();
+ const { currentCollection } = uiState;
+ const collectionId = currentCollection ? currentCollection.id : null;
+ const isSync = currentCollection ? currentCollection.is_sync_to_me : false;
+
+ const selection = {
+ elementType: 'by_ids',
+ id_params: {
+ model_name: key,
+ ids: ids,
+ total_elements: tabResult.total_elements,
+ with_filter: false,
+ },
+ list_filter_params: {},
+ search_by_method: 'search_by_ids',
+ page_size: tabResult.per_page
+ };
+
+ searchStore.loadSearchResultTab({
+ selection,
+ collectionId: collectionId,
+ isSync: isSync,
+ page_size: tabResult.per_page,
+ page: index,
+ moleculeSort: true,
+ });
+ }
+
+ const pagination = (tabResult, key) => {
+ if (tabResult.pages === 1) { return; }
+ if (tabResult.total_elements == 0) { return; }
+
+ let splittedIds = [];
+ let items = [];
+ for (let i = 0; i < tabResult.ids.length; i += tabResult.per_page) {
+ splittedIds.push(tabResult.ids.slice(i, i + tabResult.per_page));
+ }
+
+ const minPage = Math.max(currentPageNumber - 2, 1);
+ const maxPage = Math.min(minPage + 4, tabResult.pages);
+ items.push(
handlePaginationSelect(1, splittedIds[0], key)} />);
+ if (currentPageNumber > 1) {
+ items.push( handlePaginationSelect(currentPageNumber - 1, splittedIds[currentPageNumber - 1], key)} />);
+ }
+ if (minPage > 1) {
+ items.push( );
+ }
+ for (let number = minPage; number <= maxPage; number++) {
+ items.push(
+ handlePaginationSelect(number, splittedIds[number - 1], key)}
+ >
+ {number}
+
+ )
+ }
+ if (tabResult.pages > maxPage) {
+ items.push( );
+ }
+ if (currentPageNumber < tabResult.pages) {
+ items.push( handlePaginationSelect(currentPageNumber + 1, splittedIds[currentPageNumber], key)} />);
+ items.push( handlePaginationSelect(tabResult.pages, splittedIds[tabResult.pages - 1], key)} />);
+ }
+
+ return (
+
+ );
+ }
+
+ const svgPreview = (object) => {
+ if (!['sample', 'reaction'].includes(object.type)) { return null; }
+
+ const title = object.type == 'sample' ? object.molecule_iupac_name : object.short_label;
+ return (
+
+ );
+ }
+
+ const copyToClipboard = (element) => {
+ if (element.target.dataset.clipboardText) {
+ navigator.clipboard.writeText(element.target.dataset.clipboardText);
+ }
+ }
+
+ const tabContentList = () => {
+ let contentList = No results
;
+ let resultsByPage = searchStore.tabSearchResultValues.find(val => val.id == `${list.key}s-${currentPageNumber}`);
+ let tabResultByPage = resultsByPage != undefined ? resultsByPage.results : { elements: [] };
+
+ if (tabResultByPage.elements.length > 0) {
+ contentList = tabResultByPage.elements.map((object, i, elements) => {
+ let previous = elements[i - 1];
+ let previousMolecule = previous ? previous.molecule_formula : '';
+ let moleculeName = previous && previousMolecule == object.molecule_formula ? '' : ;
+ let shortLabelWithName = ['screen', 'research_plan'].includes(object.type) ? object.name : [object.short_label, object.name].join(" - ");
+
+ if (['sample', 'reaction'].includes(object.type)) {
+ return (
+
+
+ {moleculeName || object.type == 'reaction' ? svgPreview(object) : ''}
+ {moleculeName}
+
+
+ {shortLabelWithName}
+
+
+ )
+ } else {
+ return (
+
+
+ {shortLabelWithName}
+
+
+ )
+ }
+ });
+ } else if (tabResult.total_elements != 0) {
+ contentList =
;
+ }
+ return contentList;
+ }
+
+ return (
+
+
+ {tabContentList()}
+
+ {pagination(tabResult, list.key)}
+
+ );
+}
+
+export default observer(SearchResultTabContent);
diff --git a/app/packs/src/components/searchModal/forms/SelectFieldData.js b/app/packs/src/components/searchModal/forms/SelectFieldData.js
new file mode 100644
index 0000000000..7b3545e4e7
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/SelectFieldData.js
@@ -0,0 +1,649 @@
+export default {
+ fields: {
+ samples: [
+ {
+ value: {
+ column: 'iupac_name',
+ label: 'Molecule',
+ type: 'text',
+ advanced: false,
+ table: 'molecules',
+ },
+ label: 'Molecule'
+ },
+ {
+ value: {
+ column: 'stereo',
+ opt: 'abs',
+ label: 'Stereo Abs',
+ type: 'select',
+ option_layers: "stereoAbsOptions",
+ advanced: false,
+ },
+ label: 'Stereo Abs'
+ },
+ {
+ value: {
+ column: 'stereo',
+ opt: 'rel',
+ label: 'Stereo Rel',
+ type: 'select',
+ option_layers: "stereoRelOptions",
+ advanced: false,
+ },
+ label: 'Stereo Rel'
+ },
+ {
+ value: {
+ column: 'decoupled',
+ label: 'Decoupled',
+ type: 'checkbox',
+ advanced: false,
+ },
+ label: 'Decoupled'
+ },
+ {
+ value: {
+ column: 'name',
+ label: 'Sample name',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Sample name'
+ },
+ {
+ value: {
+ column: 'short_label',
+ label: 'Short Label',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Short Label'
+ },
+ {
+ value: {
+ column: 'external_label',
+ label: 'External Label',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'External Label'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'inventory_label',
+ label: 'Inventory Label',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Inventory Label'
+ },
+ {
+ value: {
+ column: 'target_amount_value',
+ label: 'Amount',
+ type: 'system-defined',
+ option_layers: 'amount',
+ info: 'Works only with the correct unit. Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Amount'
+ },
+ {
+ value: {
+ column: 'density',
+ label: 'Density',
+ type: 'textWithAddOn',
+ addon: 'g/ml',
+ info: 'Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Density'
+ },
+ {
+ value: {
+ column: 'molarity_value',
+ label: 'Molarity',
+ type: 'textWithAddOn',
+ addon: 'M',
+ info: 'Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Molarity'
+ },
+ {
+ value: {
+ column: 'purity',
+ label: 'Purity / Concentration',
+ type: 'text',
+ info: 'Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Purity / Concentration'
+ },
+ {
+ value: {
+ column: 'inventory_sample',
+ label: 'Inventory',
+ type: 'checkbox',
+ advanced: false,
+ },
+ label: 'Inventory'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'cas',
+ label: 'CAS',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'CAS'
+ },
+ {
+ value: {
+ column: 'molecular_mass',
+ label: 'Molecular mass',
+ type: 'textWithAddOn',
+ addon: 'g/mol',
+ advanced: false,
+ },
+ label: 'Molecular mass'
+ },
+ {
+ value: {
+ column: 'sum_formula',
+ label: 'Sum formula',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Sum formula'
+ },
+ {
+ value: {
+ type: 'headline',
+ label: 'Properties',
+ },
+ label: 'Properties',
+ },
+ {
+ value: {
+ column: 'melting_point',
+ label: 'Melting point',
+ type: 'textWithAddOn',
+ addon: '°C',
+ info: 'Numbers within a range: input of 2 numbers, e.g. 100 - 200. Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Melting point'
+ },
+ {
+ value: {
+ column: 'boiling_point',
+ label: 'Boiling point',
+ type: 'textWithAddOn',
+ addon: '°C',
+ info: 'Numbers within a range: input of 2 numbers, e.g. 100 - 200. Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Boiling point'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'flash_point',
+ label: 'Flash Point',
+ type: 'system-defined',
+ option_layers: 'temperature',
+ info: 'Works only with the correct temperature unit. Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Flash Point'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'refractive_index',
+ label: 'Refractive Index',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Refractive Index'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'form',
+ label: 'Form',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Form'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'color',
+ label: 'Color',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Color'
+ },
+ {
+ value: {
+ column: 'xref',
+ opt: 'solubility',
+ label: 'Solubility',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Solubility'
+ },
+ {
+ value: {
+ type: 'headline',
+ label: 'Solvents',
+ },
+ label: 'Solvents',
+ },
+ {
+ value: {
+ column: 'dry_solvent',
+ label: 'Dry solvent',
+ type: 'checkbox',
+ advanced: false,
+ },
+ label: 'Dry solvent'
+ },
+ {
+ value: {
+ column: 'solvent',
+ opt: 'smiles',
+ label: 'Label',
+ type: 'solventSelect',
+ option_layers: 'ionic_liquids',
+ advanced: false,
+ },
+ label: 'Label'
+ },
+ {
+ value: {
+ column: 'solvent',
+ opt: 'ratio',
+ label: 'Ratio',
+ type: 'text',
+ info: 'Only numbers are allowed',
+ advanced: false,
+ },
+ label: 'Ratio'
+ },
+ {
+ value: {
+ type: 'spacer',
+ },
+ label: '',
+ },
+ {
+ value: {
+ type: 'hr',
+ },
+ label: '',
+ },
+ {
+ value: {
+ column: 'description',
+ label: 'Description',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Description'
+ },
+ {
+ value: {
+ column: 'location',
+ label: 'Location',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Location'
+ },
+ {
+ value: {
+ column: 'content',
+ label: 'Private Note',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Private Note'
+ },
+ ],
+ reactions: [
+ {
+ value: {
+ column: 'name',
+ label: 'Name',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Name'
+ },
+ {
+ value: {
+ column: 'short_label',
+ label: 'Short Label',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Short Label'
+ },
+ {
+ value: {
+ column: 'status',
+ label: 'Status',
+ type: 'select',
+ option_layers: 'statusOptions',
+ advanced: true,
+ },
+ label: 'Status'
+ },
+ {
+ value: {
+ column: 'conditions',
+ label: 'Conditions',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Conditions'
+ },
+ {
+ value: {
+ column: 'temperature',
+ label: 'Temperature',
+ type: 'system-defined',
+ option_layers: 'temperature',
+ info: 'Only numbers are allowed',
+ advanced: true,
+ },
+ label: 'Temperature'
+ },
+ {
+ value: {
+ column: 'duration',
+ label: 'Duration',
+ type: 'system-defined',
+ option_layers: 'duration',
+ info: 'Only numbers are allowed',
+ advanced: true,
+ },
+ label: 'Duration'
+ },
+ {
+ value: {
+ column: 'rxno',
+ label: 'Type',
+ type: 'rxnos',
+ advanced: true,
+ },
+ label: 'Type'
+ },
+ {
+ value: {
+ column: 'role',
+ label: 'Role',
+ type: 'select',
+ option_layers: 'rolesOptions',
+ advanced: false,
+ },
+ label: 'Role'
+ },
+ {
+ value: {
+ column: 'plain_text_description',
+ label: 'Description',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Description'
+ },
+ {
+ value: {
+ column: 'purification',
+ label: 'Purification',
+ type: 'select',
+ option_layers: 'purificationOptions',
+ advanced: false,
+ },
+ label: 'Purification'
+ },
+ {
+ value: {
+ column: 'plain_text_observation',
+ label: 'Additional Information',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Additional Information'
+ },
+ {
+ value: {
+ column: 'dangerous_products',
+ label: 'Dangerous Products',
+ type: 'select',
+ option_layers: 'dangerousProductsOptions',
+ advanced: false,
+ },
+ label: 'Dangerous Products'
+ },
+ {
+ value: {
+ column: 'tlc_solvents',
+ label: 'TLC Solvents (parts)',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'TLC Solvents (parts)'
+ },
+ {
+ value: {
+ column: 'rf_value',
+ label: 'Rf-Value',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'Rf-Value'
+ },
+ {
+ value: {
+ column: 'tlc_description',
+ label: 'TLC-Description',
+ type: 'text',
+ advanced: false,
+ },
+ label: 'TLC-Description'
+ },
+ {
+ value: {
+ column: 'content',
+ label: 'Private Note',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Private Note'
+ },
+ ],
+ wellplates: [
+ {
+ value: {
+ column: 'name',
+ label: 'Name',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Name'
+ },
+ {
+ value: {
+ column: 'short_label',
+ label: 'Short Label',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Short Label'
+ },
+ {
+ value: {
+ column: 'readout_titles',
+ label: 'Readout Titles',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Readout Titles'
+ },
+ {
+ value: {
+ column: 'plain_text_description',
+ label: 'Description',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Description'
+ },
+ {
+ value: {
+ column: 'content',
+ label: 'Private Note',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Private Note'
+ },
+ ],
+ screens: [
+ {
+ value: {
+ column: 'name',
+ label: 'Name',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Name'
+ },
+ {
+ value: {
+ column: 'collaborator',
+ label: 'Collaborator',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Collaborator'
+ },
+ {
+ value: {
+ column: 'requirements',
+ label: 'Requirements',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Requirements'
+ },
+ {
+ value: {
+ column: 'conditions',
+ label: 'Conditions',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Conditions'
+ },
+ {
+ value: {
+ column: 'result',
+ label: 'Result',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Result'
+ },
+ {
+ value: {
+ column: 'plain_text_description',
+ label: 'Description',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Description'
+ },
+ {
+ value: {
+ column: 'content',
+ label: 'Private Note',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Private Note'
+ },
+ ],
+ research_plans: [
+ {
+ value: {
+ column: 'name',
+ label: 'Name',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Name'
+ },
+ {
+ value: {
+ column: 'body',
+ opt: 'ops',
+ label: 'Text',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Text'
+ },
+ {
+ value: {
+ column: 'body',
+ opt: 'rows',
+ label: 'Table',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Table'
+ },
+ {
+ value: {
+ column: 'content',
+ label: 'Private Note',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Private Note'
+ },
+ ],
+ elements: [
+ {
+ value: {
+ column: 'name',
+ label: 'Name',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Name'
+ },
+ {
+ value: {
+ column: 'short_label',
+ label: 'Short Label',
+ type: 'text',
+ advanced: true,
+ },
+ label: 'Short Label'
+ },
+ ],
+ }
+}
diff --git a/app/packs/src/components/searchModal/forms/SelectMapperData.js b/app/packs/src/components/searchModal/forms/SelectMapperData.js
new file mode 100644
index 0000000000..4247386959
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/SelectMapperData.js
@@ -0,0 +1,31 @@
+const mapperFields = [
+ {
+ value: "=",
+ label: "EXACT"
+ },
+ {
+ value: "ILIKE",
+ label: "LIKE"
+ },
+ {
+ value: "NOT ILIKE",
+ label: "NOT LIKE"
+ }
+]
+
+const unitMapperFields = [
+ {
+ value: '=',
+ label: 'EXACT',
+ },
+ {
+ value: '<',
+ label: 'LESS THAN',
+ },
+ {
+ value: '>',
+ label: 'BIGGER THAN',
+ },
+]
+
+export { mapperFields, unitMapperFields };
diff --git a/app/packs/src/components/searchModal/forms/TextSearch.js b/app/packs/src/components/searchModal/forms/TextSearch.js
new file mode 100644
index 0000000000..9b78f63de2
--- /dev/null
+++ b/app/packs/src/components/searchModal/forms/TextSearch.js
@@ -0,0 +1,214 @@
+import React, { useEffect, useContext } from 'react';
+import { Button, ButtonToolbar, ToggleButtonGroup, ToggleButton, Panel, Tooltip, OverlayTrigger } from 'react-bootstrap';
+import { togglePanel, handleClear, showErrorMessage, handleSearch, panelVariables } from './SearchModalFunctions';
+import UIStore from 'src/stores/alt/stores/UIStore';
+import UserStore from 'src/stores/alt/stores/UserStore';
+import AdvancedSearchRow from './AdvancedSearchRow';
+import DetailSearch from './DetailSearch';
+import SearchResult from './SearchResult';
+import { observer } from 'mobx-react';
+import { StoreContext } from 'src/stores/mobx/RootStore';
+
+const TextSearch = () => {
+ const elnElements = ['samples', 'reactions', 'wellplates', 'screens', 'research_plans'];
+ const genericElements = UserStore.getState().genericEls || [];
+ const searchStore = useContext(StoreContext).search;
+ const panelVars = panelVariables(searchStore);
+
+ useEffect(() => {
+ let advancedValues = searchStore.advancedSearchValues;
+ const length = advancedValues.length - 1;
+ const lastInputRow = searchStore.advancedSearchValues[length];
+
+ const checkSelectedElements =
+ (lastInputRow.field && lastInputRow.value && lastInputRow.link) ||
+ (length == 0 && lastInputRow.field && lastInputRow.value);
+
+ if (checkSelectedElements) {
+ let searchValues = {
+ link: 'OR', match: 'ILIKE',
+ table: advancedValues[0].table,
+ element_id: advancedValues[0].element_id,
+ field: '', value: '', smiles: '', sub_values: [],
+ unit: '', validationState: null
+ };
+ searchStore.addAdvancedSearchValue(length + 1, searchValues);
+ }
+ }, [searchStore.advancedSearchValues]);
+
+ const handleChangeElement = (element) => {
+ const table = elnElements.includes(element) ? element : 'elements';
+ const genericElement = (!elnElements.includes(element) && genericElements.find(el => el.name + 's' === element)) || {};
+
+ searchStore.changeSearchElement({
+ table: table,
+ element_id: (genericElement.id || 0),
+ element_table: element
+ });
+ let searchValues = { ...searchStore.advancedSearchValues[0] };
+ searchValues.table = table;
+ searchValues.element_id = (genericElement.id || 0);
+ searchStore.addAdvancedSearchValue(0, searchValues);
+ }
+
+ const SelectSearchTable = () => {
+ const layout = UserStore.getState().profile.data.layout;
+
+ const elnElements = ['sample', 'reaction', 'screen', 'wellplate', 'research_plan'];
+
+ const buttons = Object.entries(layout).filter((value) => {
+ return value[1] > 0
+ })
+ .sort((a, b) => a[1] - b[1])
+ .map((value) => {
+ let iconClass = `icon-${value[0]}`;
+ if (!elnElements.includes(value[0])) {
+ const genericElement = (genericElements && genericElements.find(el => el.name === value[0])) || {};
+ iconClass = `${genericElement.icon_name} icon_generic_nav`;
+ }
+ let tooltip = (
+
+ {value[0].charAt(0).toUpperCase() + value[0].slice(1).replace('_', ' ')}
+
+ );
+
+ return (
+
+
+
+
+
+ );
+ });
+
+ return (
+
+ {buttons}
+
+ );
+ }
+
+ const SwitchToAdvancedOrDetailSearch = () => {
+ let advancedOrDetail = searchStore.searchType == 'advanced' ? false : true;
+ let activeClass = advancedOrDetail == true ? ' active' : '';
+ return (
+ <>
+ searchStore.changeSearchType(e)}
+ id={`advanced-detail-switch-new`}
+ type="checkbox"
+ />
+
+ {searchStore.searchType.charAt(0).toUpperCase() + searchStore.searchType.slice(1)}
+
+
+ >
+ );
+ }
+
+ const renderDynamicRow = () => {
+ let dynamicRow = ( );
+
+ if (searchStore.advancedSearchValues.length > 1) {
+ let addedSelections = searchStore.advancedSearchValues.filter((val, idx) => idx > 0);
+
+ dynamicRow = addedSelections.map((_, idx) => {
+ let id = idx + 1;
+ return (
+
+ );
+ });
+ }
+
+ return dynamicRow;
+ };
+
+ return (
+ <>
+
+
+
+ {panelVars.searchTitle}
+
+
+
+
+
+
+
+
+
+ {showErrorMessage(searchStore)}
+ {
+ searchStore.searchType == 'advanced' ? (
+ <>
+
+ {renderDynamicRow()}
+ >
+ ) : (
+
+ )
+ }
+
+
+
+ searchStore.handleCancel()}>
+ Cancel
+
+ handleClear(searchStore)}>
+ Reset
+
+ handleSearch(searchStore, UIStore.getState())} style={{ marginRight: '20px' }} >
+ Search
+
+
+
+
+
+
+
+
+ {panelVars.resultTitle}
+
+
+
+
+
+ handleClear(searchStore)}
+ />
+
+
+
+ >
+ );
+}
+
+export default observer(TextSearch);
diff --git a/app/packs/src/components/staticDropdownOptions/options.js b/app/packs/src/components/staticDropdownOptions/options.js
index b380c5c469..b04062a97c 100644
--- a/app/packs/src/components/staticDropdownOptions/options.js
+++ b/app/packs/src/components/staticDropdownOptions/options.js
@@ -1,322 +1,424 @@
export const solventOptions = [{
- label: 'Acetic acid',
- value: 'Acetic acid'
- }, {
- label: 'Acetone',
- value: 'Acetone'
- }, {
- label: 'Acetonitrile',
- value: 'Acetonitrile'
- }, {
- label: 'Benzene',
- value: 'Benzene'
- }, {
- label: 'Butanol',
- value: 'Butanol'
- }, {
- label: 'Carbon tetrachloride (CCl4)',
- value: 'Carbon tetrachloride'
- }, {
- label: 'Chloroform',
- value: 'Chloroform'
- }, {
- label: 'Cyclohexane',
- value: 'Cyclohexane'
- }, {
- label: 'Diethyl ether',
- value: 'Diethyl ether'
- }, {
- label: 'Dimethyl sulfoxide (DMSO)',
- value: 'Dimethyl sulfoxide'
- }, {
- label: 'Dimethylformamide (DMF)',
- value: 'Dimethylformamide'
- }, {
- label: '1,4-Dioxane',
- value: '1,4-Dioxane'
- }, {
- label: 'Ethanol',
- value: 'Ethanol'
- }, {
- label: 'Ethyl acetate',
- value: 'Ethyl acetate'
- }, {
- label: 'Isopropanol',
- value: 'Isopropanol'
- }, {
- label: 'Methanol',
- value: 'Methanol'
- }, {
- label: 'Methylene chloride (DCM)',
- value: 'Methylene chloride'
- }, {
- label: 'Methyl tert-butyl ether (MTBE)',
- value: 'Methyl tert-butyl ether'
- }, {
- label: 'n-Hexane',
- value: 'n-Hexane'
- }, {
- label: 'N-Methyl-2-pyrrolidone (NMP)',
- value: 'N-Methyl-2-pyrrolidone'
- }, {
- label: 'Pentane',
- value: 'Pentane'
- }, {
- label: 'Pyridine',
- value: 'Pyridine'
- }, {
- label: 'Tetrahydrofuran (THF)',
- value: 'Tetrahydrofuran'
- }, {
- label: 'Toluene',
- value: 'Toluene'
- }, {
- label: 'Water',
- value: 'Water'
- }, {
- label: 'CDCl3',
- value: 'CDCl3'
- }, {
- label: 'MeOD-d4',
- value: 'MeOD-d4'
- }, {
- label: 'C6D6',
- value: 'C6D6'
- }, {
- label: 'D2O',
- value: 'D2O'
- }];
-
+ label: 'Acetic acid',
+ value: 'Acetic acid'
+}, {
+ label: 'Acetone',
+ value: 'Acetone'
+}, {
+ label: 'Acetonitrile',
+ value: 'Acetonitrile'
+}, {
+ label: 'Benzene',
+ value: 'Benzene'
+}, {
+ label: 'Butanol',
+ value: 'Butanol'
+}, {
+ label: 'Carbon tetrachloride (CCl4)',
+ value: 'Carbon tetrachloride'
+}, {
+ label: 'Chloroform',
+ value: 'Chloroform'
+}, {
+ label: 'Cyclohexane',
+ value: 'Cyclohexane'
+}, {
+ label: 'Diethyl ether',
+ value: 'Diethyl ether'
+}, {
+ label: 'Dimethyl sulfoxide (DMSO)',
+ value: 'Dimethyl sulfoxide'
+}, {
+ label: 'Dimethylformamide (DMF)',
+ value: 'Dimethylformamide'
+}, {
+ label: '1,4-Dioxane',
+ value: '1,4-Dioxane'
+}, {
+ label: 'Ethanol',
+ value: 'Ethanol'
+}, {
+ label: 'Ethyl acetate',
+ value: 'Ethyl acetate'
+}, {
+ label: 'Isopropanol',
+ value: 'Isopropanol'
+}, {
+ label: 'Methanol',
+ value: 'Methanol'
+}, {
+ label: 'Methylene chloride (DCM)',
+ value: 'Methylene chloride'
+}, {
+ label: 'Methyl tert-butyl ether (MTBE)',
+ value: 'Methyl tert-butyl ether'
+}, {
+ label: 'n-Hexane',
+ value: 'n-Hexane'
+}, {
+ label: 'N-Methyl-2-pyrrolidone (NMP)',
+ value: 'N-Methyl-2-pyrrolidone'
+}, {
+ label: 'Pentane',
+ value: 'Pentane'
+}, {
+ label: 'Pyridine',
+ value: 'Pyridine'
+}, {
+ label: 'Tetrahydrofuran (THF)',
+ value: 'Tetrahydrofuran'
+}, {
+ label: 'Toluene',
+ value: 'Toluene'
+}, {
+ label: 'Water',
+ value: 'Water'
+}, {
+ label: 'CDCl3',
+ value: 'CDCl3'
+}, {
+ label: 'MeOD-d4',
+ value: 'MeOD-d4'
+}, {
+ label: 'C6D6',
+ value: 'C6D6'
+}, {
+ label: 'D2O',
+ value: 'D2O'
+}];
export const defaultMultiSolventsSmilesOptions = [{
label: 'Acetic acid',
- value: { external_label: 'Acetic acid',
- smiles: 'CC(O)=O',
- density: 1.05 }
- }, {
+ value: {
+ external_label: 'Acetic acid',
+ smiles: 'CC(O)=O',
+ density: 1.05
+ }
+}, {
label: 'Acetone',
- value: { external_label: 'Acetone',
- smiles: 'CC(C)=O',
- density: 0.79 }
- }, {
+ value: {
+ external_label: 'Acetone',
+ smiles: 'CC(C)=O',
+ density: 0.79
+ }
+}, {
label: 'Acetonitrile',
- value: { external_label: 'Acetonitrile',
- smiles: 'CC#N',
- density: 0.78 }
- }, {
+ value: {
+ external_label: 'Acetonitrile',
+ smiles: 'CC#N',
+ density: 0.78
+ }
+}, {
label: 'Argon',
- value: { external_label: 'Ar',
- smiles: '[Ar]',
- density: 0.001633 }
- }, {
+ value: {
+ external_label: 'Ar',
+ smiles: '[Ar]',
+ density: 0.001633
+ }
+}, {
label: 'Benzene',
- value: { external_label: 'Benzene',
- smiles: 'C1=CC=CC=C1',
- density: 0.88 }
- }, {
+ value: {
+ external_label: 'Benzene',
+ smiles: 'C1=CC=CC=C1',
+ density: 0.88
+ }
+}, {
+ label: '2-Butanone',
+ value: {
+ external_label: '2-Butanone',
+ smiles: 'CCC(=O)C',
+ density: 0.805
+ }
+}, {
label: 'n-Butanol',
- value: { external_label: 'n-Butanol',
- smiles: 'CCCCO',
- density: 0.81 }
- }, {
+ value: {
+ external_label: 'n-Butanol',
+ smiles: 'CCCCO',
+ density: 0.81
+ }
+}, {
label: 'Carbon tetrachloride (CCl4)',
- value: { external_label: 'CCl4',
- smiles: 'ClC(Cl)(Cl)Cl',
- density: 1.594 }
- }, {
+ value: {
+ external_label: 'CCl4',
+ smiles: 'ClC(Cl)(Cl)Cl',
+ density: 1.594
+ }
+}, {
label: 'Chloroform',
- value: { external_label: 'Chloroform',
- smiles: 'ClC(Cl)Cl',
- density: 1.48 }
- }, {
+ value: {
+ external_label: 'Chloroform',
+ smiles: 'ClC(Cl)Cl',
+ density: 1.48
+ }
+}, {
label: 'Cyclohexane',
- value: { external_label: 'Cyclohexane',
- smiles: 'C1CCCCC1',
- density: 0.78 }
- }, {
+ value: {
+ external_label: 'Cyclohexane',
+ smiles: 'C1CCCCC1',
+ density: 0.78
+ }
+}, {
label: 'Diethyl ether',
- value: { external_label: 'Diethyl ether',
- smiles: 'CCOCC',
- density: 0.71 }
- }, {
+ value: {
+ external_label: 'Diethyl ether',
+ smiles: 'CCOCC',
+ density: 0.71
+ }
+}, {
label: 'Dimethyl sulfoxide (DMSO)',
- value: { external_label: 'DMSO',
- smiles: 'CS(C)=O',
- density: 1.10 }
- }, {
+ value: {
+ external_label: 'DMSO',
+ smiles: 'CS(C)=O',
+ density: 1.10
+ }
+}, {
label: 'Dimethylformamide (DMF)',
- value: { external_label: 'DMF',
- smiles: 'CN(C)C=O',
- density: 0.95 }
- }, {
+ value: {
+ external_label: 'DMF',
+ smiles: 'CN(C)C=O',
+ density: 0.95
+ }
+}, {
label: '1,4-Dioxane',
- value: { external_label: '1,4-Dioxane',
- smiles: 'C1COCCO1',
- density: 1.03 }
- }, {
+ value: {
+ external_label: '1,4-Dioxane',
+ smiles: 'C1COCCO1',
+ density: 1.03
+ }
+}, {
label: 'Ethanol',
- value: { external_label: 'Ethanol',
- smiles: 'OCC',
- density: 0.789 }
- }, {
+ value: {
+ external_label: 'Ethanol',
+ smiles: 'OCC',
+ density: 0.789
+ }
+}, {
label: 'Ethyl acetate',
- value: { external_label: 'Ethyl acetate',
- smiles: 'CC(OCC)=O',
- density: 0.894 }
- }, {
+ value: {
+ external_label: 'Ethyl acetate',
+ smiles: 'CC(OCC)=O',
+ density: 0.894
+ }
+}, {
label: 'Isopropanol',
- value: { external_label: 'Isopropanol',
- smiles: 'CC(O)C',
- density: 0.78 }
- }, {
+ value: {
+ external_label: 'Isopropanol',
+ smiles: 'CC(O)C',
+ density: 0.78
+ }
+}, {
label: 'Methanol',
- value: { external_label: 'Methanol',
- smiles: 'CO',
- density: 0.79 }
- }, {
+ value: {
+ external_label: 'Methanol',
+ smiles: 'CO',
+ density: 0.79
+ }
+}, {
label: 'Methylene chloride (DCM)',
- value: { external_label: 'DCM',
- smiles: 'ClCCl',
- density: 1.33 }
- }, {
+ value: {
+ external_label: 'DCM',
+ smiles: 'ClCCl',
+ density: 1.33
+ }
+}, {
label: 'Methyl tert-butyl ether (MTBE)',
- value: { external_label: 'MTBE',
- smiles: 'O(C(C)(C)C)C',
- density: 0.74 }
- }, {
+ value: {
+ external_label: 'MTBE',
+ smiles: 'O(C(C)(C)C)C',
+ density: 0.74
+ }
+}, {
label: 'N2',
- value: { external_label: 'N2',
- smiles: 'N#N',
- density: 0.00125 }
- }, {
+ value: {
+ external_label: 'N2',
+ smiles: 'N#N',
+ density: 0.00125
+ }
+}, {
label: 'n-Hexane',
- value: { external_label: 'n-Hexane',
- smiles: 'CCCCCC',
- density: 0.66 }
- }, {
+ value: {
+ external_label: 'n-Hexane',
+ smiles: 'CCCCCC',
+ density: 0.66
+ }
+}, {
label: 'N-Methyl-2-pyrrolidone (NMP)',
- value: { external_label: 'NMP',
- smiles: 'O=C1CCCN1C',
- density: 1.03 }
- }, {
+ value: {
+ external_label: 'NMP',
+ smiles: 'O=C1CCCN1C',
+ density: 1.03
+ }
+}, {
label: 'Pentane',
- value: { external_label: 'Pentane',
- smiles: 'CCCCC',
- density: 0.63 }
- }, {
+ value: {
+ external_label: 'Pentane',
+ smiles: 'CCCCC',
+ density: 0.63
+ }
+}, {
label: 'Pyridine',
- value: { external_label: 'Pyridine',
- smiles: 'C1=CC=NC=C1',
- density: 0.98 }
- }, {
+ value: {
+ external_label: 'Pyridine',
+ smiles: 'C1=CC=NC=C1',
+ density: 0.98
+ }
+}, {
+ label: 'Tetramethylethylenediamine (TMEDA)',
+ value: {
+ external_label: 'TMEDA',
+ smiles: 'CN(C)CCN(C)C',
+ density: 0.775
+ }
+}, {
label: 'Tetrahydrofuran (THF)',
- value: { external_label: 'THF',
- smiles: 'C1CCCO1',
- density: 0.889 }
- }, {
+ value: {
+ external_label: 'THF',
+ smiles: 'C1CCCO1',
+ density: 0.889
+ }
+}, {
label: 'Toluene',
- value: { external_label: 'Toluene',
- smiles: 'CC1=CC=CC=C1',
- density: 0.87 }
- }, {
+ value: {
+ external_label: 'Toluene',
+ smiles: 'CC1=CC=CC=C1',
+ density: 0.87
+ }
+}, {
label: 'Water',
- value: { external_label: 'Water',
- smiles: '[H]O[H]',
- density: 1.00 }
- }, {
+ value: {
+ external_label: 'Water',
+ smiles: '[H]O[H]',
+ density: 1.00
+ }
+}, {
label: 'CDCl3',
- value: { external_label: 'CDCl3',
- smiles: '[2H]C(Cl)(Cl)Cl',
- density: 1.500 }
- }, {
+ value: {
+ external_label: 'CDCl3',
+ smiles: '[2H]C(Cl)(Cl)Cl',
+ density: 1.500
+ }
+}, {
label: 'MeOD-d4',
- value: { external_label: 'MeOD-d4',
- smiles: '[2H]OC([2H])([2H])[2H]',
- density: 0.888 }
- }, {
+ value: {
+ external_label: 'MeOD-d4',
+ smiles: '[2H]OC([2H])([2H])[2H]',
+ density: 0.888
+ }
+}, {
label: 'C6D6',
- value: { external_label: 'C6D6',
- smiles: '[2H]c1c([2H])c([2H])c([2H])c([2H])c1[2H]',
- density: 0.950 }
- }, {
+ value: {
+ external_label: 'C6D6',
+ smiles: '[2H]c1c([2H])c([2H])c([2H])c([2H])c1[2H]',
+ density: 0.950
+ }
+}, {
label: 'D2O',
- value: { external_label: 'D2O',
- smiles: '[2H]O[2H]',
- density: 1.107 }
- }, {
- label: 'Cyclopentane',
- value: { external_label: 'Cyclopentane',
- smiles: 'C1CCCC1',
- density: 0.74 }
- }, {
- label: 'Nitromethane',
- value: { external_label: 'Nitromethane',
- smiles: 'C[N+]([O-])=O',
- density: 1.14 }
- }, {
- label: 'Formic acid',
- value: { external_label: 'Formic acid',
- smiles: 'O=CO',
- density: 1.22 }
- }, {
- label: 'n-octanol',
- value: { external_label: 'n-octanol',
- smiles: 'CCCCCCCCO',
- density: 0.817 }
- }, {
- label: 'n-propanol',
- value: { external_label: 'n-propanol',
- smiles: 'CCCO ',
- density: 0.8 }
- }, {
- label: 'Dimethylacetamide',
- value: { external_label: 'Dimethylacetamide',
- smiles: 'CC(N(C)C)=O',
- density: 0.94 }
- }, {
- label: '1,2-xylene',
- value: { external_label: '1,2-xylene',
- smiles: 'CC1=CC=CC=C1C',
- density: 0.8755 }
- }, {
- label: '1,3-xylene',
- value: { external_label: '1,3-xylene',
- smiles: 'CC1=CC=CC(C)=C1',
- density: 0.8598 }
- }, {
- label: '1,4-xylene',
- value: { external_label: '1,4-xylene',
- smiles: 'CC1=CC=C(C)C=C1',
- density: 0.8565 }
- }, {
- label: 'Sulfolane',
- value: { external_label: 'Sulfolane',
- smiles: 'O=S1(CCCC1)=O',
- density: 1.261 }
- }, {
- label: '2-methoxy ethanol',
- value: { external_label: '2-methoxy ethanol',
- smiles: 'OCCOC',
- density: 0.97 }
- }, {
- label: 'Carbon tribromide',
- value: { external_label: 'Carbon tribromide',
- smiles: 'BrC(Br)([H])Br',
- density: 2.89 }
- }, {
- label: 'Cyclopentylmethylether',
- value: { external_label: 'Cyclopentylmethylether',
- smiles: 'COC1CCCC1',
- density: 0.86 }
- }, {
- label: '1,2-Dichloroethane',
- value: { external_label: '1,2-Dichloroethane',
- smiles: 'ClCCCl',
- density: 1.25 }
+ value: {
+ external_label: 'D2O',
+ smiles: '[2H]O[2H]',
+ density: 1.107
+ }
+}, {
+ label: 'Cyclopentane',
+ value: {
+ external_label: 'Cyclopentane',
+ smiles: 'C1CCCC1',
+ density: 0.74
+ }
+}, {
+ label: 'Nitromethane',
+ value: {
+ external_label: 'Nitromethane',
+ smiles: 'C[N+]([O-])=O',
+ density: 1.14
+ }
+}, {
+ label: 'Formic acid',
+ value: {
+ external_label: 'Formic acid',
+ smiles: 'O=CO',
+ density: 1.22
+ }
+}, {
+ label: 'n-octanol',
+ value: {
+ external_label: 'n-octanol',
+ smiles: 'CCCCCCCCO',
+ density: 0.817
+ }
+}, {
+ label: 'n-propanol',
+ value: {
+ external_label: 'n-propanol',
+ smiles: 'CCCO',
+ density: 0.8
+ }
+}, {
+ label: 'Dimethylacetamide',
+ value: {
+ external_label: 'Dimethylacetamide',
+ smiles: 'CC(N(C)C)=O',
+ density: 0.94
+ }
+}, {
+ label: '1,2-xylene',
+ value: {
+ external_label: '1,2-xylene',
+ smiles: 'CC1=CC=CC=C1C',
+ density: 0.8755
+ }
+}, {
+ label: '1,3-xylene',
+ value: {
+ external_label: '1,3-xylene',
+ smiles: 'CC1=CC=CC(C)=C1',
+ density: 0.8598
+ }
+}, {
+ label: '1,4-xylene',
+ value: {
+ external_label: '1,4-xylene',
+ smiles: 'CC1=CC=C(C)C=C1',
+ density: 0.8565
}
+}, {
+ label: 'Sulfolane',
+ value: {
+ external_label: 'Sulfolane',
+ smiles: 'O=S1(CCCC1)=O',
+ density: 1.261
+ }
+}, {
+ label: '2-methoxy ethanol',
+ value: {
+ external_label: '2-methoxy ethanol',
+ smiles: 'OCCOC',
+ density: 0.97
+ }
+}, {
+ label: 'Carbon tribromide',
+ value: {
+ external_label: 'Carbon tribromide',
+ smiles: 'BrC(Br)([H])Br',
+ density: 2.89
+ }
+}, {
+ label: 'Cyclopentylmethylether',
+ value: {
+ external_label: 'Cyclopentylmethylether',
+ smiles: 'COC1CCCC1',
+ density: 0.86
+ }
+}, {
+ label: '1,2-Dichloroethane',
+ value: {
+ external_label: '1,2-Dichloroethane',
+ smiles: 'ClCCCl',
+ density: 1.25
+ }
+}
];
-
export const purificationOptions = [{
label: 'Flash-Chromatography',
value: 'Flash-Chromatography'
@@ -332,6 +434,12 @@ export const purificationOptions = [{
}, {
label: 'Distillation',
value: 'Distillation'
+}, {
+ label: 'Dialysis',
+ value: 'Dialysis'
+}, {
+ label: 'Filtration',
+ value: 'Filtration'
}, {
label: 'Sublimation',
value: 'Sublimation'
@@ -341,9 +449,6 @@ export const purificationOptions = [{
}, {
label: 'Recrystallisation',
value: 'Recrystallisation'
-}, {
- label: 'Dialysis',
- value: 'Dialysis'
}, {
label: 'Precipitation',
value: 'Precipitation'
@@ -369,7 +474,6 @@ export const statusOptions = [{
value: 'Not Successful',
}];
-
export const dangerousProductsOptions = [{
label: 'Causes cancer',
value: 'Causes cancer'
@@ -420,46 +524,44 @@ export const dangerousProductsOptions = [{
value: 'Diverse (Class 9)'
}];
-
-
export const confirmOptions = [{
- label: "Confirmed",
- value: "Confirmed"
-},{
- label: "Unconfirmed",
- value: "Unconfirmed"
+ label: 'Confirmed',
+ value: 'Confirmed'
+}, {
+ label: 'Unconfirmed',
+ value: 'Unconfirmed'
}];
export const kindOptions = [{
- label: "1H NMR",
- value: "1H NMR"
-},{
- label: "13C NMR",
- value: "13C NMR"
-},{
- label: "Mass",
- value: "Mass"
-},{
- label: "IR",
- value: "IR"
-},{
- label: "EA",
- value: "EA"
-},{
- label: "GCMS",
- value: "GCMS"
-},{
- label: "HPLC",
- value: "HPLC"
-},{
- label: "TLC",
- value: "TLC"
-},{
- label: "Crystal-Structure",
- value: "Crystal-Structure"
-},{
- label: "Others",
- value: "Others"
+ label: '1H NMR',
+ value: '1H NMR'
+}, {
+ label: '13C NMR',
+ value: '13C NMR'
+}, {
+ label: 'Mass',
+ value: 'Mass'
+}, {
+ label: 'IR',
+ value: 'IR'
+}, {
+ label: 'EA',
+ value: 'EA'
+}, {
+ label: 'GCMS',
+ value: 'GCMS'
+}, {
+ label: 'HPLC',
+ value: 'HPLC'
+}, {
+ label: 'TLC',
+ value: 'TLC'
+}, {
+ label: 'Crystal-Structure',
+ value: 'Crystal-Structure'
+}, {
+ label: 'Others',
+ value: 'Others'
}];
export const rolesOptions = [{
@@ -496,8 +598,63 @@ export const conditionsOptions = [{
value: 'pH = value'
}, {
label: 'pH < value',
- value: 'pH < value' /* < renders < in HTML*/
+ value: 'pH < value' /* < renders < in HTML */
}, {
label: 'pH > value',
- value: 'pH > value' /* > renders > in HTML*/
+ value: 'pH > value' /* > renders > in HTML */
}];
+
+export const temperatureOptions = [
+ { value: '°C', label: '°C' },
+ { value: '°F', label: '°F' },
+ { value: 'K', label: 'K' }
+];
+
+export const durationOptions = [
+ { value: 'Hour(s)', label: 'Hour(s)' },
+ { value: 'Minute(s)', label: 'Minute(s)' },
+ { value: 'Second(s)', label: 'Second(s)' },
+ { value: 'Week(s)', label: 'Week(s)' },
+ { value: 'Day(s)', label: 'Day(s)' },
+];
+
+export const stereoAbsOptions = [
+ { label: 'any', value: 'any' },
+ { label: 'rac', value: 'rac' },
+ { label: 'meso', value: 'meso' },
+ { label: 'delta', value: 'delta' },
+ { label: 'lambda', value: 'lambda' },
+ { label: '(S)', value: '(S)' },
+ { label: '(R)', value: '(R)' },
+ { label: '(Sp)', value: '(Sp)' },
+ { label: '(Rp)', value: '(Rp)' },
+ { label: '(Sa)', value: '(Sa)' },
+ { label: '(Ra)', value: '(Ra)' },
+];
+
+export const stereoRelOptions = [
+ { label: 'any', value: 'any' },
+ { label: 'syn', value: 'syn' },
+ { label: 'anti', value: 'anti' },
+ { label: 'p-geminal', value: 'p-geminal' },
+ { label: 'p-ortho', value: 'p-ortho' },
+ { label: 'p-meta', value: 'p-meta' },
+ { label: 'p-para', value: 'p-para' },
+ { label: 'cis', value: 'cis' },
+ { label: 'trans', value: 'trans' },
+ { label: 'fac', value: 'fac' },
+ { label: 'mer', value: 'mer' },
+];
+
+export const chemicalStatusOptions = [
+ { label: 'Available', value: 'Available' },
+ { label: 'Out of stock', value: 'Out of stock' },
+ { label: 'To be ordered', value: 'To be ordered' },
+ { label: 'Ordered', value: 'Ordered' },
+];
+
+export const amountSearchOptions = [
+ { label: 'g', value: 'g' },
+ { label: 'l', value: 'l' },
+ { label: 'mol', value: 'mol' },
+];
diff --git a/app/packs/src/components/staticDropdownOptions/reagents_kombi.js b/app/packs/src/components/staticDropdownOptions/reagents_kombi.js
index b52876e8e7..35a6b63ee5 100644
--- a/app/packs/src/components/staticDropdownOptions/reagents_kombi.js
+++ b/app/packs/src/components/staticDropdownOptions/reagents_kombi.js
@@ -1,546 +1,546 @@
export const reagents_kombi = {
- "ferrocene": '[CH-]1C=CC=C1.[CH-]1C=CC=C1.[Fe+2]',
+ ferrocene: '[CH-]1C=CC=C1.[CH-]1C=CC=C1.[Fe+2]',
"1,1'-Bis(diphenylphosphino)ferrocene": 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.[Fe+2]',
- "dppf": 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.[Fe+2]',
+ dppf: 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.[Fe+2]',
"[1,1'-Bis(diphenylphosphino)ferrocene]palladium(II) dichloride": 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.Cl[Pd]Cl.[Fe+2]',
- "Pd(dppf)Cl2": 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.Cl[Pd]Cl.[Fe+2]',
- "[1,1′-Bis(diphenylphosphino)ferrocene]dichloropalladium(II) complex with dichloromethane": 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.ClCCl.Cl[Pd]Cl.[Fe+2]',
- "(-)-10,2-Camphorsultam": 'CC1(C)C2(C3)CCC1CC2NS3(=O)=O',
- "(-)-10-Camphorsulfonic Acid": 'O=C(CC(C(C)1C)CC2)C21CS(=O)(O)=O',
+ 'Pd(dppf)Cl2': 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.Cl[Pd]Cl.[Fe+2]',
+ '[1,1′-Bis(diphenylphosphino)ferrocene]dichloropalladium(II) complex with dichloromethane': 'c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.c1ccc(cc1)P(c1ccccc1)C1=CC=C[CH-]1.ClCCl.Cl[Pd]Cl.[Fe+2]',
+ '(-)-10,2-Camphorsultam': 'CC1(C)C2(C3)CCC1CC2NS3(=O)=O',
+ '(-)-10-Camphorsulfonic Acid': 'O=C(CC(C(C)1C)CC2)C21CS(=O)(O)=O',
"(-)-2,2'-Methylenebis[(3aS,8aR)-3a,8a-dihydro-8H-indeno[1,2-d]oxazole]": '[H][C@@]12N=C(CC3=N[C@]4([H])[C@](CC5=C4C=CC=C5)([H])O3)O[C@]1([H])CC6=C2C=CC=C6',
- "(-)-4,5-Bis[hydroxy(diphenyl)methyl]-2,2-dimethyl-1,3-dioxolane": 'CC1(C)OC(C(C2=CC=CC=C2)(O)C3=CC=CC=C3)C(C(C4=CC=CC=C4)(O)C5=CC=CC=C5)O1',
- "(-)-B-Chlorodiisopinocampheylborane": 'CC1(C)C2CC(B(Cl)C3CC4CC(C3C)C4(C)C)C(C)C1C2',
- "(-)-Benzotetramisole": 'C12=N[C@@H](C3=CC=CC=C3)CN1C4=CC=CC=C4S2',
- "(-)-Isopinocampheylborane TMEDA Complex": 'B[C@H]1[C@H](C)C2C(C(C1)C2)(C)C.B[C@H]3[C@H](C)C4C(C(C3)C4)(C)C.CN(C)CCN(C)C',
- "(-)-Sparteine": '[H][C@]12CCCCN1C[C@H]3[C@]4([H])CCCCN4C[C@@H]2C3',
- "(+)-(5aR,10bS)-5a,10b-Dihydro-2-(2,4,6-trimethylphenyl)-4H,6H-indeno[2,1-b][1,2,4]triazolo[4,3-d][1,4]oxazinium Chloride Monohydrate": 'CC1=C(N2N=C3[N+]([C@]4([H])[C@](CC5=C4C=CC=C5)([H])OC3)=C2)C(C)=CC(C)=C1.[H]O[H].[Cl-]',
- "(+)-10,2-Camphorsultam": 'CC1(C)C2(C3)CCC1CC2NS3(=O)=O',
- "(+)-10-Camphorsulfonic Acid": 'O=C(CC(C(C)1C)CC2)C21CS(=O)(O)=O',
+ '(-)-4,5-Bis[hydroxy(diphenyl)methyl]-2,2-dimethyl-1,3-dioxolane': 'CC1(C)OC(C(C2=CC=CC=C2)(O)C3=CC=CC=C3)C(C(C4=CC=CC=C4)(O)C5=CC=CC=C5)O1',
+ '(-)-B-Chlorodiisopinocampheylborane': 'CC1(C)C2CC(B(Cl)C3CC4CC(C3C)C4(C)C)C(C)C1C2',
+ '(-)-Benzotetramisole': 'C12=N[C@@H](C3=CC=CC=C3)CN1C4=CC=CC=C4S2',
+ '(-)-Isopinocampheylborane TMEDA Complex': 'B[C@H]1[C@H](C)C2C(C(C1)C2)(C)C.B[C@H]3[C@H](C)C4C(C(C3)C4)(C)C.CN(C)CCN(C)C',
+ '(-)-Sparteine': '[H][C@]12CCCCN1C[C@H]3[C@]4([H])CCCCN4C[C@@H]2C3',
+ '(+)-(5aR,10bS)-5a,10b-Dihydro-2-(2,4,6-trimethylphenyl)-4H,6H-indeno[2,1-b][1,2,4]triazolo[4,3-d][1,4]oxazinium Chloride Monohydrate': 'CC1=C(N2N=C3[N+]([C@]4([H])[C@](CC5=C4C=CC=C5)([H])OC3)=C2)C(C)=CC(C)=C1.[H]O[H].[Cl-]',
+ '(+)-10,2-Camphorsultam': 'CC1(C)C2(C3)CCC1CC2NS3(=O)=O',
+ '(+)-10-Camphorsulfonic Acid': 'O=C(CC(C(C)1C)CC2)C21CS(=O)(O)=O',
"(+)-2,2'-Methylenebis[(3aR,8aS)-3a,8a-dihydro-8H-indeno[1,2-d]oxazole]": '[H][C@]12N=C(CC3=N[C@@]4([H])[C@@](CC5=C4C=CC=C5)([H])O3)O[C@@]1([H])CC6=C2C=CC=C6',
- "(+)-4,5-Bis[hydroxy(diphenyl)methyl]-2,2-dimethyl-1,3-dioxolane": 'CC1(C)OC(C(C2=CC=CC=C2)(O)C3=CC=CC=C3)C(C(C4=CC=CC=C4)(O)C5=CC=CC=C5)O1',
- "(+)-4,5-Bis[hydroxy(diphenyl)methyl]-2-methyl-2-phenyl-1,3-dioxolane": 'CC1(C2=CC=CC=C2)OC(C(C3=CC=CC=C3)(O)C4=CC=CC=C4)C(C(C5=CC=CC=C5)(O)C6=CC=CC=C6)O1',
- "(+)-B-Chlorodiisopinocampheylborane": 'CN(C)CCN(C)C.CC1(C)C2CC(BC3CC4CC(C3C)C4(C)C)C(C)C1C2',
- "(+)-Sparteine": '[H][C@]12CCCCN1C[C@H]3[C@]4([H])CCCCN4C[C@@H]2C3',
+ '(+)-4,5-Bis[hydroxy(diphenyl)methyl]-2,2-dimethyl-1,3-dioxolane': 'CC1(C)OC(C(C2=CC=CC=C2)(O)C3=CC=CC=C3)C(C(C4=CC=CC=C4)(O)C5=CC=CC=C5)O1',
+ '(+)-4,5-Bis[hydroxy(diphenyl)methyl]-2-methyl-2-phenyl-1,3-dioxolane': 'CC1(C2=CC=CC=C2)OC(C(C3=CC=CC=C3)(O)C4=CC=CC=C4)C(C(C5=CC=CC=C5)(O)C6=CC=CC=C6)O1',
+ '(+)-B-Chlorodiisopinocampheylborane': 'CN(C)CCN(C)C.CC1(C)C2CC(BC3CC4CC(C3C)C4(C)C)C(C)C1C2',
+ '(+)-Sparteine': '[H][C@]12CCCCN1C[C@H]3[C@]4([H])CCCCN4C[C@@H]2C3',
"(±)-1,1'-Binaphthyl-2,2'-diyl Hydrogenphosphate": 'O=P1(OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)O',
- "(±)-10-Camphorsulfonic Acid": 'O=C(CC(C(C)1C)CC2)C21CS(=O)(O)=O',
- "(1,10-Phenanthroline)(trifluoromethyl)(triphenylphosphine)copper(I)": '[Cu]C(F)(F)F.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.C45=CC=C6C=CC=NC6=C4N=CC=C5',
- "(1,5-Cyclooctadiene)(methoxy)iridium(I)": '[Ir]OC.C1=C\\CC/C=C\\CC/1',
- "(1,5-Cyclooctadiene)(pyridine)(tricyclohexylphosphine)iridium(I) Hexafluorophosphate": 'F[P-](F)(F)(F)(F)F.P(C1CCCCC1)(C2CCCCC2)C3CCCCC3.[Ir+].C4=C\\CC/C=C\\CC/4.C5=NC=CC=C5',
+ '(±)-10-Camphorsulfonic Acid': 'O=C(CC(C(C)1C)CC2)C21CS(=O)(O)=O',
+ '(1,10-Phenanthroline)(trifluoromethyl)(triphenylphosphine)copper(I)': '[Cu]C(F)(F)F.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.C45=CC=C6C=CC=NC6=C4N=CC=C5',
+ '(1,5-Cyclooctadiene)(methoxy)iridium(I)': '[Ir]OC.C1=C\\CC/C=C\\CC/1',
+ '(1,5-Cyclooctadiene)(pyridine)(tricyclohexylphosphine)iridium(I) Hexafluorophosphate': 'F[P-](F)(F)(F)(F)F.P(C1CCCCC1)(C2CCCCC2)C3CCCCC3.[Ir+].C4=C\\CC/C=C\\CC/4.C5=NC=CC=C5',
"(11bS)-2,6-Bis[bis[3,5-bis(trifluoromethyl)phenyl]hydroxymethyl]-3,5-dihydrospiro[4H-dinaphth[2,1-c:1',2'-e]azepine-4,4'-morpholinium] Bromide": 'OC(C1=C2C(C3=C4C=CC=CC4=CC(C(C5=CC(C(F)(F)F)=CC(C(F)(F)F)=C5)(C6=CC(C(F)(F)F)=CC(C(F)(F)F)=C6)O)=C3C(Br)[N]7(CCOCC7)C2)=C8C=CC=CC8=C1)(C9=CC(C(F)(F)F)=CC(C(F)(F)F)=C9)C%10=CC(C(F)(F)F)=CC(C(F)(F)F)=C%10',
- "(11R,12R)-9,10-Dihydro-9,10-ethanoanthracene-11,12-diamine": 'N[C@H]1[C@H](N)C2C3=C(C=CC=C3)C1C4=CC=CC=C24',
- "(11S,12S)-9,10-Dihydro-9,10-ethanoanthracene-11,12-diamine": 'N[C@@H]1[C@@H](N)C2C3=C(C=CC=C3)C1C4=CC=CC=C24',
- "(1-Bromovinyl)trimethylsilane": 'C[Si](C)(C(Br)=C)C',
- "(1E)-1-tert-Butoxy-1-(trimethylsilyloxy)propene": 'C/C=C(OC(C)(C)C)/O[Si](C)(C)C',
- "(1R,2R)-(-)-1,2-Cyclohexanediamine": 'N[C@H]1[C@H](N)CCCC1',
+ '(11R,12R)-9,10-Dihydro-9,10-ethanoanthracene-11,12-diamine': 'N[C@H]1[C@H](N)C2C3=C(C=CC=C3)C1C4=CC=CC=C24',
+ '(11S,12S)-9,10-Dihydro-9,10-ethanoanthracene-11,12-diamine': 'N[C@@H]1[C@@H](N)C2C3=C(C=CC=C3)C1C4=CC=CC=C24',
+ '(1-Bromovinyl)trimethylsilane': 'C[Si](C)(C(Br)=C)C',
+ '(1E)-1-tert-Butoxy-1-(trimethylsilyloxy)propene': 'C/C=C(OC(C)(C)C)/O[Si](C)(C)C',
+ '(1R,2R)-(-)-1,2-Cyclohexanediamine': 'N[C@H]1[C@H](N)CCCC1',
"(1R,2R)-(-)-N,N'-Dimethylcyclohexane-1,2-diamine": 'CN[C@H]1[C@H](NC)CCCC1',
- "(1R,2R)-(+)-1,2-Diphenylethylenediamine": 'N[C@H](C1=CC=CC=C1)[C@@H](C2=CC=CC=C2)N',
- "(1R,2R)-1,2-Bis(2,4,6-trimethylphenyl)ethylenediamine": 'N[C@H](C1=C(C)C=C(C)C=C1C)[C@@H](C2=C(C)C=C(C)C=C2C)N',
- "(1R,2R)-1,2-Bis(2-hydroxyphenyl)ethylenediamine": 'N[C@H](C1=CC=CC=C1O)[C@@H](C2=CC=CC=C2O)N',
+ '(1R,2R)-(+)-1,2-Diphenylethylenediamine': 'N[C@H](C1=CC=CC=C1)[C@@H](C2=CC=CC=C2)N',
+ '(1R,2R)-1,2-Bis(2,4,6-trimethylphenyl)ethylenediamine': 'N[C@H](C1=C(C)C=C(C)C=C1C)[C@@H](C2=C(C)C=C(C)C=C2C)N',
+ '(1R,2R)-1,2-Bis(2-hydroxyphenyl)ethylenediamine': 'N[C@H](C1=CC=CC=C1O)[C@@H](C2=CC=CC=C2O)N',
"(1R,2R)-N,N'-Bis(2-acetyl-3-oxo-2-butenylidene)-1,2-dimesitylethylenediaminato Cobalt(II)": 'CC1=C(C(C)=CC(C)=C1)[C@@H](/N=C/C=C(C(C)=O)\\C[O-])[C@@H](C2=C(C)C=C(C)C=C2C)/N=C/C=C(C(C)=O)\\C[O-].[Co+2]',
"(1R,2R)-N,N'-Bis[3-oxo-2-(2,4,6-trimethylbenzoyl)butylidene]-1,2-diphenylethylenediaminato Cobalt(II)": '[O-]/C(C)=C(C(C1=C(C)C=C(C)C=C1C)=O)\\C=N\\[C@@H]([C@@H](C2=CC=CC=C2)/N=C/C(C(C3=C(C)C=C(C)C=C3C)=O)=C(C)\\[O-])C4=CC=CC=C4.[Co+2]',
"(1R,2R)-N,N'-Dihydroxy-N,N'-bis(diphenylacetyl)cyclohexane-1,2-diamine": 'O=C(N(O)[C@H]1[C@H](N(O)C(C(C2=CC=CC=C2)C3=CC=CC=C3)=O)CCCC1)C(C4=CC=CC=C4)C5=CC=CC=C5',
- "(1R,2R,4R,5R)-2,5-Bis(3,5-di-tert-butyl-2-hydroxybenzylideneamino)bicyclo[2.2.1]heptane": 'OC1=C(C(C)(C)C)C=C(C(C)(C)C)C=C1/C=N/[C@H]2[C@@]3([H])C[C@@H](/N=C/C4=CC(C(C)(C)C)=CC(C(C)(C)C)=C4O)[C@@](C3)([H])C2',
- "(1R,2S)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenyl-1-propanol": 'C[C@H](N(CC1=CC=CC=C1)S(=O)(C(C(C)=CC(C)=C2)=C2C)=O)[C@@H](C3=CC=CC=C3)O',
- "(1R,2S)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Propionate": 'CCC(O[C@H](C1=CC=CC=C1)[C@@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
- "(1R,3R)-5-(Bromomethylene)-1,3-bis(tert-butyldimethylsilyloxy)cyclohexane": 'C[Si](O[C@H](C1)C[C@H](O[Si](C)(C(C)(C)C)C)CC1=CBr)(C(C)(C)C)C',
- "(1R,3S,5R,7R,8aS)-7-Ethylhexahydro-1-(6-hydroxy-4-quinolinyl)-3,7-methano-1H-pyrrolo[2,1-c][1,4]oxazine": 'OC1=CC=C2N=CC=C([C@H]3O[C@](C4)([H])C[N@@]5[C@@]3([H])C[C@@]4(CC)C5)C2=C1',
- "(1R,4R,5R)-4,7,7-Trimethyl-6-thiabicyclo[3.2.1]octane": 'CC1(C)S[C@@]2([H])[C@H](C)CC[C@]1([H])C2',
+ '(1R,2R,4R,5R)-2,5-Bis(3,5-di-tert-butyl-2-hydroxybenzylideneamino)bicyclo[2.2.1]heptane': 'OC1=C(C(C)(C)C)C=C(C(C)(C)C)C=C1/C=N/[C@H]2[C@@]3([H])C[C@@H](/N=C/C4=CC(C(C)(C)C)=CC(C(C)(C)C)=C4O)[C@@](C3)([H])C2',
+ '(1R,2S)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenyl-1-propanol': 'C[C@H](N(CC1=CC=CC=C1)S(=O)(C(C(C)=CC(C)=C2)=C2C)=O)[C@@H](C3=CC=CC=C3)O',
+ '(1R,2S)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Propionate': 'CCC(O[C@H](C1=CC=CC=C1)[C@@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
+ '(1R,3R)-5-(Bromomethylene)-1,3-bis(tert-butyldimethylsilyloxy)cyclohexane': 'C[Si](O[C@H](C1)C[C@H](O[Si](C)(C(C)(C)C)C)CC1=CBr)(C(C)(C)C)C',
+ '(1R,3S,5R,7R,8aS)-7-Ethylhexahydro-1-(6-hydroxy-4-quinolinyl)-3,7-methano-1H-pyrrolo[2,1-c][1,4]oxazine': 'OC1=CC=C2N=CC=C([C@H]3O[C@](C4)([H])C[N@@]5[C@@]3([H])C[C@@]4(CC)C5)C2=C1',
+ '(1R,4R,5R)-4,7,7-Trimethyl-6-thiabicyclo[3.2.1]octane': 'CC1(C)S[C@@]2([H])[C@H](C)CC[C@]1([H])C2',
"(1S)-3-(1,10-Phenanthrolin-2-yl)-2'-phenyl-[1,1'-binaphthalen]-2-ol": 'OC1=C(C2=NC3=C4N=CC=CC4=CC=C3C=C2)C=C5C=CC=CC5=C1C6=C7C=CC=CC7=CC=C6C8=CC=CC=C8',
- "(1S,2R)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenyl-1-propanol": 'C[C@@H](N(CC1=CC=CC=C1)S(=O)(C(C(C)=CC(C)=C2)=C2C)=O)[C@H](C3=CC=CC=C3)O',
- "(1S,2R)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Propionate": 'CCC(O[C@@H](C1=CC=CC=C1)[C@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
- "(1S,2S)-(-)-1,2-Diphenylethylenediamine": 'N[C@@H](C1=CC=CC=C1)[C@H](C2=CC=CC=C2)N',
- "(1S,2S)-(+)-1,2-Cyclohexanediamine": 'N[C@@H]1[C@@H](N)CCCC1',
+ '(1S,2R)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenyl-1-propanol': 'C[C@@H](N(CC1=CC=CC=C1)S(=O)(C(C(C)=CC(C)=C2)=C2C)=O)[C@H](C3=CC=CC=C3)O',
+ '(1S,2R)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Propionate': 'CCC(O[C@@H](C1=CC=CC=C1)[C@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
+ '(1S,2S)-(-)-1,2-Diphenylethylenediamine': 'N[C@@H](C1=CC=CC=C1)[C@H](C2=CC=CC=C2)N',
+ '(1S,2S)-(+)-1,2-Cyclohexanediamine': 'N[C@@H]1[C@@H](N)CCCC1',
"(1S,2S)-(+)-N,N'-Dimethylcyclohexane-1,2-diamine": 'CN[C@@H]1[C@@H](NC)CCCC1',
- "(1S,2S)-1,2-Bis(2,4,6-trimethylphenyl)ethylenediamine": 'N[C@@H](C1=C(C)C=C(C)C=C1C)[C@H](C2=C(C)C=C(C)C=C2C)N',
- "(1S,2S)-1,2-Bis(2-hydroxyphenyl)ethylenediamine": 'N[C@@H](C1=CC=CC=C1O)[C@H](C2=CC=CC=C2O)N',
+ '(1S,2S)-1,2-Bis(2,4,6-trimethylphenyl)ethylenediamine': 'N[C@@H](C1=C(C)C=C(C)C=C1C)[C@H](C2=C(C)C=C(C)C=C2C)N',
+ '(1S,2S)-1,2-Bis(2-hydroxyphenyl)ethylenediamine': 'N[C@@H](C1=CC=CC=C1O)[C@H](C2=CC=CC=C2O)N',
"(1S,2S)-N,N'-Bis(2-acetyl-3-oxo-2-butenylidene)-1,2-dimesitylethylenediaminato Cobalt(II)": 'CC1=C(C(C)=CC(C)=C1)[C@H](/N=C/C=C(C(C)=O)\\C[O-])[C@H](C2=C(C)C=C(C)C=C2C)/N=C/C=C(C(C)=O)\\C[O-].[Co+2]',
"(1S,2S)-N,N'-Bis[(R)-2-hydroxy-2'-phenyl-1,1'-binaphthyl-3-ylmethylene]-1,2-diphenylethylenediaminato Manganese(III) Acetate": 'CC([O-])=O.OC1=C(C([Mn+]2)=N[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N=C2C5=C(O)C(C6=C7C=CC=CC7=CC=C6C8=CC=CC=C8)=C9C=CC=CC9=C5)C=C%10C=CC=CC%10=C1C%11=C%12C=CC=CC%12=CC=C%11C%13=CC=CC=C%13',
"(1S,2S)-N,N'-Bis[3-oxo-2-(2,4,6-trimethylbenzoyl)butylidene]-1,2-diphenylethylenediaminato Cobalt(II)": '[O-]/C(C)=C(C(C1=C(C)C=C(C)C=C1C)=O)\\C=N\\[C@H]([C@H](C2=CC=CC=C2)/N=C/C(C(C3=C(C)C=C(C)C=C3C)=O)=C(C)\\[O-])C4=CC=CC=C4.[Co+2]',
"(1S,2S)-N,N'-Dihydroxy-N,N'-bis(diphenylacetyl)cyclohexane-1,2-diamine": 'O=C(N(O)[C@@H]1[C@@H](N(O)C(C(C2=CC=CC=C2)C3=CC=CC=C3)=O)CCCC1)C(C4=CC=CC=C4)C5=CC=CC=C5',
- "(1S,2S,4S,5S)-2,5-Bis(3,5-di-tert-butyl-2-hydroxybenzylideneamino)bicyclo[2.2.1]heptane": 'OC1=C(C(C)(C)C)C=C(C(C)(C)C)C=C1/C=N/[C@@H]2[C@]3([H])C[C@H](/N=C/C4=CC(C(C)(C)C)=CC(C(C)(C)C)=C4O)[C@](C3)([H])C2',
- "(1S,4S,5S)-4,7,7-Trimethyl-6-thiabicyclo[3.2.1]octane": 'CC1(C)S[C@]2([H])[C@@H](C)CC[C@@]1([H])C2',
- "(2,5-Dimethylphenyl)magnesium Bromide": 'Br[Mg]C1=CC(C)=CC=C1C',
- "(2-Bromo-4,5-dimethoxyphenoxy)trimethylsilane": 'C[Si](C)(OC1=CC(OC)=C(OC)C=C1Br)C',
- "(2-Bromoallyl)trimethylsilane": 'C[Si](C)(CC(Br)=C)C',
- "(2-Bromophenyl)(2,4,6-trimethylphenyl)iodonium triflate": 'CC1=C([I+]C2=CC=CC=C2Br)C(C)=CC(C)=C1.O=S([O-])(C(F)(F)F)=O',
- "(2-Bromophenyl)diphenylphosphine": 'BrC1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
- "(2-Bromophenylethynyl)trimethylsilane": 'C[Si](C)(C#CC1=CC=CC=C1Br)C',
- "(2R,3R)-(-)-1,4-Bis(diphenylphosphino)-2,3-O-isopropylidene-2,3-butanediol": 'CC1(O[C@H]([C@@H](O1)CP(C2=CC=CC=C2)C3=CC=CC=C3)CP(C4=CC=CC=C4)C5=CC=CC=C5)C',
- "(2R,3R)-(-)-2,3-Bis(diphenylphosphino)bicyclo[2.2.1]hept-5-ene": 'C1(C2)[C@@H](P(C3=CC=CC=C3)C4=CC=CC=C4)[C@H](P(C5=CC=CC=C5)C6=CC=CC=C6)C2C=C1',
- "(2R,5R)-2,5-Diphenylpyrrolidine": '[C@@H]1(C2=CC=CC=C2)N[C@@H](C3=CC=CC=C3)CC1',
- "(2R,8aS)-(+)-(Camphorylsulfonyl)oxaziridine": 'O=S(N1OC1)(CC23C(CC(C(C)3C)CC2)=O)=O',
- "(2S)-N-[(1S)-1-(Hydroxydiphenylmethyl)-3-methylbutyl]-2-pyrrolidinecarboxamide": 'O=C([C@H]1NCCC1)N[C@H](C(C2=CC=CC=C2)(O)C3=CC=CC=C3)CC(C)C',
- "(2S,3aS,7aS)-Octahydro-1H-indole-2-carboxylic Acid": 'O=C([C@H]1N[C@@]2([H])CCCC[C@@]2([H])C1)O',
- "(2S,3R)-3,4-Dihydro-3-isopropyl-2-phenyl-2H-pyrimido[2,1-b]benzothiazole": 'CC([C@H]1[C@@H](C2=CC=CC=C2)N=C3SC4=CC=CC=C4N3C1)C',
- "(2S,3S)-(-)-Bis(diphenylphosphino)butane": 'C[C@H](P(C1=CC=CC=C1)C2=CC=CC=C2)[C@@H](P(C3=CC=CC=C3)C4=CC=CC=C4)C',
- "(2S,3S)-(+)-1,4-Bis(diphenylphosphino)-2,3-O-isopropylidene-2,3-butanediol": 'CC1(O[C@@H]([C@H](O1)CP(C2=CC=CC=C2)C3=CC=CC=C3)CP(C4=CC=CC=C4)C5=CC=CC=C5)C',
- "(2S,3S)-(+)-2,3-Bis(diphenylphosphino)bicyclo[2.2.1]hept-5-ene": 'C1(C2)[C@H](P(C3=CC=CC=C3)C4=CC=CC=C4)[C@@H](P(C5=CC=CC=C5)C6=CC=CC=C6)C2C=C1',
- "(2S,5S)-(-)-2-tert-Butyl-3-methyl-5-benzyl-4-imidazolidinone": 'O=C1N(C)[C@@H](C(C)(C)C)N[C@H]1CC2=CC=CC=C2',
- "(2S,5S)-2,5-Diphenylpyrrolidine": '[C@H]1(C2=CC=CC=C2)N[C@H](C3=CC=CC=C3)CC1',
- "(2S,8aR)-(-)-(Camphorylsulfonyl)oxaziridine": 'O=S(N1OC1)(CC23C(CC(C(C)3C)CC2)=O)=O',
- "(3,5-Dibromophenyl)triphenylsilane": 'BrC1=CC(Br)=CC([Si](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=C1',
- "(3-Bromopropoxy)(tert-butyl)dimethylsilane": 'C[Si](C(C)(C)C)(OCCCBr)C',
- "(3-Bromopropyl)trimethoxysilane": 'CO[Si](OC)(CCCBr)OC',
- "(3-Chloropropyl)tris(trimethylsilyloxy)silane": 'C[Si](O[Si](O[Si](C)(C)C)(CCCCl)O[Si](C)(C)C)(C)C',
- "(3-Mercaptopropyl)triethoxysilane": 'CCO[Si](OCC)(CCCS)OCC',
- "(3-Mercaptopropyl)trimethoxysilane": 'CO[Si](OC)(CCCS)OC',
- "(3-Phenyl-1H-inden-1-ylidene)bis(tricyclohexylphosphine)ruthenium(II) Dichloride": '[Ru+2]=C1C=C(C2=CC=CC=C2)C3=C1C=CC=C3.P(C4CCCCC4)(C5CCCCC5)C6CCCCC6.P(C7CCCCC7)(C8CCCCC8)C9CCCCC9.[Cl-].[Cl-]',
- "(4-(Isopropoxycarbonyl)phenyl)boronic acid": 'B(C1=CC=C(C=C1)C(=O)OC(C)C)(O)O',
- "(4-Dimethylaminophenyl)di-tert-butylphosphine": 'CC(P(C1=CC=C(N(C)C)C=C1)C(C)(C)C)(C)C',
- "(4-Nitrophenyl)(2,4,6-trimethylphenyl)iodonium triflate": 'CC1=C([I+]C2=CC=C([N+]([O-])=O)C=C2)C(C)=CC(C)=C1.O=S([O-])(C(F)(F)F)=O',
- "(4-Nitrophenyl)phenyliodonium triflate": 'O=[N+](C1=CC=C([I+]C2=CC=CC=C2)C=C1)[O-].O=S([O-])(C(F)(F)F)=O',
- "(4R)-(+)-4-Isopropyl-5,5-diphenyl-2-oxazolidinone": 'O=C1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@@H](C(C)C)N1',
- "(4R,5R)-1,3-Dimethyl-4,5-diphenyl-2-[(S)-1-benzyl-2-hydroxyethylimino]imidazolidine": 'OC[C@H](CC1=CC=CC=C1)N=C2N(C)[C@H](C3=CC=CC=C3)[C@@H](C4=CC=CC=C4)N2C',
- "(4S)-(-)-4-Isopropyl-5,5-diphenyl-2-oxazolidinone": 'O=C1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@H](C(C)C)N1',
+ '(1S,2S,4S,5S)-2,5-Bis(3,5-di-tert-butyl-2-hydroxybenzylideneamino)bicyclo[2.2.1]heptane': 'OC1=C(C(C)(C)C)C=C(C(C)(C)C)C=C1/C=N/[C@@H]2[C@]3([H])C[C@H](/N=C/C4=CC(C(C)(C)C)=CC(C(C)(C)C)=C4O)[C@](C3)([H])C2',
+ '(1S,4S,5S)-4,7,7-Trimethyl-6-thiabicyclo[3.2.1]octane': 'CC1(C)S[C@]2([H])[C@@H](C)CC[C@@]1([H])C2',
+ '(2,5-Dimethylphenyl)magnesium Bromide': 'Br[Mg]C1=CC(C)=CC=C1C',
+ '(2-Bromo-4,5-dimethoxyphenoxy)trimethylsilane': 'C[Si](C)(OC1=CC(OC)=C(OC)C=C1Br)C',
+ '(2-Bromoallyl)trimethylsilane': 'C[Si](C)(CC(Br)=C)C',
+ '(2-Bromophenyl)(2,4,6-trimethylphenyl)iodonium triflate': 'CC1=C([I+]C2=CC=CC=C2Br)C(C)=CC(C)=C1.O=S([O-])(C(F)(F)F)=O',
+ '(2-Bromophenyl)diphenylphosphine': 'BrC1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
+ '(2-Bromophenylethynyl)trimethylsilane': 'C[Si](C)(C#CC1=CC=CC=C1Br)C',
+ '(2R,3R)-(-)-1,4-Bis(diphenylphosphino)-2,3-O-isopropylidene-2,3-butanediol': 'CC1(O[C@H]([C@@H](O1)CP(C2=CC=CC=C2)C3=CC=CC=C3)CP(C4=CC=CC=C4)C5=CC=CC=C5)C',
+ '(2R,3R)-(-)-2,3-Bis(diphenylphosphino)bicyclo[2.2.1]hept-5-ene': 'C1(C2)[C@@H](P(C3=CC=CC=C3)C4=CC=CC=C4)[C@H](P(C5=CC=CC=C5)C6=CC=CC=C6)C2C=C1',
+ '(2R,5R)-2,5-Diphenylpyrrolidine': '[C@@H]1(C2=CC=CC=C2)N[C@@H](C3=CC=CC=C3)CC1',
+ '(2R,8aS)-(+)-(Camphorylsulfonyl)oxaziridine': 'O=S(N1OC1)(CC23C(CC(C(C)3C)CC2)=O)=O',
+ '(2S)-N-[(1S)-1-(Hydroxydiphenylmethyl)-3-methylbutyl]-2-pyrrolidinecarboxamide': 'O=C([C@H]1NCCC1)N[C@H](C(C2=CC=CC=C2)(O)C3=CC=CC=C3)CC(C)C',
+ '(2S,3aS,7aS)-Octahydro-1H-indole-2-carboxylic Acid': 'O=C([C@H]1N[C@@]2([H])CCCC[C@@]2([H])C1)O',
+ '(2S,3R)-3,4-Dihydro-3-isopropyl-2-phenyl-2H-pyrimido[2,1-b]benzothiazole': 'CC([C@H]1[C@@H](C2=CC=CC=C2)N=C3SC4=CC=CC=C4N3C1)C',
+ '(2S,3S)-(-)-Bis(diphenylphosphino)butane': 'C[C@H](P(C1=CC=CC=C1)C2=CC=CC=C2)[C@@H](P(C3=CC=CC=C3)C4=CC=CC=C4)C',
+ '(2S,3S)-(+)-1,4-Bis(diphenylphosphino)-2,3-O-isopropylidene-2,3-butanediol': 'CC1(O[C@@H]([C@H](O1)CP(C2=CC=CC=C2)C3=CC=CC=C3)CP(C4=CC=CC=C4)C5=CC=CC=C5)C',
+ '(2S,3S)-(+)-2,3-Bis(diphenylphosphino)bicyclo[2.2.1]hept-5-ene': 'C1(C2)[C@H](P(C3=CC=CC=C3)C4=CC=CC=C4)[C@@H](P(C5=CC=CC=C5)C6=CC=CC=C6)C2C=C1',
+ '(2S,5S)-(-)-2-tert-Butyl-3-methyl-5-benzyl-4-imidazolidinone': 'O=C1N(C)[C@@H](C(C)(C)C)N[C@H]1CC2=CC=CC=C2',
+ '(2S,5S)-2,5-Diphenylpyrrolidine': '[C@H]1(C2=CC=CC=C2)N[C@H](C3=CC=CC=C3)CC1',
+ '(2S,8aR)-(-)-(Camphorylsulfonyl)oxaziridine': 'O=S(N1OC1)(CC23C(CC(C(C)3C)CC2)=O)=O',
+ '(3,5-Dibromophenyl)triphenylsilane': 'BrC1=CC(Br)=CC([Si](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=C1',
+ '(3-Bromopropoxy)(tert-butyl)dimethylsilane': 'C[Si](C(C)(C)C)(OCCCBr)C',
+ '(3-Bromopropyl)trimethoxysilane': 'CO[Si](OC)(CCCBr)OC',
+ '(3-Chloropropyl)tris(trimethylsilyloxy)silane': 'C[Si](O[Si](O[Si](C)(C)C)(CCCCl)O[Si](C)(C)C)(C)C',
+ '(3-Mercaptopropyl)triethoxysilane': 'CCO[Si](OCC)(CCCS)OCC',
+ '(3-Mercaptopropyl)trimethoxysilane': 'CO[Si](OC)(CCCS)OC',
+ '(3-Phenyl-1H-inden-1-ylidene)bis(tricyclohexylphosphine)ruthenium(II) Dichloride': '[Ru+2]=C1C=C(C2=CC=CC=C2)C3=C1C=CC=C3.P(C4CCCCC4)(C5CCCCC5)C6CCCCC6.P(C7CCCCC7)(C8CCCCC8)C9CCCCC9.[Cl-].[Cl-]',
+ '(4-(Isopropoxycarbonyl)phenyl)boronic acid': 'B(C1=CC=C(C=C1)C(=O)OC(C)C)(O)O',
+ '(4-Dimethylaminophenyl)di-tert-butylphosphine': 'CC(P(C1=CC=C(N(C)C)C=C1)C(C)(C)C)(C)C',
+ '(4-Nitrophenyl)(2,4,6-trimethylphenyl)iodonium triflate': 'CC1=C([I+]C2=CC=C([N+]([O-])=O)C=C2)C(C)=CC(C)=C1.O=S([O-])(C(F)(F)F)=O',
+ '(4-Nitrophenyl)phenyliodonium triflate': 'O=[N+](C1=CC=C([I+]C2=CC=CC=C2)C=C1)[O-].O=S([O-])(C(F)(F)F)=O',
+ '(4R)-(+)-4-Isopropyl-5,5-diphenyl-2-oxazolidinone': 'O=C1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@@H](C(C)C)N1',
+ '(4R,5R)-1,3-Dimethyl-4,5-diphenyl-2-[(S)-1-benzyl-2-hydroxyethylimino]imidazolidine': 'OC[C@H](CC1=CC=CC=C1)N=C2N(C)[C@H](C3=CC=CC=C3)[C@@H](C4=CC=CC=C4)N2C',
+ '(4S)-(-)-4-Isopropyl-5,5-diphenyl-2-oxazolidinone': 'O=C1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@H](C(C)C)N1',
"(4S,4'S)-2,2'-(Pentane-3,3'-diyl)bis(4-benzyl-4,5-dihydrooxazole)": 'CCC(C1=N[C@H](CO1)CC2=CC=CC=C2)(C3=N[C@H](CO3)CC4=CC=CC=C4)CC',
- "(4S,5S)-1,3-Dimethyl-4,5-diphenyl-2-[(R)-1-benzyl-2-hydroxyethylimino]imidazolidine": 'OC[C@@H](CC1=CC=CC=C1)N=C2N(C)[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N2C',
- "(6-Chloro-1H-benzotriazol-1-yloxy)tripyrrolidinophosphonium Hexafluorophosphate": 'ClC1=CC=C2N=NN(O[P+](N3CCCC3)(N4CCCC4)N5CCCC5)C2=C1.F[P-](F)(F)(F)(F)F',
- "(7-Azabenzotriazol-1-yloxy)tris(dimethylamino)phosphonium Hexafluorophosphate": 'CN([P+](N(C)C)(ON1N=NC2=CC=CN=C21)N(C)C)C.F[P-](F)(F)(F)(F)F',
- "(Bromodifluoromethyl)trimethylsilane": 'C[Si](C)(C(F)(Br)F)C',
- "(Bromomethyl)trimethylsilane": 'C[Si](C)(CBr)C',
- "(Chloromethyl)isopropoxydimethylsilane": 'C[Si](OC(C)C)(CCl)C',
- "(Chloromethyl)trimethylsilane": 'C[Si](C)(CCl)C',
- "(Diacetoxyiodo)benzene": 'O=C(OI(C1=CC=CC=C1)OC(C)=O)C',
- "(Diethylamino)sulfur Trifluoride": 'CCN(S(F)(F)F)CC',
- "(Difluoromethyl)trimethylsilane": 'C[Si](C)(C(F)F)C',
- "(E)-Trimethyl(3,3,3-trifluoro-1-propenyl)silane": 'FC(F)(F)/C=C/[Si](C)(C)C',
- "(Hexamethylbenzene)ruthenium(II) Dichloride": 'CC1=C(C)C(C)=C(C)C(C)=C1C.[Ru+2].[Cl-].[Cl-]',
- "(Indenyl)titanium(IV) Trichloride": '[Ti+3]C1C=CC2=C1C=CC=C2.[Cl-].[Cl-].[Cl-]',
- "(Iodomethyl)trimethylsilane": 'C[Si](C)(CI)C',
+ '(4S,5S)-1,3-Dimethyl-4,5-diphenyl-2-[(R)-1-benzyl-2-hydroxyethylimino]imidazolidine': 'OC[C@@H](CC1=CC=CC=C1)N=C2N(C)[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N2C',
+ '(6-Chloro-1H-benzotriazol-1-yloxy)tripyrrolidinophosphonium Hexafluorophosphate': 'ClC1=CC=C2N=NN(O[P+](N3CCCC3)(N4CCCC4)N5CCCC5)C2=C1.F[P-](F)(F)(F)(F)F',
+ '(7-Azabenzotriazol-1-yloxy)tris(dimethylamino)phosphonium Hexafluorophosphate': 'CN([P+](N(C)C)(ON1N=NC2=CC=CN=C21)N(C)C)C.F[P-](F)(F)(F)(F)F',
+ '(Bromodifluoromethyl)trimethylsilane': 'C[Si](C)(C(F)(Br)F)C',
+ '(Bromomethyl)trimethylsilane': 'C[Si](C)(CBr)C',
+ '(Chloromethyl)isopropoxydimethylsilane': 'C[Si](OC(C)C)(CCl)C',
+ '(Chloromethyl)trimethylsilane': 'C[Si](C)(CCl)C',
+ '(Diacetoxyiodo)benzene': 'O=C(OI(C1=CC=CC=C1)OC(C)=O)C',
+ '(Diethylamino)sulfur Trifluoride': 'CCN(S(F)(F)F)CC',
+ '(Difluoromethyl)trimethylsilane': 'C[Si](C)(C(F)F)C',
+ '(E)-Trimethyl(3,3,3-trifluoro-1-propenyl)silane': 'FC(F)(F)/C=C/[Si](C)(C)C',
+ '(Hexamethylbenzene)ruthenium(II) Dichloride': 'CC1=C(C)C(C)=C(C)C(C)=C1C.[Ru+2].[Cl-].[Cl-]',
+ '(Indenyl)titanium(IV) Trichloride': '[Ti+3]C1C=CC2=C1C=CC=C2.[Cl-].[Cl-].[Cl-]',
+ '(Iodomethyl)trimethylsilane': 'C[Si](C)(CI)C',
"(m-Terphenyl-5'-yl)trimethylsilane": 'C[Si](C)(C1=CC(C2=CC=CC=C2)=CC(C3=CC=CC=C3)=C1)C',
- "(Pentafluorophenyl)diphenylphosphine": 'FC1=C(F)C(F)=C(F)C(F)=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
- "(Pentamethylcyclopentadienyl)rhodium(III) Dichloride": '[Rh+2]C1=C(C)C(C)=C(C)C1(C)C.[Cl-].[Cl-]',
- "(Pentamethylcyclopentadienyl)titanium(IV) Trichloride": '[Ti+3]C1=C(C)C(C)=C(C)C1(C)C.[Cl-].[Cl-].[Cl-]',
- "(Perfluorohexyl)phenyliodonium Trifluoromethanesulfonate": 'FC([I+]C1=CC=CC=C1)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F.O=S(C(F)(F)F)([O-])=O',
- "(Perfluoro-n-octyl)phenyliodonium Trifluoromethanesulfonate": 'FC([I+]C1=CC=CC=C1)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F.O=S(C(F)(F)F)([O-])=O',
- "(Perfluoropropyl)phenyliodonium Trifluoromethanesulfonate": 'FC([I+]C1=CC=CC=C1)(F)C(F)(F)C(F)(F)F.O=S(C(F)(F)F)([O-])=O',
- "(Phenylthio)trimethylsilane": 'C[Si](C)(SC1=CC=CC=C1)C',
- "(Phenylthiomethyl)trimethylsilane": 'C[Si](C)(CSC1=CC=CC=C1)C',
- "(Piperidinium-1-ylmethyl)trifluoroborate": 'F[B-2](F)(C[NH+]1CCCCC1)F',
- "(R)-(-)-1-(2-Pyrrolidinylmethyl)pyrrolidine": 'N1(C[C@@H]2NCCC2)CCCC1',
- "(R)-(-)-2-[Hydroxy(diphenyl)methyl]-1-methylpyrrolidine": 'CN1[C@@H](C(C2=CC=CC=C2)(O)C3=CC=CC=C3)CCC1',
- "(R)-(-)-4-Benzyl-3-propionyl-2-oxazolidinone": 'O=C1OC[C@@H](CC2=CC=CC=C2)N1C(CC)=O',
- "(R)-(-)-4-Isopropyl-3-propionyl-2-oxazolidinone": 'O=C1OC[C@@H](C(C)C)N1C(CC)=O',
- "(R)-(-)-4-Phenyl-2-oxazolidinone": 'O=C1OC[C@@H](C2=CC=CC=C2)N1',
- "(R)-(-)-p-Toluenesulfinamide": 'CC1=CC=C([S@](N)=O)C=C1',
+ '(Pentafluorophenyl)diphenylphosphine': 'FC1=C(F)C(F)=C(F)C(F)=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
+ '(Pentamethylcyclopentadienyl)rhodium(III) Dichloride': '[Rh+2]C1=C(C)C(C)=C(C)C1(C)C.[Cl-].[Cl-]',
+ '(Pentamethylcyclopentadienyl)titanium(IV) Trichloride': '[Ti+3]C1=C(C)C(C)=C(C)C1(C)C.[Cl-].[Cl-].[Cl-]',
+ '(Perfluorohexyl)phenyliodonium Trifluoromethanesulfonate': 'FC([I+]C1=CC=CC=C1)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F.O=S(C(F)(F)F)([O-])=O',
+ '(Perfluoro-n-octyl)phenyliodonium Trifluoromethanesulfonate': 'FC([I+]C1=CC=CC=C1)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F.O=S(C(F)(F)F)([O-])=O',
+ '(Perfluoropropyl)phenyliodonium Trifluoromethanesulfonate': 'FC([I+]C1=CC=CC=C1)(F)C(F)(F)C(F)(F)F.O=S(C(F)(F)F)([O-])=O',
+ '(Phenylthio)trimethylsilane': 'C[Si](C)(SC1=CC=CC=C1)C',
+ '(Phenylthiomethyl)trimethylsilane': 'C[Si](C)(CSC1=CC=CC=C1)C',
+ '(Piperidinium-1-ylmethyl)trifluoroborate': 'F[B-2](F)(C[NH+]1CCCCC1)F',
+ '(R)-(-)-1-(2-Pyrrolidinylmethyl)pyrrolidine': 'N1(C[C@@H]2NCCC2)CCCC1',
+ '(R)-(-)-2-[Hydroxy(diphenyl)methyl]-1-methylpyrrolidine': 'CN1[C@@H](C(C2=CC=CC=C2)(O)C3=CC=CC=C3)CCC1',
+ '(R)-(-)-4-Benzyl-3-propionyl-2-oxazolidinone': 'O=C1OC[C@@H](CC2=CC=CC=C2)N1C(CC)=O',
+ '(R)-(-)-4-Isopropyl-3-propionyl-2-oxazolidinone': 'O=C1OC[C@@H](C(C)C)N1C(CC)=O',
+ '(R)-(-)-4-Phenyl-2-oxazolidinone': 'O=C1OC[C@@H](C2=CC=CC=C2)N1',
+ '(R)-(-)-p-Toluenesulfinamide': 'CC1=CC=C([S@](N)=O)C=C1',
"(R)-(+)-2,2'-bis(diphenylphosphino)-1,1'-binaphthyl": 'C1(C2=C3C=CC=CC3=CC=C2P(C4=CC=CC=C4)C5=CC=CC=C5)=C6C=CC=CC6=CC=C1P(C7=CC=CC=C7)C8=CC=CC=C8',
"(R)-(+)-2-Diphenylphosphino-2'-methoxy-1,1'-binaphthyl": 'COC1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3P(C5=CC=CC=C5)C6=CC=CC=C6',
- "(R)-(+)-Indoline-2-carboxylic Acid": 'O=C([C@@H]1NC2=C(C=CC=C2)C1)O',
- "(R)-(+)-N,N-Dimethyl-1-ferrocenylethylamine": 'C[C@H]([C]1[CH][CH][CH][CH]1)N(C)C.[Fe].[CH]2[CH][CH][CH][CH]2',
- "(R)-(+)-tert-Butylsulfinamide": 'CC(C)([S@](N)=O)C',
- "(R)-(+)-α,α-Diphenyl-2-pyrrolidinemethanol": 'OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@@H]3NCCC3',
- "(R)-(+)-α,α-Diphenyl-2-pyrrolidinemethanol Trimethylsilyl Ether": 'C[Si](OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@@H]3NCCC3)(C)C',
- "(R)-2-(Methoxymethyl)pyrrolidine": 'COC[C@@H]1NCCC1',
+ '(R)-(+)-Indoline-2-carboxylic Acid': 'O=C([C@@H]1NC2=C(C=CC=C2)C1)O',
+ '(R)-(+)-N,N-Dimethyl-1-ferrocenylethylamine': 'C[C@H]([C]1[CH][CH][CH][CH]1)N(C)C.[Fe].[CH]2[CH][CH][CH][CH]2',
+ '(R)-(+)-tert-Butylsulfinamide': 'CC(C)([S@](N)=O)C',
+ '(R)-(+)-α,α-Diphenyl-2-pyrrolidinemethanol': 'OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@@H]3NCCC3',
+ '(R)-(+)-α,α-Diphenyl-2-pyrrolidinemethanol Trimethylsilyl Ether': 'C[Si](OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@@H]3NCCC3)(C)C',
+ '(R)-2-(Methoxymethyl)pyrrolidine': 'COC[C@@H]1NCCC1',
"(R)-3,3'-Bis[[[(1R,2R)-2-(isoindolin-2-yl)-1,2-diphenylethyl]imino]methyl]-1,1'-bi-2-naphthol": 'OC1=C(/C=N/[C@H](C2=CC=CC=C2)[C@H](N3CC4=C(C=CC=C4)C3)C5=CC=CC=C5)C=C6C=CC=CC6=C1C7=C8C=CC=CC8=CC(/C=N/[C@H](C9=CC=CC=C9)[C@H](N%10CC%11=C(C=CC=C%11)C%10)C%12=CC=CC=C%12)=C7O',
- "(R)-4-Benzyl-2-oxazolidinone": 'O=C1OC[C@@H](CC2=CC=CC=C2)N1',
- "(R)-4-Isopropyl-2-oxazolidinone": 'O=C1OC[C@@H](C(C)C)N1',
- "(R)-4-Phenylthiazolidine-2-thione": 'S=C1SC[C@@H](C2=CC=CC=C2)N1',
- "(R)-5,5-Diphenyl-2-methyl-3,4-propano-1,3,2-oxazaborolidine": 'CB1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@]4([H])N1CCC4',
- "(R)-N-(2-Benzoylphenyl)-1-benzylpyrrolidine-2-carboxamide": 'O=C([C@@H]1N(CC2=CC=CC=C2)CCC1)NC3=CC=CC=C3C(C4=CC=CC=C4)=O',
- "(R,R)-(-)-2,3-Bis(tert-butylmethylphosphino)quinoxaline": 'C[P@@](C1=NC2=CC=CC=C2N=C1[P@@](C(C)(C)C)C)C(C)(C)C',
- "(R,R)-(-)-2,3-Dimethoxy-1,4-bis(dimethylamino)butane": 'CN(C[C@@H](OC)[C@H](OC)CN(C)C)C',
+ '(R)-4-Benzyl-2-oxazolidinone': 'O=C1OC[C@@H](CC2=CC=CC=C2)N1',
+ '(R)-4-Isopropyl-2-oxazolidinone': 'O=C1OC[C@@H](C(C)C)N1',
+ '(R)-4-Phenylthiazolidine-2-thione': 'S=C1SC[C@@H](C2=CC=CC=C2)N1',
+ '(R)-5,5-Diphenyl-2-methyl-3,4-propano-1,3,2-oxazaborolidine': 'CB1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@]4([H])N1CCC4',
+ '(R)-N-(2-Benzoylphenyl)-1-benzylpyrrolidine-2-carboxamide': 'O=C([C@@H]1N(CC2=CC=CC=C2)CCC1)NC3=CC=CC=C3C(C4=CC=CC=C4)=O',
+ '(R,R)-(-)-2,3-Bis(tert-butylmethylphosphino)quinoxaline': 'C[P@@](C1=NC2=CC=CC=C2N=C1[P@@](C(C)(C)C)C)C(C)(C)C',
+ '(R,R)-(-)-2,3-Dimethoxy-1,4-bis(dimethylamino)butane': 'CN(C[C@@H](OC)[C@H](OC)CN(C)C)C',
"(R,R)-(-)-N,N'-Bis(3,5-di-tert-butylsalicylidene)-1,2-cyclohexanediamine": 'OC1=C(C(C)(C)C)C=C(C(C)(C)C)C=C1/C=N/[C@H]2[C@H](/N=C/C3=CC(C(C)(C)C)=CC(C(C)(C)C)=C3O)CCCC2',
"(R,R)-(-)-N,N'-Bis(3,5-di-tert-butylsalicylidene)-1,2-cyclohexanediaminomanganese(III) Chloride": 'OC1=C(C(C)(C)C)C=C(C(C)(C)C)C=C1/C=[N]([Mn+]/[N]2=C\\C3=CC(C(C)(C)C)=CC(C(C)(C)C)=C3O)\\[C@@]4([H])[C@@]2([H])CCCC4.[Cl-]',
"(R,R)-(+)-2,2'-Isopropylidenebis(4-tert-butyl-2-oxazoline)": 'CC(C1=N[C@H](C(C)(C)C)CO1)(C2=N[C@H](C(C)(C)C)CO2)C',
- "(R,R)-1,2-Bis[(2-methoxyphenyl)phenylphosphino]ethane": 'COC1=CC=CC=C1[P@](CC[P@@](C2=CC=CC=C2OC)C3=CC=CC=C3)C4=CC=CC=C4',
+ '(R,R)-1,2-Bis[(2-methoxyphenyl)phenylphosphino]ethane': 'COC1=CC=CC=C1[P@](CC[P@@](C2=CC=CC=C2OC)C3=CC=CC=C3)C4=CC=CC=C4',
"(R,R)-2,2'-Isopropylidenebis(4-phenyl-2-oxazoline)": 'CC(C1=N[C@H](C2=CC=CC=C2)CO1)(C3=N[C@H](C4=CC=CC=C4)CO3)C',
- "(R,R)-2,6-Bis(4-isopropyl-2-oxazolin-2-yl)pyridine": 'CC([C@H]1N=C(C2=CC=CC(C3=N[C@H](C(C)C)CO3)=N2)OC1)C',
- "(R,R)-2,6-Bis(4-phenyl-2-oxazolin-2-yl)pyridine": 'C1(C2=N[C@H](C3=CC=CC=C3)CO2)=NC(C4=N[C@H](C5=CC=CC=C5)CO4)=CC=C1',
- "(R,R)-2-Iodo-1,3-bis[1-(mesitylcarbamoyl)ethoxy]benzene": 'C[C@H](C(NC1=C(C)C=C(C)C=C1C)=O)OC2=C(I)C(O[C@@H](C(NC3=C(C)C=C(C)C=C3C)=O)C)=CC=C2',
- "(R,R)-N-(2-Amino-1,2-diphenylethyl)-p-toluenesulfonamide": 'CC1=CC=C(S(=O)(N[C@H](C2=CC=CC=C2)[C@H](N)C3=CC=CC=C3)=O)C=C1',
+ '(R,R)-2,6-Bis(4-isopropyl-2-oxazolin-2-yl)pyridine': 'CC([C@H]1N=C(C2=CC=CC(C3=N[C@H](C(C)C)CO3)=N2)OC1)C',
+ '(R,R)-2,6-Bis(4-phenyl-2-oxazolin-2-yl)pyridine': 'C1(C2=N[C@H](C3=CC=CC=C3)CO2)=NC(C4=N[C@H](C5=CC=CC=C5)CO4)=CC=C1',
+ '(R,R)-2-Iodo-1,3-bis[1-(mesitylcarbamoyl)ethoxy]benzene': 'C[C@H](C(NC1=C(C)C=C(C)C=C1C)=O)OC2=C(I)C(O[C@@H](C(NC3=C(C)C=C(C)C=C3C)=O)C)=CC=C2',
+ '(R,R)-N-(2-Amino-1,2-diphenylethyl)-p-toluenesulfonamide': 'CC1=CC=C(S(=O)(N[C@H](C2=CC=CC=C2)[C@H](N)C3=CC=CC=C3)=O)C=C1',
"(R,R,R)-(3,5-Dioxa-4-phosphacyclohepta[2,1-a:3,4-a']dinaphthalen-4-yl)bis(1-phenylethyl)amine": 'C[C@@H](N(P1OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)[C@@H](C6=CC=CC=C6)C)C7=CC=CC=C7',
"(S)-(-)-1,1'-Binaphthyl-2,2'-diamine": 'NC1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3N',
- "(S)-(-)-1-Methyl-2-(1-piperidinomethyl)pyrrolidine": 'CN1[C@H](CN2CCCCC2)CCC1',
- "(S)-(-)-2-(Diphenylmethyl)pyrrolidine": '[C@H]1(C(C2=CC=CC=C2)C3=CC=CC=C3)NCCC1',
+ '(S)-(-)-1-Methyl-2-(1-piperidinomethyl)pyrrolidine': 'CN1[C@H](CN2CCCCC2)CCC1',
+ '(S)-(-)-2-(Diphenylmethyl)pyrrolidine': '[C@H]1(C(C2=CC=CC=C2)C3=CC=CC=C3)NCCC1',
"(S)-(-)-2-Amino-2'-hydroxy-1,1'-binaphthyl": 'OC1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3N',
- "(S)-(-)-2-Aminomethyl-1-ethylpyrrolidine": 'CCN1[C@H](CN)CCC1',
- "(S)-(-)-3-(tert-Butoxycarbonyl)-4-formyl-2,2-dimethyl-1,3-oxazolidine": 'CC1(C)OC[C@@H](C=O)N1C(OC(C)(C)C)=O',
+ '(S)-(-)-2-Aminomethyl-1-ethylpyrrolidine': 'CCN1[C@H](CN)CCC1',
+ '(S)-(-)-3-(tert-Butoxycarbonyl)-4-formyl-2,2-dimethyl-1,3-oxazolidine': 'CC1(C)OC[C@@H](C=O)N1C(OC(C)(C)C)=O',
"(S)-(-)-3,3'-Dibromo-5,5',6,6',7,7',8,8'-octahydro-1,1'-bi-2-naphthol": 'OC1=C(Br)C=C2CCCCC2=C1C3=C4CCCCC4=CC(Br)=C3O',
- "(S)-(-)-3-tert-Butoxycarbonyl-4-methoxycarbonyl-2,2-dimethyl-1,3-oxazolidine": 'CC1(C)OC[C@@H](C(OC)=O)N1C(OC(C)(C)C)=O',
+ '(S)-(-)-3-tert-Butoxycarbonyl-4-methoxycarbonyl-2,2-dimethyl-1,3-oxazolidine': 'CC1(C)OC[C@@H](C(OC)=O)N1C(OC(C)(C)C)=O',
"(S)-(-)-5,5',6,6',7,7',8,8'-Octahydro-1,1'-bi-2-naphthol": 'OC1=CC=C2CCCCC2=C1C3=C4CCCCC4=CC=C3O',
- "(S)-(-)-BINAP": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=C(C(C=CC=C4)=C4C=C3)C(C(C=CC=C5)=C5C=C6)=C6P(C7=CC=CC=C7)C8=CC=CC=C8',
- "(S)-(-)-Indoline-2-carboxylic Acid": 'O=C([C@H]1NC2=C(C=CC=C2)C1)O',
- "(S)-(-)-tert-Butylsulfinamide": 'CC(C)([S@@](N)=O)C',
- "(S)-(-)-α,α-Diphenyl-2-pyrrolidinemethanol": 'OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@@H]3CCCN3',
- "(S)-(-)-α,α-Diphenyl-2-pyrrolidinemethanol Trimethylsilyl Ether": 'C[Si](OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@H]3NCCC3)(C)C',
- "(S)-(+)-(3,5-Dioxa-4-phosphacyclohepta[2,1-a": 'CN(P1OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)C',
+ '(S)-(-)-BINAP': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=C(C(C=CC=C4)=C4C=C3)C(C(C=CC=C5)=C5C=C6)=C6P(C7=CC=CC=C7)C8=CC=CC=C8',
+ '(S)-(-)-Indoline-2-carboxylic Acid': 'O=C([C@H]1NC2=C(C=CC=C2)C1)O',
+ '(S)-(-)-tert-Butylsulfinamide': 'CC(C)([S@@](N)=O)C',
+ '(S)-(-)-α,α-Diphenyl-2-pyrrolidinemethanol': 'OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@@H]3CCCN3',
+ '(S)-(-)-α,α-Diphenyl-2-pyrrolidinemethanol Trimethylsilyl Ether': 'C[Si](OC(C1=CC=CC=C1)(C2=CC=CC=C2)[C@H]3NCCC3)(C)C',
+ '(S)-(+)-(3,5-Dioxa-4-phosphacyclohepta[2,1-a': 'CN(P1OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)C',
"3,4-a']dinaphthalen-4-yl)dimethylamine": 'CN(P1OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)C',
- "(S)-(+)-1-(2-Pyrrolidinylmethyl)pyrrolidine": 'N1(C[C@H]2NCCC2)CCCC1',
+ '(S)-(+)-1-(2-Pyrrolidinylmethyl)pyrrolidine': 'N1(C[C@H]2NCCC2)CCCC1',
"(S)-(+)-1,1'-Binaphthyl-2,2'-diyl Bis(trifluoromethanesulfonate)": 'O=S(C(F)(F)F)(OC1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3OS(C(F)(F)F)(=O)=O)=O',
"(S)-(+)-1,1'-Binaphthyl-2,2'-diyl Hydrogen Phosphate": 'O=P1(OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)O',
- "(S)-(+)-2-(Anilinomethyl)pyrrolidine": '[C@H]1(CNC2=CC=CC=C2)NCCC1',
- "(S)-(+)-2-[Hydroxy(diphenyl)methyl]-1-methylpyrrolidine": 'CN1[C@H](C(C2=CC=CC=C2)(O)C3=CC=CC=C3)CCC1',
- "(S)-(+)-4-Benzyl-3-propionyl-2-oxazolidinone": 'O=C1OC[C@H](CC2=CC=CC=C2)N1C(CC)=O',
- "(S)-(+)-4-Isopropyl-3-propionyl-2-oxazolidinone": 'O=C1OC[C@H](C(C)C)N1C(CC)=O',
- "(S)-(+)-4-Phenyl-2-oxazolidinone": 'O=C1OC[C@H](C2=CC=CC=C2)N1',
+ '(S)-(+)-2-(Anilinomethyl)pyrrolidine': '[C@H]1(CNC2=CC=CC=C2)NCCC1',
+ '(S)-(+)-2-[Hydroxy(diphenyl)methyl]-1-methylpyrrolidine': 'CN1[C@H](C(C2=CC=CC=C2)(O)C3=CC=CC=C3)CCC1',
+ '(S)-(+)-4-Benzyl-3-propionyl-2-oxazolidinone': 'O=C1OC[C@H](CC2=CC=CC=C2)N1C(CC)=O',
+ '(S)-(+)-4-Isopropyl-3-propionyl-2-oxazolidinone': 'O=C1OC[C@H](C(C)C)N1C(CC)=O',
+ '(S)-(+)-4-Phenyl-2-oxazolidinone': 'O=C1OC[C@H](C2=CC=CC=C2)N1',
"(S)-(+)-6,6'-Dibromo-1,1'-bi-2-naphthol": 'OC1=CC=C2C=C(Br)C=CC2=C1C3=C4C=CC(Br)=CC4=CC=C3O',
- "(S)-(+)-p-Toluenesulfinamide": 'CC1=CC=C([S@@](N)=O)C=C1',
+ '(S)-(+)-p-Toluenesulfinamide': 'CC1=CC=C([S@@](N)=O)C=C1',
"(S)-[4-(Pyridin-4-yl)-4,5-dihydro-3H-dinaphtho[2,1-c:1',2'-e]azepine-2,6-diyl]bis[bis[4-(tert-butyl)phenyl]methanol]": 'OC(C1=C2CN(C3=CC=NC=C3)CC4=C(C(C5=CC=C(C(C)(C)C)C=C5)(C6=CC=C(C(C)(C)C)C=C6)O)C=C7C=CC=CC7=C4C2=C8C=CC=CC8=C1)(C9=CC=C(C(C)(C)C)C=C9)C%10=CC=C(C(C)(C)C)C=C%10',
- "(S)-2-(Aminomethyl)pyrrolidine": 'NC[C@H]1NCCC1',
- "(S)-2-(Methoxymethyl)pyrrolidine": 'COC[C@H]1NCCC1',
+ '(S)-2-(Aminomethyl)pyrrolidine': 'NC[C@H]1NCCC1',
+ '(S)-2-(Methoxymethyl)pyrrolidine': 'COC[C@H]1NCCC1',
"(S)-2,2'-Dimethoxy-1,1'-binaphthyl": 'COC1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3OC',
- "(S)-2,4-Diphenyl-4,5-dihydrooxazole": 'C1(C2=CC=CC=C2)=N[C@@H](C3=CC=CC=C3)CO1',
- "(S)-2-[(1-Methyl-2-pyrrolidinyl)methyl]isoindoline Dihydrochloride": 'CN1[C@H](CN2CC3=C(C=CC=C3)C2)CCC1.[H]Cl.[H]Cl',
+ '(S)-2,4-Diphenyl-4,5-dihydrooxazole': 'C1(C2=CC=CC=C2)=N[C@@H](C3=CC=CC=C3)CO1',
+ '(S)-2-[(1-Methyl-2-pyrrolidinyl)methyl]isoindoline Dihydrochloride': 'CN1[C@H](CN2CC3=C(C=CC=C3)C2)CCC1.[H]Cl.[H]Cl',
"(S)-3,3'-Dibromo-1,1'-bi-2-naphthol": 'OC1=C(Br)C=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC(Br)=C3O',
"(S)-3,3'-Dibromo-2,2'-dimethoxy-1,1'-binaphthyl": 'COC1=C(Br)C=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC(Br)=C3OC',
"(S)-3-[1-(4-Methoxybenzenesulfonyl)-(4S,5S)-4,5-diphenyl-4,5-dihydro-1H-imidazol-2-yl]-1,1'-binaphthalene-2,2'-diyl Hydrogen Phosphate": 'O=P1(OC2=C(C3=N[C@@H](C4=CC=CC=C4)[C@H](C5=CC=CC=C5)N3S(=O)(C6=CC=C(OC)C=C6)=O)C=C7C=CC=CC7=C2C8=C9C=CC=CC9=CC=C8O1)O',
- "(S)-4-(4-Aminobenzyl)-2-oxazolidinone": 'O=C1OC[C@H](CC2=CC=C(N)C=C2)N1',
- "(S)-4-Benzyl-2-oxazolidinone": 'O=C1OC[C@H](CC2=CC=CC=C2)N1',
- "(S)-4-Isopropyl-2-oxazolidinone": 'O=C1OC[C@H](C(C)C)N1',
- "(S)-4-Isopropyl-3-(1-naphthylmethyl)-2,5,5-triphenyl-1,3,2-oxazaborolidine": 'CC([C@@H]1N(CC2=C3C=CC=CC3=CC=C2)B(C4=CC=CC=C4)OC1(C5=CC=CC=C5)C6=CC=CC=C6)C',
- "(S)-4-Isopropylthiazolidine-2-thione": 'S=C1SC[C@H](C(C)C)N1',
- "(S)-4-Phenylthiazolidine-2-thione": 'S=C1SC[C@H](C2=CC=CC=C2)N1',
- "(S)-4-tert-Butyl-2-(2-pyridyl)oxazoline": 'CC([C@@H]1N=C(C2=NC=CC=C2)OC1)(C)C',
- "(S)-5-(Pyrrolidin-2-yl)-1H-tetrazole": 'C1([C@H]2NCCC2)=NN=NN1',
- "(S)-5,5-Diphenyl-2-methyl-3,4-propano-1,3,2-oxazaborolidine": 'CB1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@@]4([H])N1CCC4',
- "(S)-Benzyl-2-[4-(trifluoromethyl)phenyl]-6,7-dihydro-5H-pyrrolo[2,1-c][1,2,4]triazolium Tetrafluoroborate": 'FC(C1=CC=C([N+]2=C(CC3=CC=CC=C3)N4C(CCC4)=N2)C=C1)(F)F.F[B-](F)(F)F',
+ '(S)-4-(4-Aminobenzyl)-2-oxazolidinone': 'O=C1OC[C@H](CC2=CC=C(N)C=C2)N1',
+ '(S)-4-Benzyl-2-oxazolidinone': 'O=C1OC[C@H](CC2=CC=CC=C2)N1',
+ '(S)-4-Isopropyl-2-oxazolidinone': 'O=C1OC[C@H](C(C)C)N1',
+ '(S)-4-Isopropyl-3-(1-naphthylmethyl)-2,5,5-triphenyl-1,3,2-oxazaborolidine': 'CC([C@@H]1N(CC2=C3C=CC=CC3=CC=C2)B(C4=CC=CC=C4)OC1(C5=CC=CC=C5)C6=CC=CC=C6)C',
+ '(S)-4-Isopropylthiazolidine-2-thione': 'S=C1SC[C@H](C(C)C)N1',
+ '(S)-4-Phenylthiazolidine-2-thione': 'S=C1SC[C@H](C2=CC=CC=C2)N1',
+ '(S)-4-tert-Butyl-2-(2-pyridyl)oxazoline': 'CC([C@@H]1N=C(C2=NC=CC=C2)OC1)(C)C',
+ '(S)-5-(Pyrrolidin-2-yl)-1H-tetrazole': 'C1([C@H]2NCCC2)=NN=NN1',
+ '(S)-5,5-Diphenyl-2-methyl-3,4-propano-1,3,2-oxazaborolidine': 'CB1OC(C2=CC=CC=C2)(C3=CC=CC=C3)[C@@]4([H])N1CCC4',
+ '(S)-Benzyl-2-[4-(trifluoromethyl)phenyl]-6,7-dihydro-5H-pyrrolo[2,1-c][1,2,4]triazolium Tetrafluoroborate': 'FC(C1=CC=C([N+]2=C(CC3=CC=CC=C3)N4C(CCC4)=N2)C=C1)(F)F.F[B-](F)(F)F',
"(S,S)-(-)-2,2'-Isopropylidenebis(4-tert-butyl-2-oxazoline)": 'CC(C1=N[C@@H](C(C)(C)C)CO1)(C2=N[C@@H](C(C)(C)C)CO2)C',
- "(S,S)-(+)-2,3-Bis(tert-butylmethylphosphino)quinoxaline": 'C[P@](C1=NC2=CC=CC=C2N=C1[P@](C(C)(C)C)C)C(C)(C)C',
- "(S,S)-(+)-2,3-Dimethoxy-1,4-bis(dimethylamino)butane": 'CN(C[C@H](OC)[C@@H](OC)CN(C)C)C',
- "(S,S)-1,2-Bis[(2-methoxyphenyl)phenylphosphino]ethane": 'COC1=CC=CC=C1[P@@](CC[P@](C2=CC=CC=C2OC)C3=CC=CC=C3)C4=CC=CC=C4',
- "(S,S)-1,2-Bis[(tert-butyl)methylphosphino]ethane Bis(borane)": 'C[P@@](CC[P@@](C(C)(C)C)C)C(C)(C)C.B.B',
+ '(S,S)-(+)-2,3-Bis(tert-butylmethylphosphino)quinoxaline': 'C[P@](C1=NC2=CC=CC=C2N=C1[P@](C(C)(C)C)C)C(C)(C)C',
+ '(S,S)-(+)-2,3-Dimethoxy-1,4-bis(dimethylamino)butane': 'CN(C[C@H](OC)[C@@H](OC)CN(C)C)C',
+ '(S,S)-1,2-Bis[(2-methoxyphenyl)phenylphosphino]ethane': 'COC1=CC=CC=C1[P@@](CC[P@](C2=CC=CC=C2OC)C3=CC=CC=C3)C4=CC=CC=C4',
+ '(S,S)-1,2-Bis[(tert-butyl)methylphosphino]ethane Bis(borane)': 'C[P@@](CC[P@@](C(C)(C)C)C)C(C)(C)C.B.B',
"(S,S)-2,2'-Isopropylidenebis(4-phenyl-2-oxazoline)": 'CC(C1=N[C@@H](C2=CC=CC=C2)CO1)(C3=N[C@@H](C4=CC=CC=C4)CO3)C',
- "(S,S)-2,6-Bis(4-isopropyl-2-oxazolin-2-yl)pyridine": 'CC([C@@H]1N=C(C2=CC=CC(C3=N[C@@H](C(C)C)CO3)=N2)OC1)C',
- "(S,S)-2,6-Bis(4-phenyl-2-oxazolin-2-yl)pyridine": 'C1(C2=N[C@@H](C3=CC=CC=C3)CO2)=NC(C4=N[C@@H](C5=CC=CC=C5)CO4)=CC=C1',
- "(S,S)-4,6-Bis(4-isopropyl-2-oxazolin-2-yl)-m-xylene": 'CC1=C(C2=N[C@@H](C(C)C)CO2)C=C(C3=N[C@@H](C(C)C)CO3)C(C)=C1',
- "(S,S)-N-(2-Amino-1,2-diphenylethyl)-p-toluenesulfonamide": 'CC1=CC=C(S(=O)(N[C@@H](C2=CC=CC=C2)[C@@H](N)C3=CC=CC=C3)=O)C=C1',
+ '(S,S)-2,6-Bis(4-isopropyl-2-oxazolin-2-yl)pyridine': 'CC([C@@H]1N=C(C2=CC=CC(C3=N[C@@H](C(C)C)CO3)=N2)OC1)C',
+ '(S,S)-2,6-Bis(4-phenyl-2-oxazolin-2-yl)pyridine': 'C1(C2=N[C@@H](C3=CC=CC=C3)CO2)=NC(C4=N[C@@H](C5=CC=CC=C5)CO4)=CC=C1',
+ '(S,S)-4,6-Bis(4-isopropyl-2-oxazolin-2-yl)-m-xylene': 'CC1=C(C2=N[C@@H](C(C)C)CO2)C=C(C3=N[C@@H](C(C)C)CO3)C(C)=C1',
+ '(S,S)-N-(2-Amino-1,2-diphenylethyl)-p-toluenesulfonamide': 'CC1=CC=C(S(=O)(N[C@@H](C2=CC=CC=C2)[C@@H](N)C3=CC=CC=C3)=O)C=C1',
"(S,S,S)-(3,5-Dioxa-4-phosphacyclohepta[2,1-a:3,4-a']dinaphthalen-4-yl)bis(1-phenylethyl)amine": 'C[C@H](N(P1OC2=CC=C3C=CC=CC3=C2C4=C5C=CC=CC5=CC=C4O1)[C@H](C6=CC=CC=C6)C)C7=CC=CC=C7',
- "(tert-Butyldimethylsilyl)acetylene": 'C#C[Si](C)(C(C)(C)C)C',
- "(tert-Butyldimethylsilyloxy)malononitrile": 'N#CC(O[Si](C)(C(C)(C)C)C)C#N',
- "(Trifluoroacetyl)benzotriazole": 'O=C(C1=C2N=NNC2=CC=C1)C(F)(F)F',
- "(Trifluoromethyl)trimethylsilane": 'C[Si](C)(C(F)(F)F)C',
- "(Trifluoromethyl)tris(triphenylphosphine)copper(I)": '[Cu]C(F)(F)F.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9',
- "(Triphenylphosphine)gold(I) Chloride": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.[Au+].[Cl-]',
- "[(4-Bromobenzyl)oxy](tert-butyl)dimethylsilane": 'C[Si](C(C)(C)C)(OCC1=CC=C(Br)C=C1)C',
- "[(4-Methoxyphenyl)ethynyl]trimethylsilane": 'C[Si](C)(C#CC1=CC=C(OC)C=C1)C',
+ '(tert-Butyldimethylsilyl)acetylene': 'C#C[Si](C)(C(C)(C)C)C',
+ '(tert-Butyldimethylsilyloxy)malononitrile': 'N#CC(O[Si](C)(C(C)(C)C)C)C#N',
+ '(Trifluoroacetyl)benzotriazole': 'O=C(C1=C2N=NNC2=CC=C1)C(F)(F)F',
+ '(Trifluoromethyl)trimethylsilane': 'C[Si](C)(C(F)(F)F)C',
+ '(Trifluoromethyl)tris(triphenylphosphine)copper(I)': '[Cu]C(F)(F)F.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9',
+ '(Triphenylphosphine)gold(I) Chloride': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.[Au+].[Cl-]',
+ '[(4-Bromobenzyl)oxy](tert-butyl)dimethylsilane': 'C[Si](C(C)(C)C)(OCC1=CC=C(Br)C=C1)C',
+ '[(4-Methoxyphenyl)ethynyl]trimethylsilane': 'C[Si](C)(C#CC1=CC=C(OC)C=C1)C',
"[(R)-2,2'-Bis(diphenylphosphino)-1,1'-binaphthyl]ruthenium(II) Dichloride": 'C1(C2=C3C=CC=CC3=CC=C2P(C4=CC=CC=C4)C5=CC=CC=C5)=C6C=CC=CC6=CC=C1P(C7=CC=CC=C7)C8=CC=CC=C8.[Ru+2].[Cl-].[Cl-]',
"[(S)-2,2'-Bis(diphenylphosphino)-1,1'-binaphthyl]ruthenium(II) Dichloride": 'C1(C2=C3C=CC=CC3=CC=C2P(C4=CC=CC=C4)C5=CC=CC=C5)=C6C=CC=CC6=CC=C1P(C7=CC=CC=C7)C8=CC=CC=C8.[Ru+2].[Cl-].[Cl-]',
- "[1,1′-Bis(diphenylphosphino)ferrocene]dichloropalladium(II)": 'C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.Cl[Pd]Cl.[Fe]',
- "PdCl2(dppf)": 'C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.Cl[Pd]Cl.[Fe]',
- "[1,2-Bis(diphenylphosphino)ethane]nickel(II) Dichloride": 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.[Ni+2].[Cl-].[Cl-]',
- "[1,2-Bis(diphenylphosphino)ethane]palladium(II) Dichloride": 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.[Pd+2].[Cl-].[Cl-]',
- "[1,3-Bis(2,6-diisopropylphenyl)imidazol-2-ylidene]triphenylphosphine Nickel(II) Dichloride": 'CC(C1=C(N(C=CN2C3=C(C(C)C)C=CC=C3C(C)C)C2=P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)C(C(C)C)=CC=C1)C.[Ni+2].[Cl-].[Cl-]',
- "[1,3-Bis(diphenylphosphino)propane]nickel(II) Dichloride": 'P(CCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.[Ni+2].[Cl-].[Cl-]',
- "[3-(6-Aminohexylamino)propyl]trimethoxysilane": 'CO[Si](OC)(CCCNCCCCCCN)OC',
- "[3-(Diethylamino)propyl]trimethoxysilane": 'CO[Si](OC)(CCCN(CC)CC)OC',
- "[3-(N,N-Dimethylamino)propyl]trimethoxysilane": 'CO[Si](OC)(CCCN(C)C)OC',
- "[3-(Trimethoxysilyl)propyl]succinic Anhydride": 'O=C(O1)C(CCC[Si](OC)(OC)OC)CC1=O',
- "[Bis(trifluoroacetoxy)iodo]benzene": 'O=C(OI(C1=CC=CC=C1)OC(C(F)(F)F)=O)C(F)(F)F',
- "[Bis(trifluoroacetoxy)iodo]pentafluorobenzene": 'FC1=C(I(OC(C(F)(F)F)=O)OC(C(F)(F)F)=O)C(F)=C(F)C(F)=C1F',
- "[Di-tert-butyl(chloro)phosphine]palladium(II) Dichloride": 'ClP(C(C)(C)C)C(C)(C)C.[Pd+2].[Cl-].[Cl-]',
- "[Hydroxy(tosyloxy)iodo]benzene": 'O=S(OI(C1=CC=CC=C1)O)(C2=CC=C(C)C=C2)=O',
- "1-(2,4,6-Triisopropylbenzenesulfonyl)-1,2,4-triazole": 'O=S(N1N=CN=C1)(C2=C(C(C)C)C=C(C(C)C)C=C2C(C)C)=O',
- "1-(2,4,6-Triisopropylbenzenesulfonyl)imidazole": 'O=S(N1C=CN=C1)(C2=C(C(C)C)C=C(C(C)C)C=C2C(C)C)=O',
- "1-(2-Hydroxyethyl)-3-methylimidazolium Chloride": 'C[N+]1=CN(CCO)C=C1.[Cl-]',
- "1-(2-Hydroxyethyl)-3-methylimidazolium Tetrafluoroborate": 'C[N+]1=CN(CCO)C=C1.F[B-](F)(F)F',
- "1-(2-Mesitylene)-1,3-butanedione": 'CC(CC(C1=C(C)C=C(C)C=C1C)=O)=O',
- "1-(2-Mesitylenesulfonyl)imidazole": 'O=S(N1C=CN=C1)(C(C(C)=CC(C)=C2)=C2C)=O',
- "1-(3-Dimethylaminopropyl)-3-ethylcarbodiimide": 'CCN=C=NCCCN(C)C',
- "EDC": 'CCN=C=NCCCN(C)C',
- "1-(3-Dimethylaminopropyl)-3-ethylcarbodiimide Hydrochloride": 'CCN=C=NCCCN(C)C.[H]Cl',
- "EDC HCl": 'CCN=C=NCCCN(C)C.[H]Cl',
- "1-(4-Bromophenyl)-1,3-butanedione": 'CC(CC(C1=CC=C(Br)C=C1)=O)=O',
- "1-(4-Chlorophenyl)-4,4,4-trifluoro-1,3-butanedione": 'O=C(C1=CC=C(Cl)C=C1)CC(C(F)(F)F)=O',
- "1-(4-Fluorophenyl)-1,3-butanedione": 'CC(CC(C1=CC=C(F)C=C1)=O)=O',
- "1-(4-tert-Butylphenyl)-3-(4-methoxyphenyl)-1,3-propanedione": 'O=C(C1=CC=C(C(C)(C)C)C=C1)CC(C2=CC=C(OC)C=C2)=O',
- "1-(Chloro-1-pyrrolidinylmethylene)pyrrolidinium Hexafluorophosphate": 'ClC(N1CCCC1)=[N+]2CCCC2.F[P-](F)(F)(F)(F)F',
- "1-(Chloro-1-pyrrolidinylmethylene)pyrrolidinium Tetrafluoroborate": 'ClC(N1CCCC1)=[N+]2CCCC2.F[B-](F)(F)F',
- "1-(Cyanomethyl)piperidinium Tetrafluoroborate": 'N#CC[NH+]1CCCCC1.F[B-](F)(F)F',
- "1-(Heptafluorobutyryl)imidazole": 'O=C(N1C=CN=C1)C(F)(F)C(F)(F)C(F)(F)F',
- "1-(p-Toluenesulfonyl)imidazole": 'O=S(N1C=CN=C1)(C2=CC=C(C)C=C2)=O',
- "1-(Trifluoroacetyl)-4-(dimethylamino)pyridinium Trifluoroacetate": 'CN(C1=CC=[N+](C(C(F)(F)F)=O)C=C1)C.O=C([O-])C(F)(F)F',
- "1-(Trifluoroacetyl)imidazole": 'O=C(N1C=CN=C1)C(F)(F)F',
- "1-(Trifluoroacetyl)piperidine": 'O=C(N1CCCCC1)C(F)(F)F',
- "1-(Trifluoromethanesulfonyl)-1H-benzotriazole": 'O=S(N1N=NC2=CC=CC=C21)(C(F)(F)F)=O',
- "1-(Trifluoromethanesulfonyl)imidazole": 'O=S(N1C=CN=C1)(C(F)(F)F)=O',
- "1-(Triisopropylsilyl)-1-propyne": 'CC#C[Si](C(C)C)(C(C)C)C(C)C',
- "1-(Trimethoxysilyl)naphthalene": 'CO[Si](C1=C2C=CC=CC2=CC=C1)(OC)OC',
- "1-(Trimethylsilyl)-1-pentyne": 'CCCC#C[Si](C)(C)C',
- "1-(Trimethylsilyl)-1-propyne": 'CC#C[Si](C)(C)C',
+ '[1,1′-Bis(diphenylphosphino)ferrocene]dichloropalladium(II)': 'C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.Cl[Pd]Cl.[Fe]',
+ 'PdCl2(dppf)': 'C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.C1=CC=C(C=C1)P(C2=CC=CC=C2)[C]3[CH][CH][CH][CH]3.Cl[Pd]Cl.[Fe]',
+ '[1,2-Bis(diphenylphosphino)ethane]nickel(II) Dichloride': 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.[Ni+2].[Cl-].[Cl-]',
+ '[1,2-Bis(diphenylphosphino)ethane]palladium(II) Dichloride': 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.[Pd+2].[Cl-].[Cl-]',
+ '[1,3-Bis(2,6-diisopropylphenyl)imidazol-2-ylidene]triphenylphosphine Nickel(II) Dichloride': 'CC(C1=C(N(C=CN2C3=C(C(C)C)C=CC=C3C(C)C)C2=P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)C(C(C)C)=CC=C1)C.[Ni+2].[Cl-].[Cl-]',
+ '[1,3-Bis(diphenylphosphino)propane]nickel(II) Dichloride': 'P(CCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.[Ni+2].[Cl-].[Cl-]',
+ '[3-(6-Aminohexylamino)propyl]trimethoxysilane': 'CO[Si](OC)(CCCNCCCCCCN)OC',
+ '[3-(Diethylamino)propyl]trimethoxysilane': 'CO[Si](OC)(CCCN(CC)CC)OC',
+ '[3-(N,N-Dimethylamino)propyl]trimethoxysilane': 'CO[Si](OC)(CCCN(C)C)OC',
+ '[3-(Trimethoxysilyl)propyl]succinic Anhydride': 'O=C(O1)C(CCC[Si](OC)(OC)OC)CC1=O',
+ '[Bis(trifluoroacetoxy)iodo]benzene': 'O=C(OI(C1=CC=CC=C1)OC(C(F)(F)F)=O)C(F)(F)F',
+ '[Bis(trifluoroacetoxy)iodo]pentafluorobenzene': 'FC1=C(I(OC(C(F)(F)F)=O)OC(C(F)(F)F)=O)C(F)=C(F)C(F)=C1F',
+ '[Di-tert-butyl(chloro)phosphine]palladium(II) Dichloride': 'ClP(C(C)(C)C)C(C)(C)C.[Pd+2].[Cl-].[Cl-]',
+ '[Hydroxy(tosyloxy)iodo]benzene': 'O=S(OI(C1=CC=CC=C1)O)(C2=CC=C(C)C=C2)=O',
+ '1-(2,4,6-Triisopropylbenzenesulfonyl)-1,2,4-triazole': 'O=S(N1N=CN=C1)(C2=C(C(C)C)C=C(C(C)C)C=C2C(C)C)=O',
+ '1-(2,4,6-Triisopropylbenzenesulfonyl)imidazole': 'O=S(N1C=CN=C1)(C2=C(C(C)C)C=C(C(C)C)C=C2C(C)C)=O',
+ '1-(2-Hydroxyethyl)-3-methylimidazolium Chloride': 'C[N+]1=CN(CCO)C=C1.[Cl-]',
+ '1-(2-Hydroxyethyl)-3-methylimidazolium Tetrafluoroborate': 'C[N+]1=CN(CCO)C=C1.F[B-](F)(F)F',
+ '1-(2-Mesitylene)-1,3-butanedione': 'CC(CC(C1=C(C)C=C(C)C=C1C)=O)=O',
+ '1-(2-Mesitylenesulfonyl)imidazole': 'O=S(N1C=CN=C1)(C(C(C)=CC(C)=C2)=C2C)=O',
+ '1-(3-Dimethylaminopropyl)-3-ethylcarbodiimide': 'CCN=C=NCCCN(C)C',
+ EDC: 'CCN=C=NCCCN(C)C',
+ '1-(3-Dimethylaminopropyl)-3-ethylcarbodiimide Hydrochloride': 'CCN=C=NCCCN(C)C.[H]Cl',
+ 'EDC HCl': 'CCN=C=NCCCN(C)C.[H]Cl',
+ '1-(4-Bromophenyl)-1,3-butanedione': 'CC(CC(C1=CC=C(Br)C=C1)=O)=O',
+ '1-(4-Chlorophenyl)-4,4,4-trifluoro-1,3-butanedione': 'O=C(C1=CC=C(Cl)C=C1)CC(C(F)(F)F)=O',
+ '1-(4-Fluorophenyl)-1,3-butanedione': 'CC(CC(C1=CC=C(F)C=C1)=O)=O',
+ '1-(4-tert-Butylphenyl)-3-(4-methoxyphenyl)-1,3-propanedione': 'O=C(C1=CC=C(C(C)(C)C)C=C1)CC(C2=CC=C(OC)C=C2)=O',
+ '1-(Chloro-1-pyrrolidinylmethylene)pyrrolidinium Hexafluorophosphate': 'ClC(N1CCCC1)=[N+]2CCCC2.F[P-](F)(F)(F)(F)F',
+ '1-(Chloro-1-pyrrolidinylmethylene)pyrrolidinium Tetrafluoroborate': 'ClC(N1CCCC1)=[N+]2CCCC2.F[B-](F)(F)F',
+ '1-(Cyanomethyl)piperidinium Tetrafluoroborate': 'N#CC[NH+]1CCCCC1.F[B-](F)(F)F',
+ '1-(Heptafluorobutyryl)imidazole': 'O=C(N1C=CN=C1)C(F)(F)C(F)(F)C(F)(F)F',
+ '1-(p-Toluenesulfonyl)imidazole': 'O=S(N1C=CN=C1)(C2=CC=C(C)C=C2)=O',
+ '1-(Trifluoroacetyl)-4-(dimethylamino)pyridinium Trifluoroacetate': 'CN(C1=CC=[N+](C(C(F)(F)F)=O)C=C1)C.O=C([O-])C(F)(F)F',
+ '1-(Trifluoroacetyl)imidazole': 'O=C(N1C=CN=C1)C(F)(F)F',
+ '1-(Trifluoroacetyl)piperidine': 'O=C(N1CCCCC1)C(F)(F)F',
+ '1-(Trifluoromethanesulfonyl)-1H-benzotriazole': 'O=S(N1N=NC2=CC=CC=C21)(C(F)(F)F)=O',
+ '1-(Trifluoromethanesulfonyl)imidazole': 'O=S(N1C=CN=C1)(C(F)(F)F)=O',
+ '1-(Triisopropylsilyl)-1-propyne': 'CC#C[Si](C(C)C)(C(C)C)C(C)C',
+ '1-(Trimethoxysilyl)naphthalene': 'CO[Si](C1=C2C=CC=CC2=CC=C1)(OC)OC',
+ '1-(Trimethylsilyl)-1-pentyne': 'CCCC#C[Si](C)(C)C',
+ '1-(Trimethylsilyl)-1-propyne': 'CC#C[Si](C)(C)C',
"1,1'-(2,6-Pyridinediyl)bis(3-methylimidazolium) Dibromide": 'C[N+]1=CN(C2=NC(N3C=C[N+](C)=C3)=CC=C2)C=C1.[Br-].[Br-]',
- "1,1,1,3,3,3-Hexafluoroisopropyl Trifluoromethanesulfonate": 'O=S(C(F)(F)F)(OC(C(F)(F)F)C(F)(F)F)=O',
- "1,1,1,3,3-Pentamethyldisiloxane": 'C[SiH](C)O[Si](C)(C)C',
- "1,1,1,3,5,5,5-Heptamethyl-3-[(trimethylsilyl)oxy]trisiloxane": 'C[Si](O[Si](O[Si](C)(C)C)(C)O[Si](C)(C)C)(C)C',
- "1,1,1,3,5,5,5-Heptamethyltrisiloxane": 'C[Si](C)(C)O[SiH](C)O[Si](C)(C)C',
- "1,1,1,3,5,7,7,7-Octamethyltetrasiloxane": 'C[Si](C)(C)O[SiH](C)O[SiH](C)O[Si](C)(C)C',
- "1,1,1,5,5,5-Hexamethyl-3-[(trimethylsilyl)oxy]-3-vinyltrisiloxane": 'C=C[Si](O[Si](C)(C)C)(O[Si](C)(C)C)O[Si](C)(C)C',
- "1,1,1,5,5,5-Hexamethyl-3-phenyl-3-(trimethylsilyloxy)trisiloxane": 'C[Si](O[Si](O[Si](C)(C)C)(C1=CC=CC=C1)O[Si](C)(C)C)(C)C',
- "1,1,2,2-Tetrachloro-1,2-dimethyldisilane": 'C[Si](Cl)(Cl)[Si](Cl)(Cl)C',
- "1,1,2,2-Tetraphenyldisilane": '[SiH](C1=CC=CC=C1)(C2=CC=CC=C2)[SiH](C3=CC=CC=C3)C4=CC=CC=C4',
- "1,1,2,3,4,5-Hexaphenylsilole": 'C1(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C(C5=CC=CC=C5)[Si]1(C6=CC=CC=C6)C7=CC=CC=C7',
- "1,1,3,3,5,5,7,7,9,9,11,11,13,13-Tetradecamethylheptasiloxane": 'C[SiH](C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[SiH](C)C',
- "1,1,3,3,5,5,7,7,9,9,11,11-Dodecamethylhexasiloxane": 'C[SiH](C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[SiH](C)C',
- "1,1,3,3,5,5-Hexaethoxy-1,3,5-trisilacyclohexane": 'CCO[Si]1(OCC)C[Si](OCC)(OCC)C[Si](OCC)(OCC)C1',
- "1,1,3,3,5,5-Hexamethyltrisiloxane": 'C[SiH](C)O[Si](C)(C)O[SiH](C)C',
- "1,1,3,3-Tetramethyl-1,3-diphenyldisiloxane": 'C[Si](C1=CC=CC=C1)(C)O[Si](C)(C)C2=CC=CC=C2',
- "1,1,3,3-Tetramethyldisiloxane": 'C[SiH](C)O[SiH](C)C',
- "1,1,3,3-Tetramethylguanidine": 'N=C(N(C)C)N(C)C',
- "1,1,4,7,10,10-Hexamethyltriethylenetetramine": 'CN(CCN(C)C)CCN(C)CCN(C)C',
- "1,1,5,5-Tetrafluoro-2,4-pentanedione": 'O=C(CC(C(F)F)=O)C(F)F',
- "1,10-Phenanthroline Monohydrate": '[H]O[H].C12=CC=C3C=CC=NC3=C1N=CC=C2',
- "1,10-Phenanthroline-5,6-dione": 'O=C1C2=C(N=CC=C2)C3=C(C=CC=N3)C1=O',
+ '1,1,1,3,3,3-Hexafluoroisopropyl Trifluoromethanesulfonate': 'O=S(C(F)(F)F)(OC(C(F)(F)F)C(F)(F)F)=O',
+ '1,1,1,3,3-Pentamethyldisiloxane': 'C[SiH](C)O[Si](C)(C)C',
+ '1,1,1,3,5,5,5-Heptamethyl-3-[(trimethylsilyl)oxy]trisiloxane': 'C[Si](O[Si](O[Si](C)(C)C)(C)O[Si](C)(C)C)(C)C',
+ '1,1,1,3,5,5,5-Heptamethyltrisiloxane': 'C[Si](C)(C)O[SiH](C)O[Si](C)(C)C',
+ '1,1,1,3,5,7,7,7-Octamethyltetrasiloxane': 'C[Si](C)(C)O[SiH](C)O[SiH](C)O[Si](C)(C)C',
+ '1,1,1,5,5,5-Hexamethyl-3-[(trimethylsilyl)oxy]-3-vinyltrisiloxane': 'C=C[Si](O[Si](C)(C)C)(O[Si](C)(C)C)O[Si](C)(C)C',
+ '1,1,1,5,5,5-Hexamethyl-3-phenyl-3-(trimethylsilyloxy)trisiloxane': 'C[Si](O[Si](O[Si](C)(C)C)(C1=CC=CC=C1)O[Si](C)(C)C)(C)C',
+ '1,1,2,2-Tetrachloro-1,2-dimethyldisilane': 'C[Si](Cl)(Cl)[Si](Cl)(Cl)C',
+ '1,1,2,2-Tetraphenyldisilane': '[SiH](C1=CC=CC=C1)(C2=CC=CC=C2)[SiH](C3=CC=CC=C3)C4=CC=CC=C4',
+ '1,1,2,3,4,5-Hexaphenylsilole': 'C1(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C(C5=CC=CC=C5)[Si]1(C6=CC=CC=C6)C7=CC=CC=C7',
+ '1,1,3,3,5,5,7,7,9,9,11,11,13,13-Tetradecamethylheptasiloxane': 'C[SiH](C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[SiH](C)C',
+ '1,1,3,3,5,5,7,7,9,9,11,11-Dodecamethylhexasiloxane': 'C[SiH](C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[SiH](C)C',
+ '1,1,3,3,5,5-Hexaethoxy-1,3,5-trisilacyclohexane': 'CCO[Si]1(OCC)C[Si](OCC)(OCC)C[Si](OCC)(OCC)C1',
+ '1,1,3,3,5,5-Hexamethyltrisiloxane': 'C[SiH](C)O[Si](C)(C)O[SiH](C)C',
+ '1,1,3,3-Tetramethyl-1,3-diphenyldisiloxane': 'C[Si](C1=CC=CC=C1)(C)O[Si](C)(C)C2=CC=CC=C2',
+ '1,1,3,3-Tetramethyldisiloxane': 'C[SiH](C)O[SiH](C)C',
+ '1,1,3,3-Tetramethylguanidine': 'N=C(N(C)C)N(C)C',
+ '1,1,4,7,10,10-Hexamethyltriethylenetetramine': 'CN(CCN(C)C)CCN(C)CCN(C)C',
+ '1,1,5,5-Tetrafluoro-2,4-pentanedione': 'O=C(CC(C(F)F)=O)C(F)F',
+ '1,10-Phenanthroline Monohydrate': '[H]O[H].C12=CC=C3C=CC=NC3=C1N=CC=C2',
+ '1,10-Phenanthroline-5,6-dione': 'O=C1C2=C(N=CC=C2)C3=C(C=CC=N3)C1=O',
"1,1'-Bi-2-naphthol": 'OC1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3O',
"1,1'-Carbonyldi(1,2,4-triazole)": 'O=C(N1N=CN=C1)N2N=CN=C2',
"1,1'-Carbonyldiimidazole": 'O=C(N1C=CN=C1)N2C=CN=C2',
"1,1'-Difluoro-2,2'-bipyridinium Bis(tetrafluoroborate)": 'F[N+]1=CC=CC=C1C2=CC=CC=[N+]2F.F[B-](F)(F)F.F[B-](F)(F)F',
- "1,1-Dimethyl-1,3-dihydrobenzo[c][1,2]oxasilole": 'C[Si]1(C)OCC2=CC=CC=C12',
- "1,1-Dimethylpropylmagnesium chloride": 'Cl[Mg]C(C)(C)CC',
+ '1,1-Dimethyl-1,3-dihydrobenzo[c][1,2]oxasilole': 'C[Si]1(C)OCC2=CC=CC=C12',
+ '1,1-Dimethylpropylmagnesium chloride': 'Cl[Mg]C(C)(C)CC',
"1,1'-Oxalyldiimidazole": 'O=C(N1C=CN=C1)C(N2C=CN=C2)=O',
- "1,2,3,4,5-Pentamethylcyclopentadiene": 'CC1C(C)=C(C)C(C)=C1C',
- "1,2,3,4,5-Pentaphenyl-1,3-cyclopentadiene": 'C1(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C(C5=CC=CC=C5)C1C6=CC=CC=C6',
- "1,2,3,4-Tetrahydroquinoline": 'C12=C(NCCC2)C=CC=C1',
- "1,2,3,4-Tetraphenyl-1,3-cyclopentadiene": 'C1(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C(C5=CC=CC=C5)C1',
- "1,2,4-Triazole": 'N1N=CN=C1',
- "1,2-Benzenedisulfonic Imide": 'O=S(C1=CC=CC=C1S2(=O)=O)(N2)=O',
- "1,2-Bis(3-indenyl)ethane": 'C1(CCC2=CCC3=C2C=CC=C3)=CCC4=C1C=CC=C4',
+ '1,2,3,4,5-Pentamethylcyclopentadiene': 'CC1C(C)=C(C)C(C)=C1C',
+ '1,2,3,4,5-Pentaphenyl-1,3-cyclopentadiene': 'C1(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C(C5=CC=CC=C5)C1C6=CC=CC=C6',
+ '1,2,3,4-Tetrahydroquinoline': 'C12=C(NCCC2)C=CC=C1',
+ '1,2,3,4-Tetraphenyl-1,3-cyclopentadiene': 'C1(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C(C5=CC=CC=C5)C1',
+ '1,2,4-Triazole': 'N1N=CN=C1',
+ '1,2-Benzenedisulfonic Imide': 'O=S(C1=CC=CC=C1S2(=O)=O)(N2)=O',
+ '1,2-Bis(3-indenyl)ethane': 'C1(CCC2=CCC3=C2C=CC=C3)=CCC4=C1C=CC=C4',
"1,2-Bis(4'-methyl-2,2'-bipyridin-4-yl)ethane": 'CC1=CC(C2=NC=CC(CCC3=CC(C4=NC=CC(C)=C4)=NC=C3)=C2)=NC=C1',
- "1,2-Bis(dimethylphosphino)ethane": 'CP(CCP(C)C)C',
- "1,2-Bis(diphenylphosphino)benzene": 'C1(P(C2=CC=CC=C2)C3=CC=CC=C3)=CC=CC=C1P(C4=CC=CC=C4)C5=CC=CC=C5',
- "1,2-Bis(diphenylphosphino)ethane": 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "1,2-Bis(phenylsulfinyl)ethane Palladium(II) Diacetate": 'O=S(CCS(C1=CC=CC=C1)=O)C2=CC=CC=C2.CC([O-])=O.CC([O-])=O.[Pd+2]',
- "1,2-Bis(tert-butylthio)ethane Borane": 'CC(SCCSC(C)(C)C)(C)C.B',
- "1,2-Bis(trichlorosilyl)ethane": 'Cl[Si](CC[Si](Cl)(Cl)Cl)(Cl)Cl',
- "1,2-Bis(triethoxysilyl)ethane": 'CCO[Si](CC[Si](OCC)(OCC)OCC)(OCC)OCC',
- "1,2-Bis(trimethylsilyl)benzene": 'C[Si](C1=CC=CC=C1[Si](C)(C)C)(C)C',
- "1,2-Bis[bis(pentafluorophenyl)phosphino]ethane": 'FC1=C(F)C(F)=C(F)C(F)=C1P(CCP(C2=C(F)C(F)=C(F)C(F)=C2F)C3=C(F)C(F)=C(F)C(F)=C3F)C4=C(F)C(F)=C(F)C(F)=C4F',
- "1,2-Dibromo-1,1,2,2-tetrachloroethane": 'ClC(Cl)(Br)C(Cl)(Br)Cl',
- "1,2-Dibromo-1,1,2,2-tetrafluoroethane": 'FC(F)(Br)C(F)(Br)F',
- "1,2-Dichlorotetramethyldisilane": 'Cl[Si](C)(C)[Si](C)(C)Cl',
- "1,2-Dimethyl-3-propylimidazolium Iodide": 'CCC[N+]1=C(C)N(C)C=C1.[I-]',
- "1,2-Phenylenediamine": 'NC1=CC=CC=C1N',
- "1,2-xylene": 'CC1=CC=CC=C1C',
- "1,3,5,7-Cyclooctatetraene": 'C1=C\\C=C/C=C\\C=C/1',
- "1,3,5-Cycloheptatriene": 'C1=CC=CC=CC1',
- "1,3,5-Trimethylbenzene": 'CC1=CC(C)=CC(C)=C1',
- "1,3,5-Tris(3,3,3-trifluoropropyl)-1,3,5-trimethylcyclotrisiloxane": 'C[Si]1(CCC(F)(F)F)O[Si](C)(CCC(F)(F)F)O[Si](C)(CCC(F)(F)F)O1',
- "1,3-Bis(2,4,6-trimethylphenyl)imidazolinium Chloride": 'CC1=C([N+]2=CN(C3=C(C)C=C(C)C=C3C)CC2)C(C)=CC(C)=C1.[Cl-]',
- "1,3-Bis(2,6-diisopropylphenyl)-1,3,2-diazaphospholidine 2-Oxide": 'CC(C1=C(N2P(N(C3=C(C(C)C)C=CC=C3C(C)C)CC2)=O)C(C(C)C)=CC=C1)C',
- "1,3-Bis(2,6-diisopropylphenyl)imidazol-2-ylidene": 'CC(C1=C(N2[C]N(C3=C(C(C)C)C=CC=C3C(C)C)C=C2)C(C(C)C)=CC=C1)C',
- "1,3-Bis(2,6-diisopropylphenyl)imidazolidin-2-ylidene": 'CC(C1=C(N2[C]N(C3=C(C(C)C)C=CC=C3C(C)C)CC2)C(C(C)C)=CC=C1)C',
- "1,3-Bis(2,6-diisopropylphenyl)imidazolinium Chloride": 'CC(C1=C([N+]2=CN(C3=C(C(C)C)C=CC=C3C(C)C)CC2)C(C(C)C)=CC=C1)C.[Cl-]',
- "1,3-Bis(2,6-diisopropylphenyl)imidazolium Chloride": 'CC(C1=C([N+]2=CN(C3=C(C(C)C)C=CC=C3C(C)C)C=C2)C(C(C)C)=CC=C1)C.[Cl-]',
- "1,3-Bis(4-hydroxybutyl)tetramethyldisiloxane": 'OCCCC[Si](C)(C)O[Si](C)(C)CCCCO',
- "1,3-Bis(4-methoxyphenyl)-1,3-propanedione": 'O=C(C1=CC=C(OC)C=C1)CC(C2=CC=C(OC)C=C2)=O',
- "1,3-Bis(chloromethyl)tetramethyldisiloxane": 'ClC[Si](C)(C)O[Si](C)(C)CCl',
- "1,3-Bis(diphenylphosphino)propane": 'P(CCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "1,3-Bis[(di-tert-butylphosphino)oxy]benzene": 'CC(P(OC1=CC(OP(C(C)(C)C)C(C)(C)C)=CC=C1)C(C)(C)C)(C)C',
- "1,3-Bis[(trimethylsilyl)ethynyl]benzene": 'C[Si](C#CC1=CC(C#C[Si](C)(C)C)=CC=C1)(C)C',
- "1,3-Di(1-adamantyl)imidazolinium Tetrafluoroborate": 'F[B-](F)(F)F.[N+]1(C23CC4CC(C3)CC(C4)C2)=CN(C56CC7CC(C6)CC(C7)C5)CC1',
- "1,3-Di(1-adamantyl)imidazolium Tetrafluoroborate": 'F[B-](F)(F)F.[N+]1(C23CC4CC(C3)CC(C4)C2)=CN(C56CC7CC(C6)CC(C7)C5)C=C1',
- "1,3-Di(2-pyridyl)-1,3-propanedione": 'O=C(C1=NC=CC=C1)CC(C2=NC=CC=C2)=O',
- "1,3-Dibromo-5,5-dimethylhydantoin": 'O=C(N1Br)N(Br)C(C)(C)C1=O',
- "1,3-Dicyclohexylimidazolium Tetrafluoroborate": 'F[B-](F)(F)F.[N+]1(C2CCCCC2)=CN(C3CCCCC3)C=C1',
- "1,3-Diiodo-5,5-dimethylhydantoin": 'O=C(N1I)N(I)C(C)(C)C1=O',
- "1,3-Diisopropylimidazolinium Tetrafluoroborate": 'CC([N+]1=CN(C(C)C)CC1)C.F[B-](F)(F)F',
- "1,3-Diisopropylimidazolium Tetrafluoroborate": 'CC([N+]1=CN(C(C)C)C=C1)C.F[B-](F)(F)F',
- "1,3-Dimesitylimidazol-2-ylidene": 'CC1=CC(C)=CC(C)=C1N2[C]N(C3=C(C)C=C(C)C=C3C)C=C2',
- "1,3-Dimesitylimidazolium Chloride": 'CC1=CC(C)=CC(C)=C1[N+]2=CN(C3=C(C)C=C(C)C=C3C)C=C2.[Cl-]',
- "1,3-Dimethoxy-1,1,3,3-tetraphenyldisiloxane": 'CO[Si](C1=CC=CC=C1)(C2=CC=CC=C2)O[Si](C3=CC=CC=C3)(OC)C4=CC=CC=C4',
- "1,3-Dimethylimidazolium Chloride": 'C[N+]1=CN(C)C=C1.[Cl-]',
- "1,3-Dimethylimidazolium Dimethyl Phosphate": 'C[N+]1=CN(C)C=C1.O=P(OC)([O-])OC',
- "1,3-Dimethylimidazolium Iodide": 'C[N+]1=CN(C)C=C1.[I-]',
- "1,3-Dimethylimidazolium Methyl Sulfate": 'C[N+]1=CN(C)C=C1.O=S(OC)([O-])=O',
- "1,3-Diphenyl-1,3-propanedione": 'O=C(C1=CC=CC=C1)CC(C2=CC=CC=C2)=O',
- "1,3-Di-tert-butylimidazol-2-ylidene": 'CC(N1[C]N(C(C)(C)C)C=C1)(C)C',
- "1,3-Di-tert-butylimidazolium Tetrafluoroborate": 'CC([N+]1=CN(C(C)(C)C)C=C1)(C)C.F[B-](F)(F)F',
- "1,3-Divinyltetramethyldisiloxane": 'C=C[Si](C)(C)O[Si](C)(C)C=C',
- "1,3-xylene": 'CC1=CC=CC(C)=C1',
- "1,4,7,10,13,16-Hexaazacyclooctadecane": 'N1CCNCCNCCNCCNCCNCC1',
- "1,4,7,10,13,16-Hexaazacyclooctadecane Hexahydrochloride": '[H]Cl.[H]Cl.[H]Cl.[H]Cl.[H]Cl.[H]Cl.N1CCNCCNCCNCCNCCNCC1',
- "1,4,7,10-Tetraazacyclododecane": 'N1CCNCCNCCNCC1',
- "1,4,7,10-Tetraazacyclododecane Tetrahydrochloride": '[H]Cl.[H]Cl.[H]Cl.[H]Cl.N1CCNCCNCCNCC1',
- "1,4,7,10-Tetraazacyclododecane-1,4,7,10-tetraacetic Acid": 'O=C(O)CN1CCN(CC(O)=O)CCN(CC(O)=O)CCN(CC(O)=O)CC1',
- "1,4,7,10-Tetrabenzyl-1,4,7,10-tetraazacyclododecane": 'N1(CC2=CC=CC=C2)CCN(CC3=CC=CC=C3)CCN(CC4=CC=CC=C4)CCN(CC5=CC=CC=C5)CC1',
- "1,4,7-Triazacyclononane": 'N1CCNCCNCC1',
- "1,4,7-Trimethyl-1,4,7-triazacyclononane (stabilized with NaHCO3)": 'CN1CCN(C)CCN(C)CC1',
- "1,4,8,11-Tetramethyl-1,4,8,11-tetraazacyclotetradecane": 'CN1CCN(C)CCCN(C)CCN(C)CCC1',
- "1,4-Bis(dimethylsilyl)benzene": 'C[SiH](C1=CC=C([SiH](C)C)C=C1)C',
- "1,4-Bis(diphenylphosphino)butane": 'P(CCCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "1,4-Bis(trimethylsilyl)-1,3-butadiyne": 'C[Si](C#CC#C[Si](C)(C)C)(C)C',
- "1,4-Cyclohexadiene": 'C1=CCC=CC1',
- "1,4-Cyclohexadiene (stabilized with BHT)": 'C1=CCC=CC1',
+ '1,2-Bis(dimethylphosphino)ethane': 'CP(CCP(C)C)C',
+ '1,2-Bis(diphenylphosphino)benzene': 'C1(P(C2=CC=CC=C2)C3=CC=CC=C3)=CC=CC=C1P(C4=CC=CC=C4)C5=CC=CC=C5',
+ '1,2-Bis(diphenylphosphino)ethane': 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ '1,2-Bis(phenylsulfinyl)ethane Palladium(II) Diacetate': 'O=S(CCS(C1=CC=CC=C1)=O)C2=CC=CC=C2.CC([O-])=O.CC([O-])=O.[Pd+2]',
+ '1,2-Bis(tert-butylthio)ethane Borane': 'CC(SCCSC(C)(C)C)(C)C.B',
+ '1,2-Bis(trichlorosilyl)ethane': 'Cl[Si](CC[Si](Cl)(Cl)Cl)(Cl)Cl',
+ '1,2-Bis(triethoxysilyl)ethane': 'CCO[Si](CC[Si](OCC)(OCC)OCC)(OCC)OCC',
+ '1,2-Bis(trimethylsilyl)benzene': 'C[Si](C1=CC=CC=C1[Si](C)(C)C)(C)C',
+ '1,2-Bis[bis(pentafluorophenyl)phosphino]ethane': 'FC1=C(F)C(F)=C(F)C(F)=C1P(CCP(C2=C(F)C(F)=C(F)C(F)=C2F)C3=C(F)C(F)=C(F)C(F)=C3F)C4=C(F)C(F)=C(F)C(F)=C4F',
+ '1,2-Dibromo-1,1,2,2-tetrachloroethane': 'ClC(Cl)(Br)C(Cl)(Br)Cl',
+ '1,2-Dibromo-1,1,2,2-tetrafluoroethane': 'FC(F)(Br)C(F)(Br)F',
+ '1,2-Dichlorotetramethyldisilane': 'Cl[Si](C)(C)[Si](C)(C)Cl',
+ '1,2-Dimethyl-3-propylimidazolium Iodide': 'CCC[N+]1=C(C)N(C)C=C1.[I-]',
+ '1,2-Phenylenediamine': 'NC1=CC=CC=C1N',
+ '1,2-xylene': 'CC1=CC=CC=C1C',
+ '1,3,5,7-Cyclooctatetraene': 'C1=C\\C=C/C=C\\C=C/1',
+ '1,3,5-Cycloheptatriene': 'C1=CC=CC=CC1',
+ '1,3,5-Trimethylbenzene': 'CC1=CC(C)=CC(C)=C1',
+ '1,3,5-Tris(3,3,3-trifluoropropyl)-1,3,5-trimethylcyclotrisiloxane': 'C[Si]1(CCC(F)(F)F)O[Si](C)(CCC(F)(F)F)O[Si](C)(CCC(F)(F)F)O1',
+ '1,3-Bis(2,4,6-trimethylphenyl)imidazolinium Chloride': 'CC1=C([N+]2=CN(C3=C(C)C=C(C)C=C3C)CC2)C(C)=CC(C)=C1.[Cl-]',
+ '1,3-Bis(2,6-diisopropylphenyl)-1,3,2-diazaphospholidine 2-Oxide': 'CC(C1=C(N2P(N(C3=C(C(C)C)C=CC=C3C(C)C)CC2)=O)C(C(C)C)=CC=C1)C',
+ '1,3-Bis(2,6-diisopropylphenyl)imidazol-2-ylidene': 'CC(C1=C(N2[C]N(C3=C(C(C)C)C=CC=C3C(C)C)C=C2)C(C(C)C)=CC=C1)C',
+ '1,3-Bis(2,6-diisopropylphenyl)imidazolidin-2-ylidene': 'CC(C1=C(N2[C]N(C3=C(C(C)C)C=CC=C3C(C)C)CC2)C(C(C)C)=CC=C1)C',
+ '1,3-Bis(2,6-diisopropylphenyl)imidazolinium Chloride': 'CC(C1=C([N+]2=CN(C3=C(C(C)C)C=CC=C3C(C)C)CC2)C(C(C)C)=CC=C1)C.[Cl-]',
+ '1,3-Bis(2,6-diisopropylphenyl)imidazolium Chloride': 'CC(C1=C([N+]2=CN(C3=C(C(C)C)C=CC=C3C(C)C)C=C2)C(C(C)C)=CC=C1)C.[Cl-]',
+ '1,3-Bis(4-hydroxybutyl)tetramethyldisiloxane': 'OCCCC[Si](C)(C)O[Si](C)(C)CCCCO',
+ '1,3-Bis(4-methoxyphenyl)-1,3-propanedione': 'O=C(C1=CC=C(OC)C=C1)CC(C2=CC=C(OC)C=C2)=O',
+ '1,3-Bis(chloromethyl)tetramethyldisiloxane': 'ClC[Si](C)(C)O[Si](C)(C)CCl',
+ '1,3-Bis(diphenylphosphino)propane': 'P(CCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ '1,3-Bis[(di-tert-butylphosphino)oxy]benzene': 'CC(P(OC1=CC(OP(C(C)(C)C)C(C)(C)C)=CC=C1)C(C)(C)C)(C)C',
+ '1,3-Bis[(trimethylsilyl)ethynyl]benzene': 'C[Si](C#CC1=CC(C#C[Si](C)(C)C)=CC=C1)(C)C',
+ '1,3-Di(1-adamantyl)imidazolinium Tetrafluoroborate': 'F[B-](F)(F)F.[N+]1(C23CC4CC(C3)CC(C4)C2)=CN(C56CC7CC(C6)CC(C7)C5)CC1',
+ '1,3-Di(1-adamantyl)imidazolium Tetrafluoroborate': 'F[B-](F)(F)F.[N+]1(C23CC4CC(C3)CC(C4)C2)=CN(C56CC7CC(C6)CC(C7)C5)C=C1',
+ '1,3-Di(2-pyridyl)-1,3-propanedione': 'O=C(C1=NC=CC=C1)CC(C2=NC=CC=C2)=O',
+ '1,3-Dibromo-5,5-dimethylhydantoin': 'O=C(N1Br)N(Br)C(C)(C)C1=O',
+ '1,3-Dicyclohexylimidazolium Tetrafluoroborate': 'F[B-](F)(F)F.[N+]1(C2CCCCC2)=CN(C3CCCCC3)C=C1',
+ '1,3-Diiodo-5,5-dimethylhydantoin': 'O=C(N1I)N(I)C(C)(C)C1=O',
+ '1,3-Diisopropylimidazolinium Tetrafluoroborate': 'CC([N+]1=CN(C(C)C)CC1)C.F[B-](F)(F)F',
+ '1,3-Diisopropylimidazolium Tetrafluoroborate': 'CC([N+]1=CN(C(C)C)C=C1)C.F[B-](F)(F)F',
+ '1,3-Dimesitylimidazol-2-ylidene': 'CC1=CC(C)=CC(C)=C1N2[C]N(C3=C(C)C=C(C)C=C3C)C=C2',
+ '1,3-Dimesitylimidazolium Chloride': 'CC1=CC(C)=CC(C)=C1[N+]2=CN(C3=C(C)C=C(C)C=C3C)C=C2.[Cl-]',
+ '1,3-Dimethoxy-1,1,3,3-tetraphenyldisiloxane': 'CO[Si](C1=CC=CC=C1)(C2=CC=CC=C2)O[Si](C3=CC=CC=C3)(OC)C4=CC=CC=C4',
+ '1,3-Dimethylimidazolium Chloride': 'C[N+]1=CN(C)C=C1.[Cl-]',
+ '1,3-Dimethylimidazolium Dimethyl Phosphate': 'C[N+]1=CN(C)C=C1.O=P(OC)([O-])OC',
+ '1,3-Dimethylimidazolium Iodide': 'C[N+]1=CN(C)C=C1.[I-]',
+ '1,3-Dimethylimidazolium Methyl Sulfate': 'C[N+]1=CN(C)C=C1.O=S(OC)([O-])=O',
+ '1,3-Diphenyl-1,3-propanedione': 'O=C(C1=CC=CC=C1)CC(C2=CC=CC=C2)=O',
+ '1,3-Di-tert-butylimidazol-2-ylidene': 'CC(N1[C]N(C(C)(C)C)C=C1)(C)C',
+ '1,3-Di-tert-butylimidazolium Tetrafluoroborate': 'CC([N+]1=CN(C(C)(C)C)C=C1)(C)C.F[B-](F)(F)F',
+ '1,3-Divinyltetramethyldisiloxane': 'C=C[Si](C)(C)O[Si](C)(C)C=C',
+ '1,3-xylene': 'CC1=CC=CC(C)=C1',
+ '1,4,7,10,13,16-Hexaazacyclooctadecane': 'N1CCNCCNCCNCCNCCNCC1',
+ '1,4,7,10,13,16-Hexaazacyclooctadecane Hexahydrochloride': '[H]Cl.[H]Cl.[H]Cl.[H]Cl.[H]Cl.[H]Cl.N1CCNCCNCCNCCNCCNCC1',
+ '1,4,7,10-Tetraazacyclododecane': 'N1CCNCCNCCNCC1',
+ '1,4,7,10-Tetraazacyclododecane Tetrahydrochloride': '[H]Cl.[H]Cl.[H]Cl.[H]Cl.N1CCNCCNCCNCC1',
+ '1,4,7,10-Tetraazacyclododecane-1,4,7,10-tetraacetic Acid': 'O=C(O)CN1CCN(CC(O)=O)CCN(CC(O)=O)CCN(CC(O)=O)CC1',
+ '1,4,7,10-Tetrabenzyl-1,4,7,10-tetraazacyclododecane': 'N1(CC2=CC=CC=C2)CCN(CC3=CC=CC=C3)CCN(CC4=CC=CC=C4)CCN(CC5=CC=CC=C5)CC1',
+ '1,4,7-Triazacyclononane': 'N1CCNCCNCC1',
+ '1,4,7-Trimethyl-1,4,7-triazacyclononane (stabilized with NaHCO3)': 'CN1CCN(C)CCN(C)CC1',
+ '1,4,8,11-Tetramethyl-1,4,8,11-tetraazacyclotetradecane': 'CN1CCN(C)CCCN(C)CCN(C)CCC1',
+ '1,4-Bis(dimethylsilyl)benzene': 'C[SiH](C1=CC=C([SiH](C)C)C=C1)C',
+ '1,4-Bis(diphenylphosphino)butane': 'P(CCCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ '1,4-Bis(trimethylsilyl)-1,3-butadiyne': 'C[Si](C#CC#C[Si](C)(C)C)(C)C',
+ '1,4-Cyclohexadiene': 'C1=CCC=CC1',
+ '1,4-Cyclohexadiene (stabilized with BHT)': 'C1=CCC=CC1',
"1,4-Di[[2,2':6',2''-terpyridin]-4'-yl]benzene": 'C1(C2=CC(C3=NC=CC=C3)=NC(C4=NC=CC=C4)=C2)=CC=C(C5=CC(C6=NC=CC=C6)=NC(C7=NC=CC=C7)=C5)C=C1',
- "1,4-Diazabicyclo[2.2.2]octane": 'N1(CC2)CCN2CC1',
- "1,4-Dimethyl-1,2,4-triazolium Iodide": 'CN1C=N[N+](C)=C1.[I-]',
- "1,4-dioxane": 'C1COCCO1',
- "1,4-xylene": 'CC1=CC=C(C)C=C1',
- "1,5,7-Triazabicyclo[4.4.0]dec-5-ene": 'N12CCCN=C1NCCC2',
- "1,5,9-Triazacyclododecane": 'N1CCCNCCCNCCC1',
- "1,5-Bis(diphenylphosphino)pentane": 'P(CCCCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "1,5-Cyclooctadiene": 'C1=C\\CC/C=C\\CC/1',
+ '1,4-Diazabicyclo[2.2.2]octane': 'N1(CC2)CCN2CC1',
+ '1,4-Dimethyl-1,2,4-triazolium Iodide': 'CN1C=N[N+](C)=C1.[I-]',
+ '1,4-dioxane': 'C1COCCO1',
+ '1,4-xylene': 'CC1=CC=C(C)C=C1',
+ '1,5,7-Triazabicyclo[4.4.0]dec-5-ene': 'N12CCCN=C1NCCC2',
+ '1,5,9-Triazacyclododecane': 'N1CCCNCCCNCCC1',
+ '1,5-Bis(diphenylphosphino)pentane': 'P(CCCCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ '1,5-Cyclooctadiene': 'C1=C\\CC/C=C\\CC/1',
"1,5-Cyclooctadiene [stabilized with Octadecyl 3-(3',5'-Di-tert-butyl-4'-hydroxyphenyl)propionate]": 'C1=C\\CC/C=C\\CC/1',
- "1,5-Diazabicyclo[4.3.0]-5-nonene": 'N12CCCN=C1CCC2',
- "1,5-Diazabicyclo[4.3.0]non-5-ene": 'N12CCCN=C1CCC2',
- "1,5-Dichloro-1,1,3,3,5,5-hexamethyltrisiloxane": 'C[Si](C)(Cl)O[Si](C)(C)O[Si](C)(Cl)C',
- "1,5-Dimethyl-2,4-bis[2-(trimethylsilyl)ethynyl]benzene": 'C[Si](C#CC1=C(C)C=C(C)C(C#C[Si](C)(C)C)=C1)(C)C',
- "1,5-Hexadiene": 'C=CCCC=C',
- "1,6-Bis(diphenylphosphino)hexane": 'P(CCCCCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "1,7-Dichloro-1,1,3,3,5,5,7,7-octamethyltetrasiloxane": 'C[Si](C)(Cl)O[Si](C)(C)O[Si](C)(C)O[Si](C)(Cl)C',
- "1,8-Bis(dimethylamino)naphthalene": 'CN(C1=CC=CC2=CC=CC(N(C)C)=C12)C',
- "1,8-Bis(diphenylphosphino)naphthalene": 'C1(P(C2=CC=CC=C2)C3=CC=CC=C3)=C4C(P(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC4=CC=C1',
- "1,8-Diazabicyclo[5.4.0]-7-undecene": 'N12CCCCCC1=NCCC2',
- "1,8-Diazabicyclo[5.4.0]-7-undecene Hydrogen Tribromide": 'N12CCCCCC1=NCCC2.[H+].[Br-].[Br-].[Br-]',
- "1,8-Diazabicyclo[5.4.0]undec-7-ene": 'N12CCCCCC1=NCCC2',
- "1-[2-(Di-tert-butylphosphino)phenyl]-3,5-diphenyl-1H-pyrazole": 'CC(P(C1=CC=CC=C1N2N=C(C3=CC=CC=C3)C=C2C4=CC=CC=C4)C(C)(C)C)(C)C',
- "1-[3-(Trimethoxysilyl)propyl]urea": 'O=C(N)NCCC[Si](OC)(OC)OC',
- "1-[Bis(trifluoromethanesulfonyl)methyl]-2,3,4,5,6-pentafluorobenzene": 'FC1=C(C(S(=O)(C(F)(F)F)=O)S(=O)(C(F)(F)F)=O)C(F)=C(F)C(F)=C1F',
- "10-Methyl-9-phenylacridinium Perchlorate": 'C[N+]1=C2C=CC=CC2=C(C3=CC=CC=C3)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
- "10-Methylacridinium Perchlorate": 'C[N+]1=C2C=CC=CC2=CC3=C1C=CC=C3.O=Cl(=O)([O-])=O',
- "1-Acetoxy-5-bromo-1,2-benziodoxol-3(1H)-one": 'O=C1OI(OC(C)=O)C2=CC=C(Br)C=C12',
- "1-Allyl-3-methylimidazolium Chloride": 'C[N+]1=CN(CC=C)C=C1.[Cl-]',
- "1-Bromo-3-(trimethylsilyl)benzene": 'C[Si](C1=CC(Br)=CC=C1)(C)C',
- "1-Bromo-4-(trimethylsilyl)benzene": 'C[Si](C1=CC=C(Br)C=C1)(C)C',
- "1-Butyl-1-methylpiperidinium Bis(trifluoromethanesulfonyl)imide": 'C[N+]1(CCCC)CCCCC1.O=S([N-]S(=O)(C(F)(F)F)=O)(C(F)(F)F)=O',
- "1-Butyl-1-methylpiperidinium Bromide": 'C[N+]1(CCCC)CCCCC1.[Br-]',
- "1-Butyl-1-methylpyrrolidinium Bis(trifluoromethanesulfonyl)imide": 'C[N+]1(CCCC)CCCC1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "1-Butyl-1-methylpyrrolidinium Bromide": 'C[N+]1(CCCC)CCCC1.[Br-]',
- "1-Butyl-1-methylpyrrolidinium Chloride": 'C[N+]1(CCCC)CCCC1.[Cl-]',
- "1-Butyl-1-methylpyrrolidinium Dicyanamide": 'C[N+]1(CCCC)CCCC1.N#C[N-]C#N',
- "1-Butyl-1-methylpyrrolidinium Trifluoromethanesulfonate": 'C[N+]1(CCCC)CCCC1.O=S(C(F)(F)F)([O-])=O',
- "1-Butyl-2,3-dimethylimidazolium Bis(trifluoromethanesulfonyl)imide": 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CC1=[N+](C)C=CN1CCCC',
- "1-Butyl-2,3-dimethylimidazolium Chloride": 'C[N+]1=C(C)N(CCCC)C=C1.[Cl-]',
- "1-Butyl-2,3-dimethylimidazolium Hexafluorophosphate": 'C[N+]1=C(C)N(CCCC)C=C1.F[P-](F)(F)(F)(F)F',
- "1-Butyl-2,3-dimethylimidazolium Tetrafluoroborate": 'C[N+]1=C(C)N(CCCC)C=C1.F[B-](F)(F)F',
- "1-Butyl-2,3-dimethylimidazolium Trifluoromethanesulfonate": 'C[N+]1=C(C)N(CCCC)C=C1.O=S(C(F)(F)F)([O-])=O',
- "1-Butyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide": 'C[N+]1=CN(CCCC)C=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "1-Butyl-3-methylimidazolium Bromide": 'C[N+]1=CN(CCCC)C=C1.[Br-]',
- "1-Butyl-3-methylimidazolium Chloride": 'C[N+]1=CN(CCCC)C=C1.[Cl-]',
- "1-Butyl-3-methylimidazolium Dicyanamide": 'C[N+]1=CN(CCCC)C=C1.N#C[N-]C#N',
- "1-Butyl-3-methylimidazolium Hexafluorophosphate": 'C[N+]1=CN(CCCC)C=C1.F[P-](F)(F)(F)(F)F',
- "1-Butyl-3-methylimidazolium Iodide": 'C[N+]1=CN(CCCC)C=C1.[I-]',
- "1-Butyl-3-methylimidazolium Methanesulfonate": 'C[N+]1=CN(CCCC)C=C1.CS(=O)([O-])=O',
- "1-Butyl-3-methylimidazolium Methyl Sulfate": 'C[N+]1=CN(CCCC)C=C1.O=S(OC)([O-])=O',
- "1-Butyl-3-methylimidazolium Tetrachloroferrate": 'C[N+]1=CN(CCCC)C=C1.Cl[Fe-](Cl)(Cl)Cl',
- "1-Butyl-3-methylimidazolium Tetrafluoroborate": 'C[N+]1=CN(CCCC)C=C1.F[B-](F)(F)F',
- "1-Butyl-3-methylimidazolium Thiocyanate": 'C[N+]1=CN(CCCC)C=C1.[S-]C#N',
- "1-Butyl-3-methylimidazolium Tribromide": 'C[N+]1=CN(CCCC)C=C1.[Br-].[Br-].[Br-]',
- "1-Butyl-3-methylimidazolium Tricyanomethanide": 'C[N+]1=CN(CCCC)C=C1.N#C[C-](C#N)C#N',
- "1-Butyl-3-methylimidazolium Trifluoro(trifluoromethyl)borate": 'C[N+]1=CN(CCCC)C=C1.FC([B-](F)(F)F)(F)F',
- "1-Butyl-3-methylimidazolium Trifluoroacetate": 'C[N+]1=CN(CCCC)C=C1.O=C([O-])C(F)(F)F',
- "1-Butyl-3-methylimidazolium Trifluoromethanesulfonate": 'C[N+]1=CN(CCCC)C=C1.O=S(C(F)(F)F)([O-])=O',
- "1-Butyl-3-methylpyridinium Bromide": 'CC1=C[N+](CCCC)=CC=C1.[Br-]',
- "1-Butyl-3-methylpyridinium Chloride": 'CC1=C[N+](CCCC)=CC=C1.[Cl-]',
- "1-Butyl-4-methylpyridinium Bromide": 'CC1=CC=[N+](CCCC)C=C1.[Br-]',
- "1-Butyl-4-methylpyridinium Chloride": 'CC1=CC=[N+](CCCC)C=C1.[Cl-]',
- "1-Butyl-4-methylpyridinium Hexafluorophosphate": 'CC1=CC=[N+](CCCC)C=C1.F[P-](F)(F)(F)(F)F',
- "1-Butylpyridinium Bis(trifluoromethanesulfonyl)imide": 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CCCC[N+]1=CC=CC=C1',
- "1-Butylpyridinium Bromide": 'CCCC[N+]1=CC=CC=C1.[Br-]',
- "1-Butylpyridinium Chloride": 'CCCC[N+]1=CC=CC=C1.[Cl-]',
- "1-Butylpyridinium Hexafluorophosphate": 'CCCC[N+]1=CC=CC=C1.F[P-](F)(F)(F)(F)F',
- "1-Butylpyridinium Tetrafluoroborate": 'CCCC[N+]1=CC=CC=C1.F[B-](F)(F)F',
- "1-Chloro-2-iodoethane": 'ICCCl',
- "1-Cyclohexyl-3-(2-morpholinoethyl)carbodiimide Metho-p-toluenesulfonate": 'C[N+]1(CCN=C=NC2CCCCC2)CCOCC1.O=S(C3=CC=C(C)C=C3)([O-])=O',
- "1-Cyclopentenylboronic Acid": 'OB(C1=CCCC1)O',
- "1-Decyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide": 'C[N+]1=CN(CCCCCCCCCC)C=C1.O=S(C(F)(F)F)([N-]S(C(F)(F)F)(=O)=O)=O',
- "1-Decyl-3-methylimidazolium Bromide": 'C[N+]1=CN(CCCCCCCCCC)C=C1.[Br-]',
- "1-Decyl-3-methylimidazolium Chloride": 'C[N+]1=CN(CCCCCCCCCC)C=C1.[Cl-]',
- "1-Ethoxycarbonyl-2-ethoxy-1,2-dihydroquinoline": 'CCOC1N(C(OCC)=O)C2=C(C=CC=C2)C=C1',
- "1-Ethyl-1-methylpyrrolidinium Bromide": 'C[N+]1(CC)CCCC1.[Br-]',
- "1-Ethyl-1-methylpyrrolidinium Tetrafluoroborate": 'C[N+]1(CC)CCCC1.F[B-](F)(F)F',
- "1-Ethyl-2,3-dimethylimidazolium Bis(trifluoromethanesulfonyl)imide": 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CC1=[N+](C)C=CN1CC',
- "1-Ethyl-2-methylpyridinium Bromide": 'CC1=CC=CC=[N+]1CC.[Br-]',
- "1-Ethyl-3-(hydroxymethyl)pyridinium Ethyl Sulfate": 'OCC1=C[N+](CC)=CC=C1.O=S(OCC)([O-])=O',
- "1-Ethyl-3-methylimidazolium Acetate": 'C[N+]1=CN(CC)C=C1.CC([O-])=O',
- "1-Ethyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide": 'C[N+]1=CN(CC)C=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "1-Ethyl-3-methylimidazolium Bromide": 'C[N+]1=CN(CC)C=C1.[Br-]',
- "1-Ethyl-3-methylimidazolium Chloride": 'C[N+]1=CN(CC)C=C1.[Cl-]',
- "1-Ethyl-3-methylimidazolium Dicyanamide": 'CCN1C=[N+](C)C=C1.N#C[N-]C#N',
- "1-Ethyl-3-methylimidazolium Diethyl Phosphate": 'C[N+]1=CN(CC)C=C1.O=P(OCC)([O-])OCC',
- "1-Ethyl-3-methylimidazolium Ethyl Sulfate": 'C[N+]1=CN(CC)C=C1.O=S(OCC)([O-])=O',
- "1-Ethyl-3-methylimidazolium Hexafluorophosphate": 'C[N+]1=CN(CC)C=C1.F[P-](F)(F)(F)(F)F',
- "1-Ethyl-3-methylimidazolium Hydrogen Sulfate": 'C[N+]1=CN(CC)C=C1.O=S(O)([O-])=O',
- "1-Ethyl-3-methylimidazolium Iodide": 'C[N+]1=CN(CC)C=C1.[I-]',
- "1-Ethyl-3-methylimidazolium Methanesulfonate": 'C[N+]1=CN(CC)C=C1.CS(=O)([O-])=O',
- "1-Ethyl-3-methylimidazolium Methyl Sulfate": 'C[N+]1=CN(CC)C=C1.O=S(OC)([O-])=O',
- "1-Ethyl-3-methylimidazolium Nitrate": 'C[N+]1=CN(CC)C=C1.[O-][N+]([O-])=O',
- "1-Ethyl-3-methylimidazolium Tetrachloroferrate": 'C[N+]1=CN(CC)C=C1.Cl[Fe-](Cl)(Cl)Cl',
- "1-Ethyl-3-methylimidazolium Tetrafluoroborate": 'C[N+]1=CN(CC)C=C1.F[B-](F)(F)F',
- "1-Ethyl-3-methylimidazolium Thiocyanate": 'C[N+]1=CN(CC)C=C1.[S-]C#N',
- "1-Ethyl-3-methylimidazolium Tricyanomethanide": 'C[N+]1=CN(CC)C=C1.N#C[C-](C#N)C#N',
- "1-Ethyl-3-methylimidazolium Trifluoro(trifluoromethyl)borate": 'C[N+]1=CN(CC)C=C1.FC([B-](F)(F)F)(F)F',
- "1-Ethyl-3-methylimidazolium Trifluoroacetate": 'C[N+]1=CN(CC)C=C1.O=C([O-])C(F)(F)F',
- "1-Ethyl-3-methylimidazolium Trifluoromethanesulfonate": 'C[N+]1=CN(CC)C=C1.O=S(C(F)(F)F)([O-])=O',
- "1-Ethyl-3-methylimidazolium p-Toluenesulfonate": 'C[N+]1=CN(CC)C=C1.CC2=CC=C(S(=O)([O-])=O)C=C2',
- "1-Ethyl-3-methylpyridinium Bis(trifluoromethanesulfonyl)imide": 'CC1=CC=C[N+](CC)=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "1-Ethyl-3-methylpyridinium Ethyl Sulfate": 'CC1=C[N+](CC)=CC=C1.O=S(OCC)([O-])=O',
- "1-Ethyl-4-methylpyridinium Bromide": 'CC1=CC=[N+](CC)C=C1.[Br-]',
- "1-Ethylpyridinium Bromide": 'CC[N+]1=CC=CC=C1.[Br-]',
- "1-Ethylpyridinium Chloride": 'CC[N+]1=CC=CC=C1.[Cl-]',
- "1-Fluoro-2,4,6-trimethylpyridinium Tetrafluoroborate": 'CC1=[N+](F)C(C)=CC(C)=C1.F[B-](F)(F)F',
- "1-Fluoro-2,4,6-trimethylpyridinium Trifluoromethanesulfonate": 'CC1=[N+](F)C(C)=CC(C)=C1.O=S(C(F)(F)F)([O-])=O',
- "1-Fluoro-2,6-dichloropyridinium Tetrafluoroborate": 'ClC1=[N+](F)C(Cl)=CC=C1.F[B-](F)(F)F',
- "1-Fluoro-3,3-dimethyl-1,2-benziodoxole": 'CC1(C)OI(F)C2=CC=CC=C12',
- "1-Fluoropyridinium Tetrafluoroborate": 'F[N+]1=CC=CC=C1.F[B-](F)(F)F',
- "1-Fluoropyridinium Trifluoromethanesulfonate": 'F[N+]1=CC=CC=C1.O=S(C(F)(F)F)([O-])=O',
- "1H-Benzotriazol-1-yloxytripyrrolidinophosphonium Hexafluorophosphate": 'F[P-](F)(F)(F)(F)F.N1([P+](N2CCCC2)(ON3N=NC4=CC=CC=C43)N5CCCC5)CCCC1',
- "1H-Benzotriazol-1-yloxytris(dimethylamino)phosphonium Hexafluorophosphate": 'CN([P+](N(C)C)(ON1N=NC2=CC=CC=C21)N(C)C)C.F[P-](F)(F)(F)(F)F',
- "1H-Cyclopenta[l]phenanthrene": 'C12=CC=CC=C1C(CC=C3)=C3C4=C2C=CC=C4',
- "1-Hexyl-2,3-dimethylimidazolium Iodide": 'C[N+]1=C(C)N(CCCCCC)C=C1.[I-]',
- "1-Hexyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide": 'C[N+]1=CN(CCCCCC)C=C1.O=S([N-]S(=O)(C(F)(F)F)=O)(C(F)(F)F)=O',
- "1-Hexyl-3-methylimidazolium Bromide": 'C[N+]1=CN(CCCCCC)C=C1.[Br-]',
- "1-Hexyl-3-methylimidazolium Chloride": 'C[N+]1=CN(CCCCCC)C=C1.[Cl-]',
- "1-Hexyl-3-methylimidazolium Hexafluorophosphate": 'C[N+]1=CN(CCCCCC)C=C1.F[P-](F)(F)(F)(F)F',
- "1-Hexyl-3-methylimidazolium Iodide": 'C[N+]1=CN(CCCCCC)C=C1.[I-]',
- "1-Hexyl-3-methylimidazolium Tetrafluoroborate": 'C[N+]1=CN(CCCCCC)C=C1.F[B-](F)(F)F',
- "1-Hexyl-3-methylimidazolium Trifluoromethanesulfonate": 'C[N+]1=CN(CCCCCC)C=C1.O=S(C(F)(F)F)([O-])=O',
- "1-Hexylpyridinium Hexafluorophosphate": 'CCCCCC[N+]1=CC=CC=C1.F[P-](F)(F)(F)(F)F',
- "1-Hydroxy-6-(trifluoromethyl)benzotriazole": 'FC(C1=CC=C2N=NN(O)C2=C1)(F)F',
- "1-Methoxy-3-(trimethylsilyloxy)-1,3-butadiene": 'C=C(O[Si](C)(C)C)/C=C/OC',
- "1-Methyl-1-[4-(diphenylphosphino)benzyl]pyrrolidinium Bromide": 'C[N+]1(CC2=CC=C(P(C3=CC=CC=C3)C4=CC=CC=C4)C=C2)CCCC1.[Br-]',
- "1-Methyl-1-propylpiperidinium Bis(fluorosulfonyl)imide": 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.C[N+]1(CCC)CCCCC1',
- "1-Methyl-1-propylpiperidinium Bromide": 'CCC[N+]1(C)CCCCC1.[Br-]',
- "1-Methyl-1-propylpyrrolidinium Bis(trifluoromethanesulfonyl)imide": 'O=S(NS(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.C[N+]1(CCC)CCCC1',
- "1-Methyl-2-pyrrolidinone": 'O=C1CCCN1C',
- "1-Methyl-3-n-octylimidazolium Bromide": 'CCCCCCCC[N+]1=CN(C)C=C1.[Br-]',
- "1-Methyl-3-n-octylimidazolium Chloride": 'CCCCCCCC[N+]1=CN(C)C=C1.[Cl-]',
- "1-Methyl-3-n-octylimidazolium Hexafluorophosphate": 'CCCCCCCC[N+]1=CN(C)C=C1.F[P-](F)(F)(F)(F)F',
- "1-Methyl-3-n-octylimidazolium Tetrafluoroborate": 'CCCCCCCC[N+]1=CN(C)C=C1.F[B-](F)(F)F',
- "1-Methyl-3-n-octylimidazolium Trifluoromethanesulfonate": 'CCCCCCCC[N+]1=CN(C)C=C1.O=S(C(F)(F)F)([O-])=O',
- "1-Methyl-3-pentylimidazolium Bromide": 'CCCCC[N+]1=CN(C)C=C1.[Br-]',
- "1-Methyl-3-pentylimidazolium Tetrafluoroborate": 'CCCCC[N+]1=CN(C)C=C1.F[B-](F)(F)F',
- "1-Methyl-3-propylimidazolium Bromide": 'CCC[N+]1=CN(C)C=C1.[Br-]',
- "1-Methyl-3-propylimidazolium Chloride": 'CCC[N+]1=CN(C)C=C1.[Cl-]',
- "1-Methyl-3-propylimidazolium Iodide": 'CCC[N+]1=CN(C)C=C1.[I-]',
- "1-Methyl-3-propylimidazolium Tetrafluoroborate": 'CCC[N+]1=CN(C)C=C1.F[B-](F)(F)F',
- "1-Phenyl-1,3-butanedione": 'CC(CC(C1=CC=CC=C1)=O)=O',
- "1-Phenyl-2-(trimethylsilyl)acetylene": 'C[Si](C#CC1=CC=CC=C1)(C)C',
- "1-Propylpyridinium Chloride": 'CCC[N+]1=CC=CC=C1.[Cl-]',
- "1-Trifluoromethyl-1,2-benziodoxol-3(1H)-one": 'O=C1OI(C(F)(F)F)C2=CC=CC=C12',
- "1-Trifluoromethyl-3,3-dimethyl-1,2-benziodoxole": 'CC1(C)OI(C(F)(F)F)C2=CC=CC=C12',
- "2-(1H-1,2,4-Triazol-3-yl)pyridine": 'C1(C2=NNC=N2)=NC=CC=C1',
- "2-(2-Bromophenyl)-2,3-dihydro-1H-naphtho[1,8-de][1,3,2]diazaborine": 'BrC(C=CC=C1)=C1B(N2)NC3=CC=CC4=C3C2=CC=C4',
- "2-(2-Chloro-6-fluorophenyl)ethylamine hydrochloride": 'NCCC1=C(F)C=CC=C1Cl.[H]Cl',
- "2-(2-Hydroxyphenyl)benzothiazole": 'OC1=CC=CC=C1C2=NC3=CC=CC=C3S2',
- "2-(2-Hydroxyphenyl)benzoxazole": 'OC1=CC=CC=C1C2=NC3=CC=CC=C3O2',
- "2-(2-Pyridyl)benzoxazole": 'C1(C2=NC=CC=C2)=NC3=CC=CC=C3O1',
- "2-(2-Pyridyl)indole": 'C(N1)(C2=NC=CC=C2)=CC3=C1C=CC=C3',
- "2-(3,4-Epoxycyclohexyl)ethyltrimethoxysilane": 'CO[Si](OC)(CCC1CC(O2)C2CC1)OC',
- "2-(3-Bromophenyl)-2,3-dihydro-1H-naphtho[1,8-de][1,3,2]diazaborine": 'BrC1=CC=CC(B(N2)NC3=CC=CC4=C3C2=CC=C4)=C1',
- "2-(4-Bromophenyl)-2,3-dihydro-1H-naphtho[1,8-de][1,3,2]diazaborine": 'BrC1=CC=C(C=C1)B(N2)NC3=CC=CC4=CC=CC2=C43',
- "2-(4-Thiazolyl)benzimidazole": 'C1(C2=CSC=N2)=NC3=CC=CC=C3N1',
- "2-(5-Norbornene-2,3-dicarboximido)-1,1,3,3-tetramethyluronium Tetrafluoroborate": 'CN(C)C(N(C)C)=[O+]N(C1=O)C(C2C1C3C=CC2C3)=O.F[B-](F)(F)F',
+ '1,5-Diazabicyclo[4.3.0]-5-nonene': 'N12CCCN=C1CCC2',
+ '1,5-Diazabicyclo[4.3.0]non-5-ene': 'N12CCCN=C1CCC2',
+ '1,5-Dichloro-1,1,3,3,5,5-hexamethyltrisiloxane': 'C[Si](C)(Cl)O[Si](C)(C)O[Si](C)(Cl)C',
+ '1,5-Dimethyl-2,4-bis[2-(trimethylsilyl)ethynyl]benzene': 'C[Si](C#CC1=C(C)C=C(C)C(C#C[Si](C)(C)C)=C1)(C)C',
+ '1,5-Hexadiene': 'C=CCCC=C',
+ '1,6-Bis(diphenylphosphino)hexane': 'P(CCCCCCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ '1,7-Dichloro-1,1,3,3,5,5,7,7-octamethyltetrasiloxane': 'C[Si](C)(Cl)O[Si](C)(C)O[Si](C)(C)O[Si](C)(Cl)C',
+ '1,8-Bis(dimethylamino)naphthalene': 'CN(C1=CC=CC2=CC=CC(N(C)C)=C12)C',
+ '1,8-Bis(diphenylphosphino)naphthalene': 'C1(P(C2=CC=CC=C2)C3=CC=CC=C3)=C4C(P(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC4=CC=C1',
+ '1,8-Diazabicyclo[5.4.0]-7-undecene': 'N12CCCCCC1=NCCC2',
+ '1,8-Diazabicyclo[5.4.0]-7-undecene Hydrogen Tribromide': 'N12CCCCCC1=NCCC2.[H+].[Br-].[Br-].[Br-]',
+ '1,8-Diazabicyclo[5.4.0]undec-7-ene': 'N12CCCCCC1=NCCC2',
+ '1-[2-(Di-tert-butylphosphino)phenyl]-3,5-diphenyl-1H-pyrazole': 'CC(P(C1=CC=CC=C1N2N=C(C3=CC=CC=C3)C=C2C4=CC=CC=C4)C(C)(C)C)(C)C',
+ '1-[3-(Trimethoxysilyl)propyl]urea': 'O=C(N)NCCC[Si](OC)(OC)OC',
+ '1-[Bis(trifluoromethanesulfonyl)methyl]-2,3,4,5,6-pentafluorobenzene': 'FC1=C(C(S(=O)(C(F)(F)F)=O)S(=O)(C(F)(F)F)=O)C(F)=C(F)C(F)=C1F',
+ '10-Methyl-9-phenylacridinium Perchlorate': 'C[N+]1=C2C=CC=CC2=C(C3=CC=CC=C3)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
+ '10-Methylacridinium Perchlorate': 'C[N+]1=C2C=CC=CC2=CC3=C1C=CC=C3.O=Cl(=O)([O-])=O',
+ '1-Acetoxy-5-bromo-1,2-benziodoxol-3(1H)-one': 'O=C1OI(OC(C)=O)C2=CC=C(Br)C=C12',
+ '1-Allyl-3-methylimidazolium Chloride': 'C[N+]1=CN(CC=C)C=C1.[Cl-]',
+ '1-Bromo-3-(trimethylsilyl)benzene': 'C[Si](C1=CC(Br)=CC=C1)(C)C',
+ '1-Bromo-4-(trimethylsilyl)benzene': 'C[Si](C1=CC=C(Br)C=C1)(C)C',
+ '1-Butyl-1-methylpiperidinium Bis(trifluoromethanesulfonyl)imide': 'C[N+]1(CCCC)CCCCC1.O=S([N-]S(=O)(C(F)(F)F)=O)(C(F)(F)F)=O',
+ '1-Butyl-1-methylpiperidinium Bromide': 'C[N+]1(CCCC)CCCCC1.[Br-]',
+ '1-Butyl-1-methylpyrrolidinium Bis(trifluoromethanesulfonyl)imide': 'C[N+]1(CCCC)CCCC1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ '1-Butyl-1-methylpyrrolidinium Bromide': 'C[N+]1(CCCC)CCCC1.[Br-]',
+ '1-Butyl-1-methylpyrrolidinium Chloride': 'C[N+]1(CCCC)CCCC1.[Cl-]',
+ '1-Butyl-1-methylpyrrolidinium Dicyanamide': 'C[N+]1(CCCC)CCCC1.N#C[N-]C#N',
+ '1-Butyl-1-methylpyrrolidinium Trifluoromethanesulfonate': 'C[N+]1(CCCC)CCCC1.O=S(C(F)(F)F)([O-])=O',
+ '1-Butyl-2,3-dimethylimidazolium Bis(trifluoromethanesulfonyl)imide': 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CC1=[N+](C)C=CN1CCCC',
+ '1-Butyl-2,3-dimethylimidazolium Chloride': 'C[N+]1=C(C)N(CCCC)C=C1.[Cl-]',
+ '1-Butyl-2,3-dimethylimidazolium Hexafluorophosphate': 'C[N+]1=C(C)N(CCCC)C=C1.F[P-](F)(F)(F)(F)F',
+ '1-Butyl-2,3-dimethylimidazolium Tetrafluoroborate': 'C[N+]1=C(C)N(CCCC)C=C1.F[B-](F)(F)F',
+ '1-Butyl-2,3-dimethylimidazolium Trifluoromethanesulfonate': 'C[N+]1=C(C)N(CCCC)C=C1.O=S(C(F)(F)F)([O-])=O',
+ '1-Butyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide': 'C[N+]1=CN(CCCC)C=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ '1-Butyl-3-methylimidazolium Bromide': 'C[N+]1=CN(CCCC)C=C1.[Br-]',
+ '1-Butyl-3-methylimidazolium Chloride': 'C[N+]1=CN(CCCC)C=C1.[Cl-]',
+ '1-Butyl-3-methylimidazolium Dicyanamide': 'C[N+]1=CN(CCCC)C=C1.N#C[N-]C#N',
+ '1-Butyl-3-methylimidazolium Hexafluorophosphate': 'C[N+]1=CN(CCCC)C=C1.F[P-](F)(F)(F)(F)F',
+ '1-Butyl-3-methylimidazolium Iodide': 'C[N+]1=CN(CCCC)C=C1.[I-]',
+ '1-Butyl-3-methylimidazolium Methanesulfonate': 'C[N+]1=CN(CCCC)C=C1.CS(=O)([O-])=O',
+ '1-Butyl-3-methylimidazolium Methyl Sulfate': 'C[N+]1=CN(CCCC)C=C1.O=S(OC)([O-])=O',
+ '1-Butyl-3-methylimidazolium Tetrachloroferrate': 'C[N+]1=CN(CCCC)C=C1.Cl[Fe-](Cl)(Cl)Cl',
+ '1-Butyl-3-methylimidazolium Tetrafluoroborate': 'C[N+]1=CN(CCCC)C=C1.F[B-](F)(F)F',
+ '1-Butyl-3-methylimidazolium Thiocyanate': 'C[N+]1=CN(CCCC)C=C1.[S-]C#N',
+ '1-Butyl-3-methylimidazolium Tribromide': 'C[N+]1=CN(CCCC)C=C1.[Br-].[Br-].[Br-]',
+ '1-Butyl-3-methylimidazolium Tricyanomethanide': 'C[N+]1=CN(CCCC)C=C1.N#C[C-](C#N)C#N',
+ '1-Butyl-3-methylimidazolium Trifluoro(trifluoromethyl)borate': 'C[N+]1=CN(CCCC)C=C1.FC([B-](F)(F)F)(F)F',
+ '1-Butyl-3-methylimidazolium Trifluoroacetate': 'C[N+]1=CN(CCCC)C=C1.O=C([O-])C(F)(F)F',
+ '1-Butyl-3-methylimidazolium Trifluoromethanesulfonate': 'C[N+]1=CN(CCCC)C=C1.O=S(C(F)(F)F)([O-])=O',
+ '1-Butyl-3-methylpyridinium Bromide': 'CC1=C[N+](CCCC)=CC=C1.[Br-]',
+ '1-Butyl-3-methylpyridinium Chloride': 'CC1=C[N+](CCCC)=CC=C1.[Cl-]',
+ '1-Butyl-4-methylpyridinium Bromide': 'CC1=CC=[N+](CCCC)C=C1.[Br-]',
+ '1-Butyl-4-methylpyridinium Chloride': 'CC1=CC=[N+](CCCC)C=C1.[Cl-]',
+ '1-Butyl-4-methylpyridinium Hexafluorophosphate': 'CC1=CC=[N+](CCCC)C=C1.F[P-](F)(F)(F)(F)F',
+ '1-Butylpyridinium Bis(trifluoromethanesulfonyl)imide': 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CCCC[N+]1=CC=CC=C1',
+ '1-Butylpyridinium Bromide': 'CCCC[N+]1=CC=CC=C1.[Br-]',
+ '1-Butylpyridinium Chloride': 'CCCC[N+]1=CC=CC=C1.[Cl-]',
+ '1-Butylpyridinium Hexafluorophosphate': 'CCCC[N+]1=CC=CC=C1.F[P-](F)(F)(F)(F)F',
+ '1-Butylpyridinium Tetrafluoroborate': 'CCCC[N+]1=CC=CC=C1.F[B-](F)(F)F',
+ '1-Chloro-2-iodoethane': 'ICCCl',
+ '1-Cyclohexyl-3-(2-morpholinoethyl)carbodiimide Metho-p-toluenesulfonate': 'C[N+]1(CCN=C=NC2CCCCC2)CCOCC1.O=S(C3=CC=C(C)C=C3)([O-])=O',
+ '1-Cyclopentenylboronic Acid': 'OB(C1=CCCC1)O',
+ '1-Decyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide': 'C[N+]1=CN(CCCCCCCCCC)C=C1.O=S(C(F)(F)F)([N-]S(C(F)(F)F)(=O)=O)=O',
+ '1-Decyl-3-methylimidazolium Bromide': 'C[N+]1=CN(CCCCCCCCCC)C=C1.[Br-]',
+ '1-Decyl-3-methylimidazolium Chloride': 'C[N+]1=CN(CCCCCCCCCC)C=C1.[Cl-]',
+ '1-Ethoxycarbonyl-2-ethoxy-1,2-dihydroquinoline': 'CCOC1N(C(OCC)=O)C2=C(C=CC=C2)C=C1',
+ '1-Ethyl-1-methylpyrrolidinium Bromide': 'C[N+]1(CC)CCCC1.[Br-]',
+ '1-Ethyl-1-methylpyrrolidinium Tetrafluoroborate': 'C[N+]1(CC)CCCC1.F[B-](F)(F)F',
+ '1-Ethyl-2,3-dimethylimidazolium Bis(trifluoromethanesulfonyl)imide': 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CC1=[N+](C)C=CN1CC',
+ '1-Ethyl-2-methylpyridinium Bromide': 'CC1=CC=CC=[N+]1CC.[Br-]',
+ '1-Ethyl-3-(hydroxymethyl)pyridinium Ethyl Sulfate': 'OCC1=C[N+](CC)=CC=C1.O=S(OCC)([O-])=O',
+ '1-Ethyl-3-methylimidazolium Acetate': 'C[N+]1=CN(CC)C=C1.CC([O-])=O',
+ '1-Ethyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide': 'C[N+]1=CN(CC)C=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ '1-Ethyl-3-methylimidazolium Bromide': 'C[N+]1=CN(CC)C=C1.[Br-]',
+ '1-Ethyl-3-methylimidazolium Chloride': 'C[N+]1=CN(CC)C=C1.[Cl-]',
+ '1-Ethyl-3-methylimidazolium Dicyanamide': 'CCN1C=[N+](C)C=C1.N#C[N-]C#N',
+ '1-Ethyl-3-methylimidazolium Diethyl Phosphate': 'C[N+]1=CN(CC)C=C1.O=P(OCC)([O-])OCC',
+ '1-Ethyl-3-methylimidazolium Ethyl Sulfate': 'C[N+]1=CN(CC)C=C1.O=S(OCC)([O-])=O',
+ '1-Ethyl-3-methylimidazolium Hexafluorophosphate': 'C[N+]1=CN(CC)C=C1.F[P-](F)(F)(F)(F)F',
+ '1-Ethyl-3-methylimidazolium Hydrogen Sulfate': 'C[N+]1=CN(CC)C=C1.O=S(O)([O-])=O',
+ '1-Ethyl-3-methylimidazolium Iodide': 'C[N+]1=CN(CC)C=C1.[I-]',
+ '1-Ethyl-3-methylimidazolium Methanesulfonate': 'C[N+]1=CN(CC)C=C1.CS(=O)([O-])=O',
+ '1-Ethyl-3-methylimidazolium Methyl Sulfate': 'C[N+]1=CN(CC)C=C1.O=S(OC)([O-])=O',
+ '1-Ethyl-3-methylimidazolium Nitrate': 'C[N+]1=CN(CC)C=C1.[O-][N+]([O-])=O',
+ '1-Ethyl-3-methylimidazolium Tetrachloroferrate': 'C[N+]1=CN(CC)C=C1.Cl[Fe-](Cl)(Cl)Cl',
+ '1-Ethyl-3-methylimidazolium Tetrafluoroborate': 'C[N+]1=CN(CC)C=C1.F[B-](F)(F)F',
+ '1-Ethyl-3-methylimidazolium Thiocyanate': 'C[N+]1=CN(CC)C=C1.[S-]C#N',
+ '1-Ethyl-3-methylimidazolium Tricyanomethanide': 'C[N+]1=CN(CC)C=C1.N#C[C-](C#N)C#N',
+ '1-Ethyl-3-methylimidazolium Trifluoro(trifluoromethyl)borate': 'C[N+]1=CN(CC)C=C1.FC([B-](F)(F)F)(F)F',
+ '1-Ethyl-3-methylimidazolium Trifluoroacetate': 'C[N+]1=CN(CC)C=C1.O=C([O-])C(F)(F)F',
+ '1-Ethyl-3-methylimidazolium Trifluoromethanesulfonate': 'C[N+]1=CN(CC)C=C1.O=S(C(F)(F)F)([O-])=O',
+ '1-Ethyl-3-methylimidazolium p-Toluenesulfonate': 'C[N+]1=CN(CC)C=C1.CC2=CC=C(S(=O)([O-])=O)C=C2',
+ '1-Ethyl-3-methylpyridinium Bis(trifluoromethanesulfonyl)imide': 'CC1=CC=C[N+](CC)=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ '1-Ethyl-3-methylpyridinium Ethyl Sulfate': 'CC1=C[N+](CC)=CC=C1.O=S(OCC)([O-])=O',
+ '1-Ethyl-4-methylpyridinium Bromide': 'CC1=CC=[N+](CC)C=C1.[Br-]',
+ '1-Ethylpyridinium Bromide': 'CC[N+]1=CC=CC=C1.[Br-]',
+ '1-Ethylpyridinium Chloride': 'CC[N+]1=CC=CC=C1.[Cl-]',
+ '1-Fluoro-2,4,6-trimethylpyridinium Tetrafluoroborate': 'CC1=[N+](F)C(C)=CC(C)=C1.F[B-](F)(F)F',
+ '1-Fluoro-2,4,6-trimethylpyridinium Trifluoromethanesulfonate': 'CC1=[N+](F)C(C)=CC(C)=C1.O=S(C(F)(F)F)([O-])=O',
+ '1-Fluoro-2,6-dichloropyridinium Tetrafluoroborate': 'ClC1=[N+](F)C(Cl)=CC=C1.F[B-](F)(F)F',
+ '1-Fluoro-3,3-dimethyl-1,2-benziodoxole': 'CC1(C)OI(F)C2=CC=CC=C12',
+ '1-Fluoropyridinium Tetrafluoroborate': 'F[N+]1=CC=CC=C1.F[B-](F)(F)F',
+ '1-Fluoropyridinium Trifluoromethanesulfonate': 'F[N+]1=CC=CC=C1.O=S(C(F)(F)F)([O-])=O',
+ '1H-Benzotriazol-1-yloxytripyrrolidinophosphonium Hexafluorophosphate': 'F[P-](F)(F)(F)(F)F.N1([P+](N2CCCC2)(ON3N=NC4=CC=CC=C43)N5CCCC5)CCCC1',
+ '1H-Benzotriazol-1-yloxytris(dimethylamino)phosphonium Hexafluorophosphate': 'CN([P+](N(C)C)(ON1N=NC2=CC=CC=C21)N(C)C)C.F[P-](F)(F)(F)(F)F',
+ '1H-Cyclopenta[l]phenanthrene': 'C12=CC=CC=C1C(CC=C3)=C3C4=C2C=CC=C4',
+ '1-Hexyl-2,3-dimethylimidazolium Iodide': 'C[N+]1=C(C)N(CCCCCC)C=C1.[I-]',
+ '1-Hexyl-3-methylimidazolium Bis(trifluoromethanesulfonyl)imide': 'C[N+]1=CN(CCCCCC)C=C1.O=S([N-]S(=O)(C(F)(F)F)=O)(C(F)(F)F)=O',
+ '1-Hexyl-3-methylimidazolium Bromide': 'C[N+]1=CN(CCCCCC)C=C1.[Br-]',
+ '1-Hexyl-3-methylimidazolium Chloride': 'C[N+]1=CN(CCCCCC)C=C1.[Cl-]',
+ '1-Hexyl-3-methylimidazolium Hexafluorophosphate': 'C[N+]1=CN(CCCCCC)C=C1.F[P-](F)(F)(F)(F)F',
+ '1-Hexyl-3-methylimidazolium Iodide': 'C[N+]1=CN(CCCCCC)C=C1.[I-]',
+ '1-Hexyl-3-methylimidazolium Tetrafluoroborate': 'C[N+]1=CN(CCCCCC)C=C1.F[B-](F)(F)F',
+ '1-Hexyl-3-methylimidazolium Trifluoromethanesulfonate': 'C[N+]1=CN(CCCCCC)C=C1.O=S(C(F)(F)F)([O-])=O',
+ '1-Hexylpyridinium Hexafluorophosphate': 'CCCCCC[N+]1=CC=CC=C1.F[P-](F)(F)(F)(F)F',
+ '1-Hydroxy-6-(trifluoromethyl)benzotriazole': 'FC(C1=CC=C2N=NN(O)C2=C1)(F)F',
+ '1-Methoxy-3-(trimethylsilyloxy)-1,3-butadiene': 'C=C(O[Si](C)(C)C)/C=C/OC',
+ '1-Methyl-1-[4-(diphenylphosphino)benzyl]pyrrolidinium Bromide': 'C[N+]1(CC2=CC=C(P(C3=CC=CC=C3)C4=CC=CC=C4)C=C2)CCCC1.[Br-]',
+ '1-Methyl-1-propylpiperidinium Bis(fluorosulfonyl)imide': 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.C[N+]1(CCC)CCCCC1',
+ '1-Methyl-1-propylpiperidinium Bromide': 'CCC[N+]1(C)CCCCC1.[Br-]',
+ '1-Methyl-1-propylpyrrolidinium Bis(trifluoromethanesulfonyl)imide': 'O=S(NS(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.C[N+]1(CCC)CCCC1',
+ '1-Methyl-2-pyrrolidinone': 'O=C1CCCN1C',
+ '1-Methyl-3-n-octylimidazolium Bromide': 'CCCCCCCC[N+]1=CN(C)C=C1.[Br-]',
+ '1-Methyl-3-n-octylimidazolium Chloride': 'CCCCCCCC[N+]1=CN(C)C=C1.[Cl-]',
+ '1-Methyl-3-n-octylimidazolium Hexafluorophosphate': 'CCCCCCCC[N+]1=CN(C)C=C1.F[P-](F)(F)(F)(F)F',
+ '1-Methyl-3-n-octylimidazolium Tetrafluoroborate': 'CCCCCCCC[N+]1=CN(C)C=C1.F[B-](F)(F)F',
+ '1-Methyl-3-n-octylimidazolium Trifluoromethanesulfonate': 'CCCCCCCC[N+]1=CN(C)C=C1.O=S(C(F)(F)F)([O-])=O',
+ '1-Methyl-3-pentylimidazolium Bromide': 'CCCCC[N+]1=CN(C)C=C1.[Br-]',
+ '1-Methyl-3-pentylimidazolium Tetrafluoroborate': 'CCCCC[N+]1=CN(C)C=C1.F[B-](F)(F)F',
+ '1-Methyl-3-propylimidazolium Bromide': 'CCC[N+]1=CN(C)C=C1.[Br-]',
+ '1-Methyl-3-propylimidazolium Chloride': 'CCC[N+]1=CN(C)C=C1.[Cl-]',
+ '1-Methyl-3-propylimidazolium Iodide': 'CCC[N+]1=CN(C)C=C1.[I-]',
+ '1-Methyl-3-propylimidazolium Tetrafluoroborate': 'CCC[N+]1=CN(C)C=C1.F[B-](F)(F)F',
+ '1-Phenyl-1,3-butanedione': 'CC(CC(C1=CC=CC=C1)=O)=O',
+ '1-Phenyl-2-(trimethylsilyl)acetylene': 'C[Si](C#CC1=CC=CC=C1)(C)C',
+ '1-Propylpyridinium Chloride': 'CCC[N+]1=CC=CC=C1.[Cl-]',
+ '1-Trifluoromethyl-1,2-benziodoxol-3(1H)-one': 'O=C1OI(C(F)(F)F)C2=CC=CC=C12',
+ '1-Trifluoromethyl-3,3-dimethyl-1,2-benziodoxole': 'CC1(C)OI(C(F)(F)F)C2=CC=CC=C12',
+ '2-(1H-1,2,4-Triazol-3-yl)pyridine': 'C1(C2=NNC=N2)=NC=CC=C1',
+ '2-(2-Bromophenyl)-2,3-dihydro-1H-naphtho[1,8-de][1,3,2]diazaborine': 'BrC(C=CC=C1)=C1B(N2)NC3=CC=CC4=C3C2=CC=C4',
+ '2-(2-Chloro-6-fluorophenyl)ethylamine hydrochloride': 'NCCC1=C(F)C=CC=C1Cl.[H]Cl',
+ '2-(2-Hydroxyphenyl)benzothiazole': 'OC1=CC=CC=C1C2=NC3=CC=CC=C3S2',
+ '2-(2-Hydroxyphenyl)benzoxazole': 'OC1=CC=CC=C1C2=NC3=CC=CC=C3O2',
+ '2-(2-Pyridyl)benzoxazole': 'C1(C2=NC=CC=C2)=NC3=CC=CC=C3O1',
+ '2-(2-Pyridyl)indole': 'C(N1)(C2=NC=CC=C2)=CC3=C1C=CC=C3',
+ '2-(3,4-Epoxycyclohexyl)ethyltrimethoxysilane': 'CO[Si](OC)(CCC1CC(O2)C2CC1)OC',
+ '2-(3-Bromophenyl)-2,3-dihydro-1H-naphtho[1,8-de][1,3,2]diazaborine': 'BrC1=CC=CC(B(N2)NC3=CC=CC4=C3C2=CC=C4)=C1',
+ '2-(4-Bromophenyl)-2,3-dihydro-1H-naphtho[1,8-de][1,3,2]diazaborine': 'BrC1=CC=C(C=C1)B(N2)NC3=CC=CC4=CC=CC2=C43',
+ '2-(4-Thiazolyl)benzimidazole': 'C1(C2=CSC=N2)=NC3=CC=CC=C3N1',
+ '2-(5-Norbornene-2,3-dicarboximido)-1,1,3,3-tetramethyluronium Tetrafluoroborate': 'CN(C)C(N(C)C)=[O+]N(C1=O)C(C2C1C3C=CC2C3)=O.F[B-](F)(F)F',
"2-(Dicyclohexylphosphino)-2'-(dimethylamino)biphenyl": 'CN(C1=CC=CC=C1C2=CC=CC=C2P(C3CCCCC3)C4CCCCC4)C',
- "2-(Dicyclohexylphosphino)biphenyl": 'C1(C2=CC=CC=C2)=CC=CC=C1P(C3CCCCC3)C4CCCCC4',
- "2-(Dimethylvinylsilyl)pyridine": 'C=C[Si](C1=NC=CC=C1)(C)C',
- "2-(Diphenylphosphino)benzaldehyde": 'O=CC1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
- "2-(Diphenylphosphino)benzoic Acid": 'O=C(O)C1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
- "2-(Diphenylphosphino)benzonitrile": 'N#CC1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
- "2-(Diphenylphosphino)biphenyl": 'C1(C2=CC=CC=C2)=CC=CC=C1P(C3=CC=CC=C3)C4=CC=CC=C4',
- "2-(Di-tert-butylphosphino)biphenyl": 'CC(P(C1=CC=CC=C1C2=CC=CC=C2)C(C)(C)C)(C)C',
- "2-(Trimethylsilylethynyl)thiophene": 'C[Si](C#CC1=CC=CS1)(C)C',
+ '2-(Dicyclohexylphosphino)biphenyl': 'C1(C2=CC=CC=C2)=CC=CC=C1P(C3CCCCC3)C4CCCCC4',
+ '2-(Dimethylvinylsilyl)pyridine': 'C=C[Si](C1=NC=CC=C1)(C)C',
+ '2-(Diphenylphosphino)benzaldehyde': 'O=CC1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
+ '2-(Diphenylphosphino)benzoic Acid': 'O=C(O)C1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
+ '2-(Diphenylphosphino)benzonitrile': 'N#CC1=CC=CC=C1P(C2=CC=CC=C2)C3=CC=CC=C3',
+ '2-(Diphenylphosphino)biphenyl': 'C1(C2=CC=CC=C2)=CC=CC=C1P(C3=CC=CC=C3)C4=CC=CC=C4',
+ '2-(Di-tert-butylphosphino)biphenyl': 'CC(P(C1=CC=CC=C1C2=CC=CC=C2)C(C)(C)C)(C)C',
+ '2-(Trimethylsilylethynyl)thiophene': 'C[Si](C#CC1=CC=CS1)(C)C',
"2,2'-(Methylimino)bis(N,N-di-n-octylacetamide)": 'CN(CC(N(CCCCCCCC)CCCCCCCC)=O)CC(N(CCCCCCCC)CCCCCCCC)=O',
- "2,2,2-Trifluoro-1,1-ethanediol": 'OC(O)C(F)(F)F',
- "2,2,2-Trifluoroethyl Methanesulfonate": 'CS(=O)(OCC(F)(F)F)=O',
- "2,2,2-Trifluoroethyl Trifluoromethanesulfonate": 'O=S(C(F)(F)F)(OCC(F)(F)F)=O',
- "2,2,2-Trifluoroethyl p-Toluenesulfonate": 'CC1=CC=C(S(=O)(OCC(F)(F)F)=O)C=C1',
- "2,2,2-Trifluoro-N,N-dimethylacetamide": 'O=C(N(C)C)C(F)(F)F',
- "2,2,3,3,3-Pentafluoropropyl p-Toluenesulfonate": 'CC1=CC=C(S(=O)(OCC(F)(F)C(F)(F)F)=O)C=C1',
- "2,2,6,6-Tetramethylpiperidine": 'CC1(C)CCCC(C)(C)N1',
- "2,2,6,6-Tetramethylpiperidine 1-Oxyl": 'CC1(C)CCCC(C)(C)N1[O]',
- "2,2,6,6-Tetramethylpiperidine 1-Oxyl Free Radical": 'CC1(C)CCCC(C)(C)N1[O]',
+ '2,2,2-Trifluoro-1,1-ethanediol': 'OC(O)C(F)(F)F',
+ '2,2,2-Trifluoroethyl Methanesulfonate': 'CS(=O)(OCC(F)(F)F)=O',
+ '2,2,2-Trifluoroethyl Trifluoromethanesulfonate': 'O=S(C(F)(F)F)(OCC(F)(F)F)=O',
+ '2,2,2-Trifluoroethyl p-Toluenesulfonate': 'CC1=CC=C(S(=O)(OCC(F)(F)F)=O)C=C1',
+ '2,2,2-Trifluoro-N,N-dimethylacetamide': 'O=C(N(C)C)C(F)(F)F',
+ '2,2,3,3,3-Pentafluoropropyl p-Toluenesulfonate': 'CC1=CC=C(S(=O)(OCC(F)(F)C(F)(F)F)=O)C=C1',
+ '2,2,6,6-Tetramethylpiperidine': 'CC1(C)CCCC(C)(C)N1',
+ '2,2,6,6-Tetramethylpiperidine 1-Oxyl': 'CC1(C)CCCC(C)(C)N1[O]',
+ '2,2,6,6-Tetramethylpiperidine 1-Oxyl Free Radical': 'CC1(C)CCCC(C)(C)N1[O]',
"2,2':6',2''-Terpyridine": 'C1(C2=NC(C3=NC=CC=C3)=CC=C2)=NC=CC=C1',
"2,2':6',2''-Terpyridine-4'-carboxylic Acid": 'O=C(C1=CC(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=C1)O',
- "2,2′-Bipyridinium chlorochromate": '[O-][Cr](=O)(Cl)=O.[O-][Cr](=O)(Cl)=O.C1(C2=CC=CC=[NH+]2)=CC=CC=[NH+]1',
+ '2,2′-Bipyridinium chlorochromate': '[O-][Cr](=O)(Cl)=O.[O-][Cr](=O)(Cl)=O.C1(C2=CC=CC=[NH+]2)=CC=CC=[NH+]1',
"2,2'-Bi(1,8-naphthyridine)": 'C1(C2=NC3=NC=CC=C3C=C2)=NC4=NC=CC=C4C=C1',
"2,2'-Bi-4-lepidine": 'CC1=CC(C2=NC3=CC=CC=C3C(C)=C2)=NC4=C1C=CC=C4',
"2,2'-Bicinchoninic Acid Dipotassium Salt Hydrate": 'O=C([O-])C1=CC(C2=NC3=CC=CC=C3C(C([O-])=O)=C2)=NC4=CC=CC=C14.[H]O[H].[K+].[K+]',
@@ -560,161 +560,161 @@ export const reagents_kombi = {
"2,2'-Bis(diphenylphosphino)biphenyl": 'C1(C2=CC=CC=C2P(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1P(C5=CC=CC=C5)C6=CC=CC=C6',
"2,2'-Carbonylbis(3,5-dioxo-4-methyl-1,2,4-oxadiazolidine)": 'O=C(N(C(N1C)=O)OC1=O)N(C(N2C)=O)OC2=O',
"2,2'-Diamino-4,4'-bithiazole": 'NC1=NC(C2=CSC(N)=N2)=CS1',
- "2,2-Difluoro-2-(fluorosulfonyl)acetic Acid": 'O=C(O)C(F)(F)S(=O)(F)=O',
- "2,2-Difluoroethyl Trifluoromethanesulfonate": 'O=S(C(F)(F)F)(OCC(F)F)=O',
- "2,2-Difluoroethylamine": 'NCC(F)F',
- "2,2-Dimethyl-6,6,7,7,8,8,8-heptafluoro-3,5-octanedione": 'CC(C)(C)C(CC(C(F)(F)C(F)(F)C(F)(F)F)=O)=O',
- "2,2-Dimethylpropylmagnesium chloride": 'Cl[Mg]CC(C)(C)C',
+ '2,2-Difluoro-2-(fluorosulfonyl)acetic Acid': 'O=C(O)C(F)(F)S(=O)(F)=O',
+ '2,2-Difluoroethyl Trifluoromethanesulfonate': 'O=S(C(F)(F)F)(OCC(F)F)=O',
+ '2,2-Difluoroethylamine': 'NCC(F)F',
+ '2,2-Dimethyl-6,6,7,7,8,8,8-heptafluoro-3,5-octanedione': 'CC(C)(C)C(CC(C(F)(F)C(F)(F)C(F)(F)F)=O)=O',
+ '2,2-Dimethylpropylmagnesium chloride': 'Cl[Mg]CC(C)(C)C',
"2,2'-Dipyridyl Disulfide": 'C1(SSC2=NC=CC=C2)=NC=CC=C1',
"2,2'-Methylenebisbenzothiazole": 'C1(CC2=NC3=CC=CC=C3S2)=NC4=CC=CC=C4S1',
- "2,3,7,8,12,13,17,18-Octaethylporphyrin": 'CCC1=C(CC)C2=NC1=CC3=C(CC)C(CC)=C(N3)C=C4C(CC)=C(CC)C(C=C5C(CC)=C(CC)C(N5)=C2)=N4',
- "2,3,7,8,12,13,17,18-Octafluoro-5,10,15,20-tetrakis(pentafluorophenyl)porphyrin": 'FC1=C(F)C(F)=C(F)C(F)=C1C2=C3C(F)=C(F)C(C(C4=C(F)C(F)=C(F)C(F)=C4F)=C(N5)C(F)=C(F)C5=C(C6=C(F)C(F)=C(F)C(F)=C6F)C7=NC(C(F)=C7F)=C(C8=C(F)C(F)=C(F)C(F)=C8F)C9=C(F)C(F)=C2N9)=N3',
- "2,3-Dimethyl-1-propylimidazolium Bis(trifluoromethanesulfonyl)imide": 'CN1C(C)=[N+](CCC)C=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "2,3-Lutidine": 'CC1=NC=CC=C1C',
- "2,4,4,6-Tetrabromo-2,5-cyclohexadienone": 'BrC1=CC(Br)(Br)C=C(Br)C1=O',
- "2,4,5-Trichlorophenol": 'OC1=CC(Cl)=C(Cl)C=C1Cl',
- "2,4,6,8-Tetramethyl-2,4,6,8-tetravinylcyclotetrasiloxane": 'C=CO1(C)[SiH2]O(C=C)(C)[SiH2]O(C=C)(C)[SiH2]O(C=C)(C)[SiH2]1',
- "2,4,6,8-Tetramethylcyclotetrasiloxane": 'CO1[SiH2]O(C)[SiH2]O(C)[SiH2]O(C)[SiH2]1',
- "2,4,6-Tri(2-pyridyl)-1,3,5-triazine": 'C1(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=NC(C4=NC=CC=C4)=N1',
- "2,4,6-Tri(4-pyridyl)-1,3,5-triazine": 'C1(C2=CC=NC=C2)=NC(C3=CC=NC=C3)=NC(C4=CC=NC=C4)=N1',
- "2,4,6-Trichlorobenzoyl Chloride": 'O=C(Cl)C1=C(Cl)C=C(Cl)C=C1Cl',
- "2,4,6-Triisopropylbenzenesulfonyl Chloride": 'O=S(C1=C(C(C)C)C=C(C(C)C)C=C1C(C)C)(Cl)=O',
- "2,4,6-Trimethylpyridinium p-Toluenesulfonate": 'CC1=[NH+]C(C)=CC(C)=C1.CC2=CC=C(S(=O)([O-])=O)C=C2',
- "2,4,6-Tris(3,4,5-trifluorophenyl)boroxin": 'FC1=C(F)C(F)=CC(B2OB(C3=CC(F)=C(F)C(F)=C3)OB(C4=CC(F)=C(F)C(F)=C4)O2)=C1',
- "2,4-Dibromo-6-[(E)-[[(1R,2R)-2-(isoindolin-2-yl)-1,2-diphenylethyl]imino]methyl]phenol": 'OC1=C(/C=N/[C@H](C2=CC=CC=C2)[C@H](N3CC4=C(C=CC=C4)C3)C5=CC=CC=C5)C=C(Br)C=C1Br',
- "2,4-Dibromo-6-[[[[(4S,5S)-4,5-dihydro-4,5-diphenyl-1-tosyl-1H-imidazol-2-yl]methyl][(S)-1-phenylethyl]amino]methyl]phenol": 'OC1=C(CN(CC2=N[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N2S(=O)(C5=CC=C(C)C=C5)=O)[C@H](C6=CC=CC=C6)C)C=C(Br)C=C1Br',
- "2,4-Lutidine": 'CC1=NC=CC(C)=C1',
- "2,4-Mesitylenedisulfonyl Dichloride": 'CC1=C(S(=O)(Cl)=O)C(C)=CC(C)=C1S(=O)(Cl)=O',
- "2,5-Bis(4-bromophenyl)-1,1-dimethyl-3,4-diphenylsilole": 'C[Si]1(C)C(C2=CC=C(Br)C=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C1C5=CC=C(Br)C=C5',
- "2,5-Bis[(trimethylsilyl)ethynyl]thiophene": 'C[Si](C#CC1=CC=C(C#C[Si](C)(C)C)S1)(C)C',
- "2,5-Dibromo-1,1,3,4-tetraphenylsilole": 'BrC1=C(C2=CC=CC=C2)C(C3=CC=CC=C3)=C(Br)[Si]1(C4=CC=CC=C4)C5=CC=CC=C5',
- "2,5-Dibromo-1,1-dimethyl-3,4-diphenylsilole": 'C[Si]1(C)C(Br)=C(C2=CC=CC=C2)C(C3=CC=CC=C3)=C1Br',
- "2,5-Diphenylpyridine": 'C1(C2=CC=CC=C2)=NC=C(C3=CC=CC=C3)C=C1',
- "2,5-Lutidine": 'CC1=NC=C(C)C=C1',
- "2,5-Norbornadiene": 'C12C=CC(C2)C=C1',
- "2,6-Bis(2-benzimidazolyl)pyridine": 'C1(C2=NC3=CC=CC=C3N2)=NC(C4=NC5=CC=CC=C5N4)=CC=C1',
- "2,6-Bis(2-pyridyl)-4(1H)-pyridone": 'O=C1C=C(C2=NC=CC=C2)NC(C3=NC=CC=C3)=C1',
- "2,6-Bis[(2,2,6,6-tetramethyl-1-piperidinyl)methyl]phenylboronic Acid": 'OB(C1=C(CN2C(C)(C)CCCC2(C)C)C=CC=C1CN3C(C)(C)CCCC3(C)C)O',
- "2,6-Bis[(2R,4S,5S)-1-benzyl-4,5-diphenylimidazolidin-2-yl]pyridine": 'C1([C@@H]2N[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N2CC5=CC=CC=C5)=NC([C@@H]6N[C@@H](C7=CC=CC=C7)[C@H](C8=CC=CC=C8)N6CC9=CC=CC=C9)=CC=C1',
- "2,6-Bis[(2S,4S)-4-methyl-5,5-diphenyloxazolidin-2-yl]pyridine": 'C[C@@H]1N[C@H](C2=CC=CC([C@@H]3OC(C4=CC=CC=C4)(C5=CC=CC=C5)[C@H](C)N3)=N2)OC1(C6=CC=CC=C6)C7=CC=CC=C7',
- "2,6-Bis[(2S,5S)-4,4-diphenyl-1-aza-3-oxabicyclo[3.3.0]octan-2-yl]pyridine": '[H][C@]12C(C3=CC=CC=C3)(C4=CC=CC=C4)O[C@@H](C5=CC=CC([C@H]6N7CCC[C@@]7([H])C(C8=CC=CC=C8)(C9=CC=CC=C9)O6)=N5)N1CCC2',
- "2,6-Di(1-pyrazolyl)pyridine": 'C1(N2N=CC=C2)=NC(N3N=CC=C3)=CC=C1',
- "2,6-Di(2H-1,2,3-triazol-4-yl)pyridine": 'C1(C2=NNN=C2)=NC(C3=NNN=C3)=CC=C1',
- "2,6-Dimethyl-3,5-heptanedione": 'CC(C)C(CC(C(C)C)=O)=O',
- "2,6-Lutidine": 'CC1=NC(C)=CC=C1',
- "2,8,9-Triisobutyl-2,5,8,9-tetraaza-1-phosphabicyclo[3.3.3]undecane": 'CC(C)CN1CCN2CCN(CC(C)C)P1N(CC(C)C)CC2',
- "2,8,9-Triisopropyl-2,5,8,9-tetraaza-1-phosphabicyclo[3,3,3]undecane": 'CC(N1CCN2CCN(C(C)C)P1N(C(C)C)CC2)C',
- "2,8-Difluoro-5-(trifluoromethyl)-5H-dibenzo[b,d]thiophen-5-ium Trifluoromethanesulfonate": 'FC([S+]1C2=CC=C(F)C=C2C3=CC(F)=CC=C31)(F)F.O=S(C(F)(F)F)([O-])=O',
- "2,9-Dibutyl-1,10-phenanthroline": 'CCCCC1=NC2=C3N=C(CCCC)C=CC3=CC=C2C=C1',
- "2,9-Dichloro-1,10-phenanthroline": 'ClC1=NC2=C3N=C(Cl)C=CC3=CC=C2C=C1',
- "2,9-Diphenyl-1,10-phenanthroline": 'C1(C2=CC=CC=C2)=NC3=C4N=C(C5=CC=CC=C5)C=CC4=CC=C3C=C1',
- "2-[(2,2,6,6-Tetramethyl-1-piperidyl)methyl]phenylboronic Acid": 'OB(C1=CC=CC=C1CN2C(C)(C)CCCC2(C)C)O',
- "2-[N,N-Bis(trifluoromethanesulfonyl)amino]-5-chloropyridine": 'ClC1=CN=C(N(S(=O)(C(F)(F)F)=O)S(=O)(C(F)(F)F)=O)C=C1',
- "2-Acetylcyclohexanone": 'O=C1C(C(C)=O)CCCC1',
- "2-Acetylcyclopentanone": 'O=C1C(C(C)=O)CCC1',
- "2-Bromo-1,10-phenanthroline": 'BrC1=NC2=C3N=CC=CC3=CC=C2C=C1',
- "2-Bromo-1-ethylpyridinium Tetrafluoroborate": 'CC[N+]1=CC=CC=C1Br.F[B-](F)(F)F',
- "2-Bromo-2-cyano-N,N-dimethylacetamide": 'O=C(N(C)C)C(Br)C#N',
- "2-Chloro-1,10-phenanthroline": 'ClC1=NC2=C3N=CC=CC3=CC=C2C=C1',
- "2-Chloro-1,3,2-dioxaphospholane": 'ClP1OCCO1',
- "2-Chloro-1,3-bis(2,6-diisopropylphenyl)-1H-imidazolium Chloride": 'CC(C1=C([N+]2=C(Cl)N(C3=C(C(C)C)C=CC=C3C(C)C)C=C2)C(C(C)C)=CC=C1)C.[Cl-]',
- "2-Chloro-1,3-dimethylimidazolinium Chloride": 'C[N+]1=C(Cl)N(C)CC1.[Cl-]',
- "2-Chloro-1,3-dimethylimidazolinium Hexafluorophosphate": 'C[N+]1=C(Cl)N(C)CC1.F[P-](F)(F)(F)(F)F',
- "2-Chloro-1,3-dimethylimidazolinium Tetrafluoroborate": 'C[N+]1=C(Cl)N(C)CC1.F[B-](F)(F)F',
- "2-Chloro-1-methylpyridinium Iodide": 'C[N+]1=CC=CC=C1Cl.[I-]',
- "2-Chloro-1-methylpyridinium p-Toluenesulfonate": 'C[N+]1=CC=CC=C1Cl.CC2=CC=C(S(=O)([O-])=O)C=C2',
- "2-Chloro-4H-1,3,2-benzodioxaphosphorin-4-one": 'O=C1OP(Cl)OC2=CC=CC=C12',
- "2-Cyanoethyltriethoxysilane": 'CCO[Si](OCC)(CCC#N)OCC',
+ '2,3,7,8,12,13,17,18-Octaethylporphyrin': 'CCC1=C(CC)C2=NC1=CC3=C(CC)C(CC)=C(N3)C=C4C(CC)=C(CC)C(C=C5C(CC)=C(CC)C(N5)=C2)=N4',
+ '2,3,7,8,12,13,17,18-Octafluoro-5,10,15,20-tetrakis(pentafluorophenyl)porphyrin': 'FC1=C(F)C(F)=C(F)C(F)=C1C2=C3C(F)=C(F)C(C(C4=C(F)C(F)=C(F)C(F)=C4F)=C(N5)C(F)=C(F)C5=C(C6=C(F)C(F)=C(F)C(F)=C6F)C7=NC(C(F)=C7F)=C(C8=C(F)C(F)=C(F)C(F)=C8F)C9=C(F)C(F)=C2N9)=N3',
+ '2,3-Dimethyl-1-propylimidazolium Bis(trifluoromethanesulfonyl)imide': 'CN1C(C)=[N+](CCC)C=C1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ '2,3-Lutidine': 'CC1=NC=CC=C1C',
+ '2,4,4,6-Tetrabromo-2,5-cyclohexadienone': 'BrC1=CC(Br)(Br)C=C(Br)C1=O',
+ '2,4,5-Trichlorophenol': 'OC1=CC(Cl)=C(Cl)C=C1Cl',
+ '2,4,6,8-Tetramethyl-2,4,6,8-tetravinylcyclotetrasiloxane': 'C=CO1(C)[SiH2]O(C=C)(C)[SiH2]O(C=C)(C)[SiH2]O(C=C)(C)[SiH2]1',
+ '2,4,6,8-Tetramethylcyclotetrasiloxane': 'CO1[SiH2]O(C)[SiH2]O(C)[SiH2]O(C)[SiH2]1',
+ '2,4,6-Tri(2-pyridyl)-1,3,5-triazine': 'C1(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=NC(C4=NC=CC=C4)=N1',
+ '2,4,6-Tri(4-pyridyl)-1,3,5-triazine': 'C1(C2=CC=NC=C2)=NC(C3=CC=NC=C3)=NC(C4=CC=NC=C4)=N1',
+ '2,4,6-Trichlorobenzoyl Chloride': 'O=C(Cl)C1=C(Cl)C=C(Cl)C=C1Cl',
+ '2,4,6-Triisopropylbenzenesulfonyl Chloride': 'O=S(C1=C(C(C)C)C=C(C(C)C)C=C1C(C)C)(Cl)=O',
+ '2,4,6-Trimethylpyridinium p-Toluenesulfonate': 'CC1=[NH+]C(C)=CC(C)=C1.CC2=CC=C(S(=O)([O-])=O)C=C2',
+ '2,4,6-Tris(3,4,5-trifluorophenyl)boroxin': 'FC1=C(F)C(F)=CC(B2OB(C3=CC(F)=C(F)C(F)=C3)OB(C4=CC(F)=C(F)C(F)=C4)O2)=C1',
+ '2,4-Dibromo-6-[(E)-[[(1R,2R)-2-(isoindolin-2-yl)-1,2-diphenylethyl]imino]methyl]phenol': 'OC1=C(/C=N/[C@H](C2=CC=CC=C2)[C@H](N3CC4=C(C=CC=C4)C3)C5=CC=CC=C5)C=C(Br)C=C1Br',
+ '2,4-Dibromo-6-[[[[(4S,5S)-4,5-dihydro-4,5-diphenyl-1-tosyl-1H-imidazol-2-yl]methyl][(S)-1-phenylethyl]amino]methyl]phenol': 'OC1=C(CN(CC2=N[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N2S(=O)(C5=CC=C(C)C=C5)=O)[C@H](C6=CC=CC=C6)C)C=C(Br)C=C1Br',
+ '2,4-Lutidine': 'CC1=NC=CC(C)=C1',
+ '2,4-Mesitylenedisulfonyl Dichloride': 'CC1=C(S(=O)(Cl)=O)C(C)=CC(C)=C1S(=O)(Cl)=O',
+ '2,5-Bis(4-bromophenyl)-1,1-dimethyl-3,4-diphenylsilole': 'C[Si]1(C)C(C2=CC=C(Br)C=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C1C5=CC=C(Br)C=C5',
+ '2,5-Bis[(trimethylsilyl)ethynyl]thiophene': 'C[Si](C#CC1=CC=C(C#C[Si](C)(C)C)S1)(C)C',
+ '2,5-Dibromo-1,1,3,4-tetraphenylsilole': 'BrC1=C(C2=CC=CC=C2)C(C3=CC=CC=C3)=C(Br)[Si]1(C4=CC=CC=C4)C5=CC=CC=C5',
+ '2,5-Dibromo-1,1-dimethyl-3,4-diphenylsilole': 'C[Si]1(C)C(Br)=C(C2=CC=CC=C2)C(C3=CC=CC=C3)=C1Br',
+ '2,5-Diphenylpyridine': 'C1(C2=CC=CC=C2)=NC=C(C3=CC=CC=C3)C=C1',
+ '2,5-Lutidine': 'CC1=NC=C(C)C=C1',
+ '2,5-Norbornadiene': 'C12C=CC(C2)C=C1',
+ '2,6-Bis(2-benzimidazolyl)pyridine': 'C1(C2=NC3=CC=CC=C3N2)=NC(C4=NC5=CC=CC=C5N4)=CC=C1',
+ '2,6-Bis(2-pyridyl)-4(1H)-pyridone': 'O=C1C=C(C2=NC=CC=C2)NC(C3=NC=CC=C3)=C1',
+ '2,6-Bis[(2,2,6,6-tetramethyl-1-piperidinyl)methyl]phenylboronic Acid': 'OB(C1=C(CN2C(C)(C)CCCC2(C)C)C=CC=C1CN3C(C)(C)CCCC3(C)C)O',
+ '2,6-Bis[(2R,4S,5S)-1-benzyl-4,5-diphenylimidazolidin-2-yl]pyridine': 'C1([C@@H]2N[C@@H](C3=CC=CC=C3)[C@H](C4=CC=CC=C4)N2CC5=CC=CC=C5)=NC([C@@H]6N[C@@H](C7=CC=CC=C7)[C@H](C8=CC=CC=C8)N6CC9=CC=CC=C9)=CC=C1',
+ '2,6-Bis[(2S,4S)-4-methyl-5,5-diphenyloxazolidin-2-yl]pyridine': 'C[C@@H]1N[C@H](C2=CC=CC([C@@H]3OC(C4=CC=CC=C4)(C5=CC=CC=C5)[C@H](C)N3)=N2)OC1(C6=CC=CC=C6)C7=CC=CC=C7',
+ '2,6-Bis[(2S,5S)-4,4-diphenyl-1-aza-3-oxabicyclo[3.3.0]octan-2-yl]pyridine': '[H][C@]12C(C3=CC=CC=C3)(C4=CC=CC=C4)O[C@@H](C5=CC=CC([C@H]6N7CCC[C@@]7([H])C(C8=CC=CC=C8)(C9=CC=CC=C9)O6)=N5)N1CCC2',
+ '2,6-Di(1-pyrazolyl)pyridine': 'C1(N2N=CC=C2)=NC(N3N=CC=C3)=CC=C1',
+ '2,6-Di(2H-1,2,3-triazol-4-yl)pyridine': 'C1(C2=NNN=C2)=NC(C3=NNN=C3)=CC=C1',
+ '2,6-Dimethyl-3,5-heptanedione': 'CC(C)C(CC(C(C)C)=O)=O',
+ '2,6-Lutidine': 'CC1=NC(C)=CC=C1',
+ '2,8,9-Triisobutyl-2,5,8,9-tetraaza-1-phosphabicyclo[3.3.3]undecane': 'CC(C)CN1CCN2CCN(CC(C)C)P1N(CC(C)C)CC2',
+ '2,8,9-Triisopropyl-2,5,8,9-tetraaza-1-phosphabicyclo[3,3,3]undecane': 'CC(N1CCN2CCN(C(C)C)P1N(C(C)C)CC2)C',
+ '2,8-Difluoro-5-(trifluoromethyl)-5H-dibenzo[b,d]thiophen-5-ium Trifluoromethanesulfonate': 'FC([S+]1C2=CC=C(F)C=C2C3=CC(F)=CC=C31)(F)F.O=S(C(F)(F)F)([O-])=O',
+ '2,9-Dibutyl-1,10-phenanthroline': 'CCCCC1=NC2=C3N=C(CCCC)C=CC3=CC=C2C=C1',
+ '2,9-Dichloro-1,10-phenanthroline': 'ClC1=NC2=C3N=C(Cl)C=CC3=CC=C2C=C1',
+ '2,9-Diphenyl-1,10-phenanthroline': 'C1(C2=CC=CC=C2)=NC3=C4N=C(C5=CC=CC=C5)C=CC4=CC=C3C=C1',
+ '2-[(2,2,6,6-Tetramethyl-1-piperidyl)methyl]phenylboronic Acid': 'OB(C1=CC=CC=C1CN2C(C)(C)CCCC2(C)C)O',
+ '2-[N,N-Bis(trifluoromethanesulfonyl)amino]-5-chloropyridine': 'ClC1=CN=C(N(S(=O)(C(F)(F)F)=O)S(=O)(C(F)(F)F)=O)C=C1',
+ '2-Acetylcyclohexanone': 'O=C1C(C(C)=O)CCCC1',
+ '2-Acetylcyclopentanone': 'O=C1C(C(C)=O)CCC1',
+ '2-Bromo-1,10-phenanthroline': 'BrC1=NC2=C3N=CC=CC3=CC=C2C=C1',
+ '2-Bromo-1-ethylpyridinium Tetrafluoroborate': 'CC[N+]1=CC=CC=C1Br.F[B-](F)(F)F',
+ '2-Bromo-2-cyano-N,N-dimethylacetamide': 'O=C(N(C)C)C(Br)C#N',
+ '2-Chloro-1,10-phenanthroline': 'ClC1=NC2=C3N=CC=CC3=CC=C2C=C1',
+ '2-Chloro-1,3,2-dioxaphospholane': 'ClP1OCCO1',
+ '2-Chloro-1,3-bis(2,6-diisopropylphenyl)-1H-imidazolium Chloride': 'CC(C1=C([N+]2=C(Cl)N(C3=C(C(C)C)C=CC=C3C(C)C)C=C2)C(C(C)C)=CC=C1)C.[Cl-]',
+ '2-Chloro-1,3-dimethylimidazolinium Chloride': 'C[N+]1=C(Cl)N(C)CC1.[Cl-]',
+ '2-Chloro-1,3-dimethylimidazolinium Hexafluorophosphate': 'C[N+]1=C(Cl)N(C)CC1.F[P-](F)(F)(F)(F)F',
+ '2-Chloro-1,3-dimethylimidazolinium Tetrafluoroborate': 'C[N+]1=C(Cl)N(C)CC1.F[B-](F)(F)F',
+ '2-Chloro-1-methylpyridinium Iodide': 'C[N+]1=CC=CC=C1Cl.[I-]',
+ '2-Chloro-1-methylpyridinium p-Toluenesulfonate': 'C[N+]1=CC=CC=C1Cl.CC2=CC=C(S(=O)([O-])=O)C=C2',
+ '2-Chloro-4H-1,3,2-benzodioxaphosphorin-4-one': 'O=C1OP(Cl)OC2=CC=CC=C12',
+ '2-Cyanoethyltriethoxysilane': 'CCO[Si](OCC)(CCC#N)OCC',
"2-Dicyclohexylphosphino-2',4',6'-triisopropylbiphenyl": 'CC(C1=C(C2=CC=CC=C2P(C3CCCCC3)C4CCCCC4)C(C(C)C)=CC(C(C)C)=C1)C',
"2-Dicyclohexylphosphino-2',6'-diisopropoxybiphenyl": 'CC(OC1=C(C2=CC=CC=C2P(C3CCCCC3)C4CCCCC4)C(OC(C)C)=CC=C1)C',
"2-Dicyclohexylphosphino-2',6'-dimethoxybiphenyl": 'COC1=C(C2=CC=CC=C2P(C3CCCCC3)C4CCCCC4)C(OC)=CC=C1',
"2-Di-tert-butylphosphino-2',4',6'-triisopropylbiphenyl": 'CC(C1=C(C2=CC=CC=C2P(C(C)(C)C)C(C)(C)C)C(C(C)C)=CC(C(C)C)=C1)C',
- "2-Fluoro-1-methylpyridinium p-Toluenesulfonate": 'C[N+]1=CC=CC=C1F.CC2=CC=C(S(=O)([O-])=O)C=C2',
- "2-Furoyltrifluoroacetone": 'O=C(CC(C1=CC=CO1)=O)C(F)(F)F',
- "2-Hydroxy-2-azaadamantane": 'ON1C2CC3CC(C2)CC1C3',
- "2-Hydroxybenzaldehyde Phenylhydrazone": 'OC1=CC=CC=C1/C=N/NC2=CC=CC=C2',
- "2-Hydroxybenzoic Acid": 'O=C(O)C1=CC=CC=C1O',
- "2-Hydroxypyridine N-Oxide": 'OC1=CC=CC=[N+]1[O-]',
- "2-Iodosobenzoic Acid": 'O=C(O)C1=CC=CC=C1I=O',
- "2-Iodoxybenzoic acid": 'O=C(O)C1=CC=CC=C1I(=O)=O',
- "2-methoxy ethanol": 'OCCOC',
- "2-Methyl-1,10-phenanthroline": 'CC1=NC2=C3N=CC=CC3=CC=C2C=C1',
- "2-Methyl-6-nitrobenzoic Anhydride": 'O=C(OC(C1=C([N+]([O-])=O)C=CC=C1C)=O)C2=C([N+]([O-])=O)C=CC=C2C',
- "2-Methylbenzo[e]indene": 'N/A',
- "2-Methylcyclopenta[l]phenanthrene": 'CC1=CC2=C3CC=CC=C3C4=C(C2=C1)C=CC=C4',
- "2-Nitrophenylarsonic Acid": 'O=[As](C1=CC=CC=C1[N+]([O-])=O)(O)O',
- "2-Norbornene": 'C12C=CC(C2)CC1',
- "2-Phenylethylboronic Acid": 'OB(CCC1=CC=CC=C1)O',
- "2-Salicylideneaminophenol": 'OC1=CC=CC=C1/N=C/C2=CC=CC=C2O',
- "2-tert-Butyl-1,1,3,3-tetramethylguanidine": 'CN(C)C(N(C)C)=NC(C)(C)C',
- "2-Trimethylsilyloxy-1,3-butadiene": 'C=C(O[Si](C)(C)C)C=C',
- "2-Trimethylsilylthiophene": 'C[Si](C1=CC=CS1)(C)C',
- "3-(2-Aminoethylamino)propyltrimethoxysilane": 'CO[Si](OC)(CCCNCCN)OC',
- "3-(Diethoxyphosphoryloxy)-1,2,3-benzotriazin-4(3H)-one": 'O=C1N(OP(OCC)(OCC)=O)N=NC2=CC=CC=C12',
- "3-(Dimethylsilyloxy)-1,1,5,5-tetramethyl-3-phenyltrisiloxane": 'C[SiH](C)O[Si](C1=CC=CC=C1)(O[SiH](C)C)O[SiH](C)C',
- "3-(Diphenylphosphino)-1-propylamine": 'NCCCP(C1=CC=CC=C1)C2=CC=CC=C2',
- "3-(Triallylsilyl)propyl Acrylate": 'C=CC(OCCC[Si](CC=C)(CC=C)CC=C)=O',
- "3-(Triallylsilyl)propyl Methacrylate": 'CC(C(OCCC[Si](CC=C)(CC=C)CC=C)=O)=C',
- "3-(Triethoxysilyl)propyl Isocyanate": 'CCO[Si](CCCN=C=O)(OCC)OCC',
- "3-(Trimethoxysilyl)propyl Acrylate": 'C=CC(OCCC[Si](OC)(OC)OC)=O',
- "3-(Trimethoxysilyl)propyl Methacrylate": 'CC(C(OCCC[Si](OC)(OC)OC)=O)=C',
- "3-(Trimethylsilylethynyl)thiophene": 'C[Si](C#CC1=CSC=C1)(C)C',
+ '2-Fluoro-1-methylpyridinium p-Toluenesulfonate': 'C[N+]1=CC=CC=C1F.CC2=CC=C(S(=O)([O-])=O)C=C2',
+ '2-Furoyltrifluoroacetone': 'O=C(CC(C1=CC=CO1)=O)C(F)(F)F',
+ '2-Hydroxy-2-azaadamantane': 'ON1C2CC3CC(C2)CC1C3',
+ '2-Hydroxybenzaldehyde Phenylhydrazone': 'OC1=CC=CC=C1/C=N/NC2=CC=CC=C2',
+ '2-Hydroxybenzoic Acid': 'O=C(O)C1=CC=CC=C1O',
+ '2-Hydroxypyridine N-Oxide': 'OC1=CC=CC=[N+]1[O-]',
+ '2-Iodosobenzoic Acid': 'O=C(O)C1=CC=CC=C1I=O',
+ '2-Iodoxybenzoic acid': 'O=C(O)C1=CC=CC=C1I(=O)=O',
+ '2-methoxy ethanol': 'OCCOC',
+ '2-Methyl-1,10-phenanthroline': 'CC1=NC2=C3N=CC=CC3=CC=C2C=C1',
+ '2-Methyl-6-nitrobenzoic Anhydride': 'O=C(OC(C1=C([N+]([O-])=O)C=CC=C1C)=O)C2=C([N+]([O-])=O)C=CC=C2C',
+ '2-Methylbenzo[e]indene': 'N/A',
+ '2-Methylcyclopenta[l]phenanthrene': 'CC1=CC2=C3CC=CC=C3C4=C(C2=C1)C=CC=C4',
+ '2-Nitrophenylarsonic Acid': 'O=[As](C1=CC=CC=C1[N+]([O-])=O)(O)O',
+ '2-Norbornene': 'C12C=CC(C2)CC1',
+ '2-Phenylethylboronic Acid': 'OB(CCC1=CC=CC=C1)O',
+ '2-Salicylideneaminophenol': 'OC1=CC=CC=C1/N=C/C2=CC=CC=C2O',
+ '2-tert-Butyl-1,1,3,3-tetramethylguanidine': 'CN(C)C(N(C)C)=NC(C)(C)C',
+ '2-Trimethylsilyloxy-1,3-butadiene': 'C=C(O[Si](C)(C)C)C=C',
+ '2-Trimethylsilylthiophene': 'C[Si](C1=CC=CS1)(C)C',
+ '3-(2-Aminoethylamino)propyltrimethoxysilane': 'CO[Si](OC)(CCCNCCN)OC',
+ '3-(Diethoxyphosphoryloxy)-1,2,3-benzotriazin-4(3H)-one': 'O=C1N(OP(OCC)(OCC)=O)N=NC2=CC=CC=C12',
+ '3-(Dimethylsilyloxy)-1,1,5,5-tetramethyl-3-phenyltrisiloxane': 'C[SiH](C)O[Si](C1=CC=CC=C1)(O[SiH](C)C)O[SiH](C)C',
+ '3-(Diphenylphosphino)-1-propylamine': 'NCCCP(C1=CC=CC=C1)C2=CC=CC=C2',
+ '3-(Triallylsilyl)propyl Acrylate': 'C=CC(OCCC[Si](CC=C)(CC=C)CC=C)=O',
+ '3-(Triallylsilyl)propyl Methacrylate': 'CC(C(OCCC[Si](CC=C)(CC=C)CC=C)=O)=C',
+ '3-(Triethoxysilyl)propyl Isocyanate': 'CCO[Si](CCCN=C=O)(OCC)OCC',
+ '3-(Trimethoxysilyl)propyl Acrylate': 'C=CC(OCCC[Si](OC)(OC)OC)=O',
+ '3-(Trimethoxysilyl)propyl Methacrylate': 'CC(C(OCCC[Si](OC)(OC)OC)=O)=C',
+ '3-(Trimethylsilylethynyl)thiophene': 'C[Si](C#CC1=CSC=C1)(C)C',
"3,3'-Iminobis(N,N-dimethylpropylamine)": 'CN(C)CCCNCCCN(C)C',
"3,3'-Methylenebis(1-tert-butyl-3-imidazolium Bromide)": 'CC(N1C=C[N+](C[N+]2=CN(C(C)(C)C)C=C2)=C1)(C)C.[Br-].[Br-]',
"3,3'-Methylenebis[1-(2,6-diisopropylphenyl)-3-imidazolium Bromide]": 'CC(C1=C(N2C=C[N+](C[N+]3=CN(C4=C(C(C)C)C=CC=C4C(C)C)C=C3)=C2)C(C(C)C)=CC=C1)C.[Br-].[Br-]',
- "3,4,7,8-Tetramethyl-1,10-phenanthroline": 'CC1=C(C)C2=CC=C3C(C)=C(C)C=NC3=C2N=C1',
- "3,4-Diacetyl-2,5-hexanedione": 'CC(C(C(C)=O)C(C(C)=O)C(C)=O)=O',
- "3,4-Dihydro-2H-pyrido[1,2-a]pyrimidin-2-one": 'O=C1N=C(C=CC=C2)N2CC1',
- "3,4-Dihydro-3-hydroxy-4-oxo-1,2,3-benzotriazine": 'O=C1N(O)N=NC2=CC=CC=C12',
- "3,4-Lutidine": 'CC1=C(C)C=CN=C1',
- "3,5,6,8-Tetrabromo-1,10-phenanthroline": 'BrC1=CC2=C(Br)C(Br)=C3C=C(Br)C=NC3=C2N=C1',
- "3,5-Bis(trifluoromethyl)phenylboronic Acid": 'OB(C1=CC(C(F)(F)F)=CC(C(F)(F)F)=C1)O',
- "3,5-Di(2-pyridyl)pyrazole": 'C1(C2=NC=CC=C2)=NNC(C3=NC=CC=C3)=C1',
- "3,5-Heptanedione": 'CCC(CC(CC)=O)=O',
- "3,5-Lutidine": 'CC1=CC(C)=CN=C1',
- "3,6-Di(2-pyridyl)-1,2,4,5-tetrazine": 'C1(C2=NC=CC=C2)=NN=C(C3=NC=CC=C3)N=N1',
- "3,8-Dibromo-1,10-phenanthroline": 'BrC1=CC2=CC=C3C=C(Br)C=NC3=C2N=C1',
- "3-[(Dimethylsilyl)oxy]-1,1,3,5,5-pentamethyltrisiloxane": 'C[SiH](C)O[Si](C)(O[SiH](C)C)O[SiH](C)C',
- "3-[[Dimethyl(vinyl)silyl]oxy]-1,1,5,5-tetramethyl-3-phenyl-1,5-divinyltrisiloxane": 'C=C[Si](C)(C)O[Si](C1=CC=CC=C1)(O[Si](C)(C)C=C)O[Si](C)(C)C=C',
- "3-[[tert-Butyl(dimethyl)silyl]oxy]-1-propanol": 'OCCCO[Si](C)(C(C)(C)C)C',
- "3-Aminopropyltriethoxysilane": 'CCO[Si](OCC)(CCCN)OCC',
- "3-Aminopropyltrimethoxysilane": 'CO[Si](OC)(CCCN)OC',
- "3-Bromo-1-(trimethylsilyl)-1-propyne": 'C[Si](C#CCBr)(C)C',
- "3-Bromo-1,10-phenanthroline": 'BrC1=CC2=CC=C3C=CC=NC3=C2N=C1',
- "3-Chloroacetylacetone": 'CC(C(Cl)C(C)=O)=O',
- "3-Chloroperoxybenzoic acid": 'C1=CC(=CC(=C1)Cl)C(=O)OO',
- "3-Chloropropyltriethoxysilane": 'CCO[Si](OCC)(CCCCl)OCC',
- "3-Ethyl-2,4-pentanedione": 'CC(C(CC)C(C)=O)=O',
- "3-Glycidyloxypropyltrimethoxysilane": 'CO[Si](OC)(CCCOCC1CO1)OC',
- "3-Mercaptopropyl(dimethoxy)methylsilane": 'C[Si](OC)(CCCS)OC',
- "3-Methyl-1-phenyl-2-phospholene 1-Oxide": 'CC(CC1)=CP1(C2=CC=CC=C2)=O',
- "3-Methyl-2,4-pentanedione": 'CC(C(C)C(C)=O)=O',
- "3-Nitro-1,2,4-triazole": 'O=[N+](C1=NNC=N1)[O-]',
- "3-Phenyl-2,4-pentanedione": 'CC(C(C1=CC=CC=C1)C(C)=O)=O',
- "3-Pyridinecarboxylic Anhydride": 'O=C(OC(C1=CC=CN=C1)=O)C2=CC=CN=C2',
- "3-Quinolineboronic acid": 'OB(C1=CC2=CC=CC=C2N=C1)O',
- "3-Tolylboronic acid": 'CC1=CC=CC(B(O)O)=C1',
- "3-Trimethoxysilylpropyl Chloride": 'CO[Si](CCCCl)(OC)OC',
- "3-Trimethylsilyl-2-propyn-1-ol": 'OCC#C[Si](C)(C)C',
+ '3,4,7,8-Tetramethyl-1,10-phenanthroline': 'CC1=C(C)C2=CC=C3C(C)=C(C)C=NC3=C2N=C1',
+ '3,4-Diacetyl-2,5-hexanedione': 'CC(C(C(C)=O)C(C(C)=O)C(C)=O)=O',
+ '3,4-Dihydro-2H-pyrido[1,2-a]pyrimidin-2-one': 'O=C1N=C(C=CC=C2)N2CC1',
+ '3,4-Dihydro-3-hydroxy-4-oxo-1,2,3-benzotriazine': 'O=C1N(O)N=NC2=CC=CC=C12',
+ '3,4-Lutidine': 'CC1=C(C)C=CN=C1',
+ '3,5,6,8-Tetrabromo-1,10-phenanthroline': 'BrC1=CC2=C(Br)C(Br)=C3C=C(Br)C=NC3=C2N=C1',
+ '3,5-Bis(trifluoromethyl)phenylboronic Acid': 'OB(C1=CC(C(F)(F)F)=CC(C(F)(F)F)=C1)O',
+ '3,5-Di(2-pyridyl)pyrazole': 'C1(C2=NC=CC=C2)=NNC(C3=NC=CC=C3)=C1',
+ '3,5-Heptanedione': 'CCC(CC(CC)=O)=O',
+ '3,5-Lutidine': 'CC1=CC(C)=CN=C1',
+ '3,6-Di(2-pyridyl)-1,2,4,5-tetrazine': 'C1(C2=NC=CC=C2)=NN=C(C3=NC=CC=C3)N=N1',
+ '3,8-Dibromo-1,10-phenanthroline': 'BrC1=CC2=CC=C3C=C(Br)C=NC3=C2N=C1',
+ '3-[(Dimethylsilyl)oxy]-1,1,3,5,5-pentamethyltrisiloxane': 'C[SiH](C)O[Si](C)(O[SiH](C)C)O[SiH](C)C',
+ '3-[[Dimethyl(vinyl)silyl]oxy]-1,1,5,5-tetramethyl-3-phenyl-1,5-divinyltrisiloxane': 'C=C[Si](C)(C)O[Si](C1=CC=CC=C1)(O[Si](C)(C)C=C)O[Si](C)(C)C=C',
+ '3-[[tert-Butyl(dimethyl)silyl]oxy]-1-propanol': 'OCCCO[Si](C)(C(C)(C)C)C',
+ '3-Aminopropyltriethoxysilane': 'CCO[Si](OCC)(CCCN)OCC',
+ '3-Aminopropyltrimethoxysilane': 'CO[Si](OC)(CCCN)OC',
+ '3-Bromo-1-(trimethylsilyl)-1-propyne': 'C[Si](C#CCBr)(C)C',
+ '3-Bromo-1,10-phenanthroline': 'BrC1=CC2=CC=C3C=CC=NC3=C2N=C1',
+ '3-Chloroacetylacetone': 'CC(C(Cl)C(C)=O)=O',
+ '3-Chloroperoxybenzoic acid': 'C1=CC(=CC(=C1)Cl)C(=O)OO',
+ '3-Chloropropyltriethoxysilane': 'CCO[Si](OCC)(CCCCl)OCC',
+ '3-Ethyl-2,4-pentanedione': 'CC(C(CC)C(C)=O)=O',
+ '3-Glycidyloxypropyltrimethoxysilane': 'CO[Si](OC)(CCCOCC1CO1)OC',
+ '3-Mercaptopropyl(dimethoxy)methylsilane': 'C[Si](OC)(CCCS)OC',
+ '3-Methyl-1-phenyl-2-phospholene 1-Oxide': 'CC(CC1)=CP1(C2=CC=CC=C2)=O',
+ '3-Methyl-2,4-pentanedione': 'CC(C(C)C(C)=O)=O',
+ '3-Nitro-1,2,4-triazole': 'O=[N+](C1=NNC=N1)[O-]',
+ '3-Phenyl-2,4-pentanedione': 'CC(C(C1=CC=CC=C1)C(C)=O)=O',
+ '3-Pyridinecarboxylic Anhydride': 'O=C(OC(C1=CC=CN=C1)=O)C2=CC=CN=C2',
+ '3-Quinolineboronic acid': 'OB(C1=CC2=CC=CC=C2N=C1)O',
+ '3-Tolylboronic acid': 'CC1=CC=CC(B(O)O)=C1',
+ '3-Trimethoxysilylpropyl Chloride': 'CO[Si](CCCCl)(OC)OC',
+ '3-Trimethylsilyl-2-propyn-1-ol': 'OCC#C[Si](C)(C)C',
"4-([2,2':6',2''-Terpyridin]-4'-yl)benzoic Acid": 'O=C(O)C1=CC=C(C2=CC(C3=NC=CC=C3)=NC(C4=NC=CC=C4)=C2)C=C1',
- "4-(4,6-Dimethoxy-1,3,5-triazin-2-yl)-4-methylmorpholinium Chloride": 'C[N+]1(C2=NC(OC)=NC(OC)=N2)CCOCC1.[Cl-]',
+ '4-(4,6-Dimethoxy-1,3,5-triazin-2-yl)-4-methylmorpholinium Chloride': 'C[N+]1(C2=NC(OC)=NC(OC)=N2)CCOCC1.[Cl-]',
"4'-(4-Bromophenyl)-2,2':6',2''-terpyridine": 'BrC1=CC=C(C2=CC(C3=NC=CC=C3)=NC(C4=NC=CC=C4)=C2)C=C1',
- "4-(4-Dimethylaminophenylazo)phenylarsonic Acid Hydrochloride": 'O=[As](C1=CC=C(/N=N/C2=CC=C(N(C)C)C=C2)C=C1)(O)O.[H]Cl',
+ '4-(4-Dimethylaminophenylazo)phenylarsonic Acid Hydrochloride': 'O=[As](C1=CC=C(/N=N/C2=CC=C(N(C)C)C=C2)C=C1)(O)O.[H]Cl',
"4'-(4-Pyridyl)-2,2':6',2''-terpyridine": 'C1(C2=NC(C3=NC=CC=C3)=CC(C4=CC=NC=C4)=C2)=NC=CC=C1',
"4-(Bromomethyl)-4'-methyl-2,2'-bipyridyl": 'CC1=CC(C2=NC=CC(CBr)=C2)=NC=C1',
"4-(Chloromethyl)-4'-methyl-2,2'-bipyridyl": 'CC1=CC(C2=NC=CC(CCl)=C2)=NC=C1',
- "4-(Dimethylamino)phenyldiphenylphosphine": 'CN(C1=CC=C(P(C2=CC=CC=C2)C3=CC=CC=C3)C=C1)C',
- "4-(Dimethylamino)pyridine": 'CN(C1=CC=NC=C1)C',
- "4-(Diphenylphosphino)benzoic Acid": 'O=C(O)C1=CC=C(P(C2=CC=CC=C2)C3=CC=CC=C3)C=C1',
- "4-(N,N-Dimethylamino)phenylboronic acid": 'CN(C)C1=CC=C(B(O)O)C=C1',
- "4-(Trimethylsilyl)-3-butyn-2-one": 'CC(C#C[Si](C)(C)C)=O',
- "4-(Trimethylsilyl)diphenylacetylene": 'C[Si](C1=CC=C(C#CC2=CC=CC=C2)C=C1)(C)C',
- "4,4,4-Trifluoro-1-(2-naphthyl)-1,3-butanedione": 'O=C(C1=CC=C2C=CC=CC2=C1)CC(C(F)(F)F)=O',
- "4,4,4-Trifluoro-1-(2-thienyl)-1,3-butanedione": 'O=C(C1=CC=CS1)CC(C(F)(F)F)=O',
- "4,4,4-Trifluoro-1-(4-methoxyphenyl)-1,3-butanedione": 'O=C(C1=CC=C(OC)C=C1)CC(C(F)(F)F)=O',
- "4,4,4-Trifluoro-1-(p-tolyl)-1,3-butanedione": 'O=C(C1=CC=C(C)C=C1)CC(C(F)(F)F)=O',
- "4,4,4-Trifluoro-1-phenyl-1,3-butanedione": 'O=C(C1=CC=CC=C1)CC(C(F)(F)F)=O',
- "4,4,5,5-Tetramethyl-1,3,2-dioxaphospholane 2-Oxide": 'CC1(C)C(C)(C)OP(O1)=O',
+ '4-(Dimethylamino)phenyldiphenylphosphine': 'CN(C1=CC=C(P(C2=CC=CC=C2)C3=CC=CC=C3)C=C1)C',
+ '4-(Dimethylamino)pyridine': 'CN(C1=CC=NC=C1)C',
+ '4-(Diphenylphosphino)benzoic Acid': 'O=C(O)C1=CC=C(P(C2=CC=CC=C2)C3=CC=CC=C3)C=C1',
+ '4-(N,N-Dimethylamino)phenylboronic acid': 'CN(C)C1=CC=C(B(O)O)C=C1',
+ '4-(Trimethylsilyl)-3-butyn-2-one': 'CC(C#C[Si](C)(C)C)=O',
+ '4-(Trimethylsilyl)diphenylacetylene': 'C[Si](C1=CC=C(C#CC2=CC=CC=C2)C=C1)(C)C',
+ '4,4,4-Trifluoro-1-(2-naphthyl)-1,3-butanedione': 'O=C(C1=CC=C2C=CC=CC2=C1)CC(C(F)(F)F)=O',
+ '4,4,4-Trifluoro-1-(2-thienyl)-1,3-butanedione': 'O=C(C1=CC=CS1)CC(C(F)(F)F)=O',
+ '4,4,4-Trifluoro-1-(4-methoxyphenyl)-1,3-butanedione': 'O=C(C1=CC=C(OC)C=C1)CC(C(F)(F)F)=O',
+ '4,4,4-Trifluoro-1-(p-tolyl)-1,3-butanedione': 'O=C(C1=CC=C(C)C=C1)CC(C(F)(F)F)=O',
+ '4,4,4-Trifluoro-1-phenyl-1,3-butanedione': 'O=C(C1=CC=CC=C1)CC(C(F)(F)F)=O',
+ '4,4,5,5-Tetramethyl-1,3,2-dioxaphospholane 2-Oxide': 'CC1(C)C(C)(C)OP(O1)=O',
"4,4'-Bis(5-hexyl-2-thienyl)-2,2'-bipyridyl": 'CCCCCCC1=CC=C(C2=CC(C3=NC=CC(C4=CC=C(CCCCCC)S4)=C3)=NC=C2)S1',
"4,4'-Bis(chloromethyl)-2,2'-bipyridyl": 'ClCC1=CC(C2=NC=CC(CCl)=C2)=NC=C1',
"4,4'-Bis(hydroxymethyl)-2,2'-bipyridine": 'OCC1=CC(C2=NC=CC(CO)=C2)=NC=C1',
@@ -725,65 +725,65 @@ export const reagents_kombi = {
"4,4'-Dimethyl-2,2'-bipyridyl 1-Oxide": 'CC1=CC(C2=CC(C)=CC=[N+]2[O-])=NC=C1',
"4,4'-Dinonyl-2,2'-bipyridyl": 'CCCCCCCCCC1=CC(C2=NC=CC(CCCCCCCCC)=C2)=NC=C1',
"4,4'-Di-tert-butyl-2,2'-bipyridyl": 'CC(C1=CC(C2=NC=CC(C(C)(C)C)=C2)=NC=C1)(C)C',
- "4,5-Bis(diphenylphosphino)-9,9-dimethylxanthene": 'CC1(C)C2=C(OC3=C1C=CC=C3P(C4=CC=CC=C4)C5=CC=CC=C5)C(P(C6=CC=CC=C6)C7=CC=CC=C7)=CC=C2',
- "4,5-Diazafluoren-9-one": 'O=C1C2=CC=CN=C2C3=C1C=CC=N3',
- "4,5-Diazafluorene-9-one O-(p-Toluenesulfonyl)oxime": 'O=S(ON=C1C2=CC=CN=C2C3=C1C=CC=N3)(C4=CC=C(C)C=C4)=O',
- "4,6-Bis(diphenylphosphino)phenoxazine": 'C(C=CC=C1N2)(P(C3=CC=CC=C3)C4=CC=CC=C4)=C1OC5=C2C=CC=C5P(C6=CC=CC=C6)C7=CC=CC=C7',
- "4,6-Diphenylthieno[3,4-d]-1,3-dioxol-2-one 5,5-Dioxide": 'O=C(OC1=C2C3=CC=CC=C3)OC1=C(C4=CC=CC=C4)S2(=O)=O',
- "4,7-Dibromo-1,10-phenanthroline Hydrate": 'BrC1=CC=NC2=C3N=CC=C(Br)C3=CC=C12.[H]O[H]',
- "4,7-Dichloro-1,10-phenanthroline Hydrate": 'ClC1=CC=NC2=C3N=CC=C(Cl)C3=CC=C12.[H]O[H]',
- "4,7-Dihydroxy-1,10-phenanthroline": 'OC1=CC=NC2=C3N=CC=C(O)C3=CC=C12',
- "4,7-Dimethyl-1,10-phenanthroline": 'CC1=CC=NC2=C3N=CC=C(C)C3=CC=C12',
+ '4,5-Bis(diphenylphosphino)-9,9-dimethylxanthene': 'CC1(C)C2=C(OC3=C1C=CC=C3P(C4=CC=CC=C4)C5=CC=CC=C5)C(P(C6=CC=CC=C6)C7=CC=CC=C7)=CC=C2',
+ '4,5-Diazafluoren-9-one': 'O=C1C2=CC=CN=C2C3=C1C=CC=N3',
+ '4,5-Diazafluorene-9-one O-(p-Toluenesulfonyl)oxime': 'O=S(ON=C1C2=CC=CN=C2C3=C1C=CC=N3)(C4=CC=C(C)C=C4)=O',
+ '4,6-Bis(diphenylphosphino)phenoxazine': 'C(C=CC=C1N2)(P(C3=CC=CC=C3)C4=CC=CC=C4)=C1OC5=C2C=CC=C5P(C6=CC=CC=C6)C7=CC=CC=C7',
+ '4,6-Diphenylthieno[3,4-d]-1,3-dioxol-2-one 5,5-Dioxide': 'O=C(OC1=C2C3=CC=CC=C3)OC1=C(C4=CC=CC=C4)S2(=O)=O',
+ '4,7-Dibromo-1,10-phenanthroline Hydrate': 'BrC1=CC=NC2=C3N=CC=C(Br)C3=CC=C12.[H]O[H]',
+ '4,7-Dichloro-1,10-phenanthroline Hydrate': 'ClC1=CC=NC2=C3N=CC=C(Cl)C3=CC=C12.[H]O[H]',
+ '4,7-Dihydroxy-1,10-phenanthroline': 'OC1=CC=NC2=C3N=CC=C(O)C3=CC=C12',
+ '4,7-Dimethyl-1,10-phenanthroline': 'CC1=CC=NC2=C3N=CC=C(C)C3=CC=C12',
"4'-[(tert-Butyldimethylsilyloxy)methyl]-2,2,2-trifluoroacetophenone": 'O=C(C1=CC=C(CO[Si](C)(C(C)(C)C)C)C=C1)C(F)(F)F',
- "4-[2,2,2-Trifluoro-1-[(trimethylsilyl)oxy]ethyl]morpholine": 'C[Si](OC(N1CCOCC1)C(F)(F)F)(C)C',
- "4-[2-[2-(4-Iodophenoxy)ethoxy]carbonyl]benzoyloxy-2,2,6,6-tetramethylpiperidin-1-oxyl": '[O]N1C(C)(C)CC(OC(C2=CC=CC=C2C(OCCOC3=CC=C(I)C=C3)=O)=O)CC1(C)C',
- "4-Acetamido-2,2,6,6-tetramethyl-1-oxopiperidinium Tetrafluoroborate": 'O=[N+]1C(C)(C)CC(NC(C)=O)CC1(C)C.F[B-](F)(F)F',
- "4-Acetamido-2,2,6,6-tetramethylpiperidine 1-Oxyl": 'CC1(C)CC(NC(C)=O)CC(C)(C)N1[O]',
+ '4-[2,2,2-Trifluoro-1-[(trimethylsilyl)oxy]ethyl]morpholine': 'C[Si](OC(N1CCOCC1)C(F)(F)F)(C)C',
+ '4-[2-[2-(4-Iodophenoxy)ethoxy]carbonyl]benzoyloxy-2,2,6,6-tetramethylpiperidin-1-oxyl': '[O]N1C(C)(C)CC(OC(C2=CC=CC=C2C(OCCOC3=CC=C(I)C=C3)=O)=O)CC1(C)C',
+ '4-Acetamido-2,2,6,6-tetramethyl-1-oxopiperidinium Tetrafluoroborate': 'O=[N+]1C(C)(C)CC(NC(C)=O)CC1(C)C.F[B-](F)(F)F',
+ '4-Acetamido-2,2,6,6-tetramethylpiperidine 1-Oxyl': 'CC1(C)CC(NC(C)=O)CC(C)(C)N1[O]',
"4'-Bromo-2,2':6',2''-terpyridine": 'BrC1=CC(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=C1',
- "4-Bromotetraphenylsilane": 'BrC1=CC=C([Si](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)C=C1',
+ '4-Bromotetraphenylsilane': 'BrC1=CC=C([Si](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)C=C1',
"4'-Chloro-2,2':6',2''-terpyridine": 'ClC1=CC(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=C1',
- "4-Chlorophenyl Phosphorodichloridate": 'O=P(Cl)(Cl)OC1=CC=C(Cl)C=C1',
- "4-Dimethylamino-1-neopentylpyridinium Chloride": 'CC(C)(C)C[N+]1=CC=C(N(C)C)C=C1.[Cl-]',
- "4-Dimethylaminopyridine": 'CN(C1=CC=NC=C1)C',
- "4-Dimethylaminopyridinium Bromide Perbromide": 'CN(C)C1=CC=[NH+]C=C1.Br[Br-]Br',
- "4-Ethyl-4-methylmorpholinium Bromide": 'C[N+]1(CC)CCOCC1.[Br-]',
- "4-Fluoro-N-salicylideneaniline": 'OC1=CC=CC=C1/C=N/C2=CC=C(F)C=C2',
- "4-Fluorophenylmagnesium Bromide": 'Br[Mg]C1=CC=C(F)C=C1',
- "4-Hydroxy-2,2,6,6-tetramethylpiperidine 1-Oxyl Benzoate": 'CC1(C)CC(OC(C2=CC=CC=C2)=O)CC(C)(C)N1[O]',
- "4-Hydroxy-3-nitrophenylarsonic Acid": 'O=[As](C1=CC=C(O)C([N+]([O-])=O)=C1)(O)O',
+ '4-Chlorophenyl Phosphorodichloridate': 'O=P(Cl)(Cl)OC1=CC=C(Cl)C=C1',
+ '4-Dimethylamino-1-neopentylpyridinium Chloride': 'CC(C)(C)C[N+]1=CC=C(N(C)C)C=C1.[Cl-]',
+ '4-Dimethylaminopyridine': 'CN(C1=CC=NC=C1)C',
+ '4-Dimethylaminopyridinium Bromide Perbromide': 'CN(C)C1=CC=[NH+]C=C1.Br[Br-]Br',
+ '4-Ethyl-4-methylmorpholinium Bromide': 'C[N+]1(CC)CCOCC1.[Br-]',
+ '4-Fluoro-N-salicylideneaniline': 'OC1=CC=CC=C1/C=N/C2=CC=C(F)C=C2',
+ '4-Fluorophenylmagnesium Bromide': 'Br[Mg]C1=CC=C(F)C=C1',
+ '4-Hydroxy-2,2,6,6-tetramethylpiperidine 1-Oxyl Benzoate': 'CC1(C)CC(OC(C2=CC=CC=C2)=O)CC(C)(C)N1[O]',
+ '4-Hydroxy-3-nitrophenylarsonic Acid': 'O=[As](C1=CC=C(O)C([N+]([O-])=O)=C1)(O)O',
"4-Hydroxymethyl-4'-methyl-2,2'-bipyridyl": 'CC1=CC(C2=NC=CC(CO)=C2)=NC=C1',
- "4-Hydroxyphenylarsonic Acid": 'O=[As](C1=CC=C(O)C=C1)(O)O',
- "4-Methoxy-2,2,6,6-tetramethylpiperidine 1-Oxyl": 'CC1(C)CC(OC)CC(C)(C)N1[O]',
- "4-Methoxycarbonylphenylboronic acid": 'B(C1=CC=C(C=C1)C(=O)OC)(O)O',
- "4-Methylmorpholine N-Oxide": 'C[N+]1([O-])CCOCC1',
- "4-Nitrophenol": 'OC1=CC=C([N+]([O-])=O)C=C1',
- "4-Nitrophenyl Trifluoromethanesulfonate": 'O=S(C(F)(F)F)(OC1=CC=C([N+]([O-])=O)C=C1)=O',
- "4-Pyrrolidinopyridine": 'C1(N2CCCC2)=CC=NC=C1',
- "4-tert-Butyl-2,6-dimethylphenylsulfur Trifluoride": 'CC1=C(S(F)(F)F)C(C)=CC(C(C)(C)C)=C1',
- "4-Trifluoromethylbenzoic Anhydride": 'O=C(OC(C1=CC=C(C(F)(F)F)C=C1)=O)C2=CC=C(C(F)(F)F)C=C2',
- "4-Trimethylsilyl-3-butyn-2-ol": 'CC(O)C#C[Si](C)(C)C',
- "5-(Trimethylsilyl)-1,2,3,4,5-pentamethyl-1,3-cyclopentadiene": 'CC1([Si](C)(C)C)C(C)=C(C)C(C)=C1C',
- "5,10,15,20-Tetra(4-pyridyl)porphyrin": 'C1(C2=CC=NC=C2)=C3C=CC(C(C4=CC=NC=C4)=C5C=CC(N5)=C(C6=CC=NC=C6)C(C=C7)=NC7=C(C8=CC=NC=C8)C9=CC=C1N9)=N3',
- "5,10,15,20-Tetrakis(2,4,6-trimethylphenyl)porphyrin": 'CC1=C(C2=C3C=CC(C(C4=C(C)C=C(C)C=C4C)=C(N5)C=CC5=C(C6=C(C)C=C(C)C=C6C)C7=NC(C=C7)=C(C8=C(C)C=C(C)C=C8C)C9=CC=C2N9)=N3)C(C)=CC(C)=C1',
- "5,10,15,20-Tetrakis(2,6-dichlorophenyl)porphyrin": 'ClC1=C(C2=C3C=CC(C(C4=C(Cl)C=CC=C4Cl)=C(N5)C=CC5=C(C6=C(Cl)C=CC=C6Cl)C7=NC(C=C7)=C(C8=C(Cl)C=CC=C8Cl)C9=CC=C2N9)=N3)C(Cl)=CC=C1',
- "5,10,15,20-Tetrakis(3,5-dihydroxyphenyl)porphyrin": 'OC1=CC(O)=CC(C2=C3C=CC(C(C4=CC(O)=CC(O)=C4)=C(N5)C=CC5=C(C6=CC(O)=CC(O)=C6)C7=NC(C=C7)=C(C8=CC(O)=CC(O)=C8)C9=CC=C2N9)=N3)=C1',
- "5,10,15,20-Tetrakis(3,5-dimethoxyphenyl)porphyrin": 'COC1=CC(OC)=CC(C2=C3C=CC(C(C4=CC(OC)=CC(OC)=C4)=C(N5)C=CC5=C(C6=CC(OC)=CC(OC)=C6)C7=NC(C=C7)=C(C8=CC(OC)=CC(OC)=C8)C9=CC=C2N9)=N3)=C1',
- "5,10,15,20-Tetrakis(4-carboxymethyloxyphenyl)porphyrin": 'O=C(COC1=CC=C(C2=C3C=CC(C(C4=CC=C(OCC(O)=O)C=C4)=C(N5)C=CC5=C(C6=CC=C(OCC(O)=O)C=C6)C7=NC(C=C7)=C(C8=CC=C(OCC(O)=O)C=C8)C9=CC=C2N9)=N3)C=C1)O',
- "5,10,15,20-Tetrakis(4-hydroxyphenyl)porphyrin": 'OC1=CC=C(C2=C3C=CC(C(C4=CC=C(O)C=C4)=C(N5)C=CC5=C(C6=CC=C(O)C=C6)C7=NC(C=C7)=C(C8=CC=C(O)C=C8)C9=CC=C2N9)=N3)C=C1',
- "5,10,15,20-Tetrakis(4-methoxyphenyl)porphyrin": 'COC1=CC=C(C2=C3C=CC(C(C4=CC=C(OC)C=C4)=C(N5)C=CC5=C(C6=CC=C(OC)C=C6)C7=NC(C=C7)=C(C8=CC=C(OC)C=C8)C9=CC=C2N9)=N3)C=C1',
- "5,10,15,20-Tetrakis(pentafluorophenyl)porphyrin": 'FC1=C(F)C(F)=C(F)C(F)=C1C2=C3C=CC(C(C4=C(F)C(F)=C(F)C(F)=C4F)=C(N5)C=CC5=C(C6=C(F)C(F)=C(F)C(F)=C6F)C7=NC(C=C7)=C(C8=C(F)C(F)=C(F)C(F)=C8F)C9=CC=C2N9)=N3',
- "5,10,15,20-Tetrakis(p-tolyl)porphyrin": 'CC1=CC=C(C2=C3C=CC(C(C4=CC=C(C)C=C4)=C(N5)C=CC5=C(C6=CC=C(C)C=C6)C7=NC(C=C7)=C(C8=CC=C(C)C=C8)C9=CC=C2N9)=N3)C=C1',
+ '4-Hydroxyphenylarsonic Acid': 'O=[As](C1=CC=C(O)C=C1)(O)O',
+ '4-Methoxy-2,2,6,6-tetramethylpiperidine 1-Oxyl': 'CC1(C)CC(OC)CC(C)(C)N1[O]',
+ '4-Methoxycarbonylphenylboronic acid': 'B(C1=CC=C(C=C1)C(=O)OC)(O)O',
+ '4-Methylmorpholine N-Oxide': 'C[N+]1([O-])CCOCC1',
+ '4-Nitrophenol': 'OC1=CC=C([N+]([O-])=O)C=C1',
+ '4-Nitrophenyl Trifluoromethanesulfonate': 'O=S(C(F)(F)F)(OC1=CC=C([N+]([O-])=O)C=C1)=O',
+ '4-Pyrrolidinopyridine': 'C1(N2CCCC2)=CC=NC=C1',
+ '4-tert-Butyl-2,6-dimethylphenylsulfur Trifluoride': 'CC1=C(S(F)(F)F)C(C)=CC(C(C)(C)C)=C1',
+ '4-Trifluoromethylbenzoic Anhydride': 'O=C(OC(C1=CC=C(C(F)(F)F)C=C1)=O)C2=CC=C(C(F)(F)F)C=C2',
+ '4-Trimethylsilyl-3-butyn-2-ol': 'CC(O)C#C[Si](C)(C)C',
+ '5-(Trimethylsilyl)-1,2,3,4,5-pentamethyl-1,3-cyclopentadiene': 'CC1([Si](C)(C)C)C(C)=C(C)C(C)=C1C',
+ '5,10,15,20-Tetra(4-pyridyl)porphyrin': 'C1(C2=CC=NC=C2)=C3C=CC(C(C4=CC=NC=C4)=C5C=CC(N5)=C(C6=CC=NC=C6)C(C=C7)=NC7=C(C8=CC=NC=C8)C9=CC=C1N9)=N3',
+ '5,10,15,20-Tetrakis(2,4,6-trimethylphenyl)porphyrin': 'CC1=C(C2=C3C=CC(C(C4=C(C)C=C(C)C=C4C)=C(N5)C=CC5=C(C6=C(C)C=C(C)C=C6C)C7=NC(C=C7)=C(C8=C(C)C=C(C)C=C8C)C9=CC=C2N9)=N3)C(C)=CC(C)=C1',
+ '5,10,15,20-Tetrakis(2,6-dichlorophenyl)porphyrin': 'ClC1=C(C2=C3C=CC(C(C4=C(Cl)C=CC=C4Cl)=C(N5)C=CC5=C(C6=C(Cl)C=CC=C6Cl)C7=NC(C=C7)=C(C8=C(Cl)C=CC=C8Cl)C9=CC=C2N9)=N3)C(Cl)=CC=C1',
+ '5,10,15,20-Tetrakis(3,5-dihydroxyphenyl)porphyrin': 'OC1=CC(O)=CC(C2=C3C=CC(C(C4=CC(O)=CC(O)=C4)=C(N5)C=CC5=C(C6=CC(O)=CC(O)=C6)C7=NC(C=C7)=C(C8=CC(O)=CC(O)=C8)C9=CC=C2N9)=N3)=C1',
+ '5,10,15,20-Tetrakis(3,5-dimethoxyphenyl)porphyrin': 'COC1=CC(OC)=CC(C2=C3C=CC(C(C4=CC(OC)=CC(OC)=C4)=C(N5)C=CC5=C(C6=CC(OC)=CC(OC)=C6)C7=NC(C=C7)=C(C8=CC(OC)=CC(OC)=C8)C9=CC=C2N9)=N3)=C1',
+ '5,10,15,20-Tetrakis(4-carboxymethyloxyphenyl)porphyrin': 'O=C(COC1=CC=C(C2=C3C=CC(C(C4=CC=C(OCC(O)=O)C=C4)=C(N5)C=CC5=C(C6=CC=C(OCC(O)=O)C=C6)C7=NC(C=C7)=C(C8=CC=C(OCC(O)=O)C=C8)C9=CC=C2N9)=N3)C=C1)O',
+ '5,10,15,20-Tetrakis(4-hydroxyphenyl)porphyrin': 'OC1=CC=C(C2=C3C=CC(C(C4=CC=C(O)C=C4)=C(N5)C=CC5=C(C6=CC=C(O)C=C6)C7=NC(C=C7)=C(C8=CC=C(O)C=C8)C9=CC=C2N9)=N3)C=C1',
+ '5,10,15,20-Tetrakis(4-methoxyphenyl)porphyrin': 'COC1=CC=C(C2=C3C=CC(C(C4=CC=C(OC)C=C4)=C(N5)C=CC5=C(C6=CC=C(OC)C=C6)C7=NC(C=C7)=C(C8=CC=C(OC)C=C8)C9=CC=C2N9)=N3)C=C1',
+ '5,10,15,20-Tetrakis(pentafluorophenyl)porphyrin': 'FC1=C(F)C(F)=C(F)C(F)=C1C2=C3C=CC(C(C4=C(F)C(F)=C(F)C(F)=C4F)=C(N5)C=CC5=C(C6=C(F)C(F)=C(F)C(F)=C6F)C7=NC(C=C7)=C(C8=C(F)C(F)=C(F)C(F)=C8F)C9=CC=C2N9)=N3',
+ '5,10,15,20-Tetrakis(p-tolyl)porphyrin': 'CC1=CC=C(C2=C3C=CC(C(C4=CC=C(C)C=C4)=C(N5)C=CC5=C(C6=CC=C(C)C=C6)C7=NC(C=C7)=C(C8=CC=C(C)C=C8)C9=CC=C2N9)=N3)C=C1',
"5,5'-Bis(trifluoromethyl)-2,2'-bipyridyl": 'FC(C1=CN=C(C2=NC=C(C(F)(F)F)C=C2)C=C1)(F)F',
"5,5''-Bis(trimethylstannyl)-2,2':5',2''-terthiophene": 'C[Sn](C1=CC=C(C2=CC=C(C3=CC=C([Sn](C)(C)C)S3)S2)S1)(C)C',
"5,5'-Dibromo-2,2'-bipyridyl": 'BrC1=CN=C(C2=NC=C(Br)C=C2)C=C1',
"5,5-Dibromomeldrum's Acid": 'O=C(OC(C)(C)O1)C(Br)(Br)C1=O',
"5,5'-Dimethyl-2,2'-bipyridyl": 'CC1=CN=C(C2=NC=C(C)C=C2)C=C1',
- "5,6-Dimethyl-1,10-phenanthroline": 'CC1=C2C=CC=NC2=C3N=CC=CC3=C1C',
- "5-Bromo-1,10-phenanthroline": 'BrC1=C2C=CC=NC2=C3N=CC=CC3=C1',
- "5-Chloro-1,10-phenanthroline": 'ClC1=C2C=CC=NC2=C3N=CC=CC3=C1',
- "5-Methyl-1,10-phenanthroline Hydrate": 'CC1=C2C=CC=NC2=C3N=CC=CC3=C1.[H]O[H]',
- "5-Nitro-1,10-phenanthroline": 'O=[N+](C1=C2C=CC=NC2=C3N=CC=CC3=C1)[O-]',
- "5-Sulfosalicylic Acid Dihydrate": 'OC1=CC=C(S(=O)(O)=O)C=C1C(O)=O.[H]O[H].[H]O[H]',
+ '5,6-Dimethyl-1,10-phenanthroline': 'CC1=C2C=CC=NC2=C3N=CC=CC3=C1C',
+ '5-Bromo-1,10-phenanthroline': 'BrC1=C2C=CC=NC2=C3N=CC=CC3=C1',
+ '5-Chloro-1,10-phenanthroline': 'ClC1=C2C=CC=NC2=C3N=CC=CC3=C1',
+ '5-Methyl-1,10-phenanthroline Hydrate': 'CC1=C2C=CC=NC2=C3N=CC=CC3=C1.[H]O[H]',
+ '5-Nitro-1,10-phenanthroline': 'O=[N+](C1=C2C=CC=NC2=C3N=CC=CC3=C1)[O-]',
+ '5-Sulfosalicylic Acid Dihydrate': 'OC1=CC=C(S(=O)(O)=O)C=C1C(O)=O.[H]O[H].[H]O[H]',
"6,10-Dibenzyl-N,N'-dimethyl-N,N,N',N'-tetrakis(4-methylbenzyl)-1,4-dioxaspiro[4.5]decane-(2R,3R)-diylbis(methylammonium) Bis(tetrafluoroborate)": 'C[N+](CC1=CC=C(C)C=C1)(CC2=CC=C(C)C=C2)(C)[C@@H]3OC4(C(CC5=CC=CC=C5)CCCC4(CC6=CC=CC=C6)[N+](CC7=CC=C(C)C=C7)(CC8=CC=C(C)C=C8)(C)C)OC3.F[B-](F)(F)F.F[B-](F)(F)F',
"6,10-Dibenzyl-N,N'-dimethyl-N,N,N',N'-tetrakis(4-methylbenzyl)-1,4-dioxaspiro[4.5]decane-(2S,3S)-diylbis(methylammonium) Tetrafluoroborate": 'C[N+](CC1=CC=C(C)C=C1)(CC2=CC=C(C)C=C2)(C)[C@H]3OC4(C(CC5=CC=CC=C5)CCCC4(CC6=CC=CC=C6)[N+](CC7=CC=C(C)C=C7)(CC8=CC=C(C)C=C8)(C)C)OC3.F[B-](F)(F)F.F[B-](F)(F)F',
"6,6'-Bis(chloromethyl)-2,2'-bipyridyl": 'ClCC1=CC=CC(C2=NC(CCl)=CC=C2)=N1',
@@ -791,712 +791,712 @@ export const reagents_kombi = {
"6,6'-Dibromo-2,2'-bipyridyl": 'BrC1=CC=CC(C2=NC(Br)=CC=C2)=N1',
"6,6'-Dicyano-2,2'-bipyridyl": 'N#CC1=CC=CC(C2=NC(C#N)=CC=C2)=N1',
"6,6'-Dimethyl-2,2'-bipyridyl": 'CC1=CC=CC(C2=NC(C)=CC=C2)=N1',
- "6,7-Dihydro-2-(2,4,6-trimethylphenyl)-5H-pyrrolo[2,1-c]-1,2,4-triazolium Perchlorate": 'CC1=C([N+]2=CN3C(CCC3)=N2)C(C)=CC(C)=C1.O=Cl(=O)([O-])=O',
- "6,7-Dihydro-2-pentafluorophenyl-5H-pyrrolo[2,1-c][1,2,4]triazolium Tetrafluoroborate": 'FC1=C(F)C(F)=C(F)C(F)=C1[N+]2=CN3C(CCC3)=N2.F[B-](F)(F)F',
- "6,8-Bis(benzylthio)octanoic Acid": 'O=C(O)CCCCC(SCC1=CC=CC=C1)CCSCC2=CC=CC=C2',
+ '6,7-Dihydro-2-(2,4,6-trimethylphenyl)-5H-pyrrolo[2,1-c]-1,2,4-triazolium Perchlorate': 'CC1=C([N+]2=CN3C(CCC3)=N2)C(C)=CC(C)=C1.O=Cl(=O)([O-])=O',
+ '6,7-Dihydro-2-pentafluorophenyl-5H-pyrrolo[2,1-c][1,2,4]triazolium Tetrafluoroborate': 'FC1=C(F)C(F)=C(F)C(F)=C1[N+]2=CN3C(CCC3)=N2.F[B-](F)(F)F',
+ '6,8-Bis(benzylthio)octanoic Acid': 'O=C(O)CCCCC(SCC1=CC=CC=C1)CCSCC2=CC=CC=C2',
"6-Bromo-2,2'-bipyridyl": 'BrC1=CC=CC(C2=NC=CC=C2)=N1',
"6-Bromo-4,4'-dimethyl-2,2'-bipyridyl": 'CC1=CC(C2=NC(Br)=CC(C)=C2)=NC=C1',
- "6-Methyl-2,4-heptanedione": 'CC(CC(CC(C)C)=O)=O',
- "7-Methyl-1,5,7-triazabicyclo[4.4.0]dec-5-ene": 'CN1C2=NCCCN2CCC1',
- "8-Ethylquinoline N-oxide": 'CCC1=CC=CC2=CC=C[N+]([O-])=C12',
- "8-Quinolineboronic acid": 'OB(C1=C(N=CC=C2)C2=CC=C1)O',
- "9-(2,5-Dimethylphenyl)-10-methylacridinium Perchlorate": 'C[N+]1=C2C=CC=CC2=C(C3=CC(C)=CC=C3C)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
- "9-(2,6-Dimethylphenyl)-10-methylacridinium Perchlorate": 'C[N+]1=C2C=CC=CC2=C(C3=C(C)C=CC=C3C)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
- "9-(2-Biphenylyl)-10-methylacridinium Perchlorate": 'C[N+]1=C2C=CC=CC2=C(C3=CC=CC=C3C4=CC=CC=C4)C5=C1C=CC=C5.O=Cl(=O)([O-])=O',
- "9-Azajulolidine": 'N1(CCC2)CCCC3=CN=CC2=C31',
- "9H,9H-Triacontafluoro-8,10-heptadecanedione": 'O=C(CC(C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F)=O)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F',
- "9-Mesityl-10-methylacridinium Perchlorate": 'C[N+]1=C2C=CC=CC2=C(C3=C(C)C=C(C)C=C3C)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
- "9-Mesityl-2,7,10-trimethylacridinium Perchlorate": 'C[N+]1=C2C=CC(C)=CC2=C(C3=C(C)C=C(C)C=C3C)C4=C1C=CC(C)=C4.O=Cl(=O)([O-])=O',
- "9-Methyl-3,4-dihydro-2H-pyrido[1,2-a]pyrimidin-2-one": 'O=C1N=C(C(C)=CC=C2)N2CC1',
- "Acenaphthylene": 'C12=CC=CC3=C1C(C=C2)=CC=C3',
- "acetic acid": 'CC(O)=O',
- "Acetic Acid (1R,2S)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Ester": 'CC(O[C@H](C1=CC=CC=C1)[C@@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
- "Acetic Acid (1S,2R)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Ester": 'CC(O[C@@H](C1=CC=CC=C1)[C@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
- "acetone": 'CC(C)=O',
- "acetonitrile": 'CC#N',
- "Acetylacetone": 'CC(CC(C)=O)=O',
- "AlkylFluor": 'FC(N(C=C1)C2=C(C(C)C)C=CC=C2C(C)C)=[N+]1C(C(C(C)C)=CC=C3)=C3C(C)C.F[B-](F)(F)F',
- "Allyl(chloromethyl)dimethylsilane": 'C[Si](CCl)(CC=C)C',
- "Allyl(tert-butyl)dimethylsilane": 'C[Si](C(C)(C)C)(CC=C)C',
- "Allylchlorodimethylsilane": 'C[Si](Cl)(CC=C)C',
- "Allylmagnesium Bromide": 'Br[Mg]CC=C',
- "Allylmagnesium Chloride": 'Cl[Mg]CC=C',
- "Allyloxytrimethylsilane": 'C[Si](C)(OCC=C)C',
- "Allylpalladium(II) Chloride": '[Pd+]CC=C.[Cl-]',
- "Allyltriethoxysilane": 'CCO[Si](OCC)(CC=C)OCC',
- "Allyltriethylsilane": 'CC[Si](CC)(CC=C)CC',
- "Allyltriisopropylsilane": 'CC([Si](C(C)C)(CC=C)C(C)C)C',
- "Allyltrimethoxysilane": 'CO[Si](OC)(CC=C)OC',
- "Allyltrimethylsilane": 'C[Si](C)(CC=C)C',
- "Allyltriphenyltin": 'C=CC[Sn](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Allyltris(trimethylsilyloxy)silane": 'C[Si](O[Si](O[Si](C)(C)C)(CC=C)O[Si](C)(C)C)(C)C',
- "aluminium bromide": '[Al+3].[Br-].[Br-].[Br-]',
- "Aluminium chloride": 'Cl[Al](Cl)Cl',
- "Aluminium hydroxide": '[OH-].[Al+3].[OH-].[OH-]',
- "aluminium iodide": '[Al+3].[I-].[I-].[I-]',
- "Aluminum Bromide Anhydrous": '[Al+3].[Br-].[Br-].[Br-]',
- "Aluminum Glycinate": 'NCC([O-])=O.NCC([O-])=O.NCC([O-])=O.[Al+3]',
- "Aluminum Isopropoxide": 'CC([O-])C.CC([O-])C.CC([O-])C.[Al+3]',
- "Aluminum(III) Bromide": '[Al+3].[Br-].[Br-].[Br-]',
- "Aluminum(III) Chloride": '[Al+3].[Cl-].[Cl-].[Cl-]',
- "Aminomethanesulfonic Acid": 'O=S(CN)(O)=O',
- "Ammonia": 'N',
- "ammonium actetate": 'CC([O-])=O.[NH4+]',
- "ammonium bromide": '[NH4+].[Br-]',
- "ammonium carbamate": 'NC([O-])=O.[NH4+]',
- "Ammonium Cerium(IV) Nitrate": '[O-][N+]([O-])=O.[O-][N+]([O-])=O.[O-][N+]([O-])=O.[O-][N+]([O-])=O.[O-][N+]([O-])=O.[NH4+].[Ce+4]',
- "ammonium chloride": '[NH4+].[Cl-]',
- "Ammonium dichromate": 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.[NH4+].[NH4+]',
- "ammonium fluoride": '[NH4+].[F-]',
- "ammonium formate": 'O=C[O-].[NH4+]',
- "ammonium hydrogensulfate": '[O-]S(=O)(O)=O.[NH4+]',
- "Ammonium hydroxide": '[NH4+].[OH-]',
- "Ammonium phosphomolybdate hydrate": 'O=[Mo](OP(O)(O)=O)([O-])=O.[H]O[H].[NH4+]',
- "Ammonium sulfate": 'O=S([O-])([O-])=O.[NH4+].[NH4+]',
- "ammonium tetrafluoroborate": 'F[B-](F)(F)F.[NH4+]',
- "ammoniumthiosulfate": 'O=S([O-])([O-])=S.[NH4+].[NH4+]',
- "Amyltriethylammonium Bis(trifluoromethanesulfonyl)imide": 'CCC[N+](CCC)(CCC)CCC.FC(F)(F)S([N-]S(C(F)(F)F)(=O)=O)(=O)=O',
- "B(CH3)3": 'CB(C)C',
- "B(OH)3": 'OB(O)O',
- "Barium hydroxide": '[Ba+2].[OH-].[OH-]',
- "Barium hydroxide octahydrate": '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ba+2].[OH-].[OH-]',
- "Barium tert-butoxide": 'CC(C)([O-])C.CC(C)([O-])C.[Ba+2]',
- "Bathophenanthroline": 'C1(C2=CC=CC=C2)=CC=NC3=C4N=CC=C(C5=CC=CC=C5)C4=CC=C13',
- "Bathophenanthrolinedisulfonic Acid Disodium Salt Hydrate": 'O=S(C1=NC2=C3N=CC=C(C4=CC=CC=C4)C3=CC=C2C(C5=CC=CC=C5)=C1S(=O)([O-])=O)([O-])=O.[H]O[H].[Na+].[Na+]',
- "benzene": 'C1=CC=CC=C1',
- "Benzeneruthenium(II) Chloride": '[Ru+2].C1=CC=CC=C1.[Cl-].[Cl-]',
- "Benzenesulfonic Acid Anhydrous": 'O=S(C1=CC=CC=C1)(O)=O',
- "Benzenesulfonic Acid Monohydrate": 'O=S(C1=CC=CC=C1)(O)=O.[H]O[H]',
- "Benzoic Acid": 'O=C(O)C1=CC=CC=C1',
- "Benzoyl peroxide": 'O=C(OOC(C1=CC=CC=C1)=O)C2=CC=CC=C2',
- "Benzoyl(phenyliodonio)(trifluoromethanesulfonyl)methanide": 'O=S([C-](C(C1=CC=CC=C1)=O)[I+]C2=CC=CC=C2)(C(F)(F)F)=O',
- "Benzylcetyldimethylammonium Chloride Hydrate": 'C[N+](CCCCCCCCCCCCCCCC)(CC1=CC=CC=C1)C.[H]O[H].[Cl-]',
- "Benzyldimethyltetradecylammonium Chloride Hydrate": 'CCCCCCCCCCCCCC[N+](C)(CC1=CC=CC=C1)C.[H]O[H].[Cl-]',
- "Benzyldodecyldimethylammonium Bromide": 'C[N+](CCCCCCCCCCCC)(CC1=CC=CC=C1)C.[Br-]',
- "Benzyldodecyldimethylammonium Chloride Dihydrate": 'C[N+](CCCCCCCCCCCC)(CC1=CC=CC=C1)C.[H]O[H].[H]O[H].[Cl-]',
- "Benzylmagnesium Bromide": 'Br[Mg]CC1=CC=CC=C1',
- "Benzylmagnesium Chloride": 'Cl[Mg]CC1=CC=CC=C1',
- "Benzyltributylammonium Bromide": 'CCCC[N+](CCCC)(CC1=CC=CC=C1)CCCC.[Br-]',
- "Benzyltributylammonium Chloride": 'CCCC[N+](CCCC)(CC1=CC=CC=C1)CCCC.[Cl-]',
- "Benzyltriethylammonium Borohydride": 'CC[N+](CC)(CC1=CC=CC=C1)CC.[BH4-]',
- "Benzyltriethylammonium Bromide": 'CC[N+](CC)(CC1=CC=CC=C1)CC.[Br-]',
- "Benzyltriethylammonium Chloride": 'CC[N+](CC)(CC1=CC=CC=C1)CC.[Cl-]',
- "Benzyltriethylammonium Iodide": 'CC[N+](CC)(CC1=CC=CC=C1)CC.[I-]',
- "Benzyltrimethylammonium Bromide": 'C[N+](C)(CC1=CC=CC=C1)C.[Br-]',
- "Benzyltrimethylammonium Chloride": 'C[N+](C)(CC1=CC=CC=C1)C.[Cl-]',
- "Benzyltrimethylammonium Dichloroiodate": 'C[N+](C)(CC1=CC=CC=C1)C.Cl[I-]Cl',
- "Benzyltrimethylammonium Hydroxide": 'C[N+](C)(CC1=CC=CC=C1)C.[OH-]',
- "Benzyltrimethylammonium Tetrachloroiodate": 'C[N+](C)(CC1=CC=CC=C1)C.Cl[I-](Cl)(Cl)Cl',
- "Benzyltrimethylammonium Tribromide": 'C[N+](C)(CC1=CC=CC=C1)C.[Br-].[Br-].[Br-]',
- "Benzyltrimethylsilane": 'C[Si](C)(CC1=CC=CC=C1)C',
- "BERYLLIUM": '[Be]',
- "BERYLLIUM HYDROXIDE": '[Be+2].[OH-].[OH-]',
- "BF3": 'FB(F)F',
- "Bicinchoninic Acid Disodium Salt Hydrate": 'O=C([O-])C1=C(C2=C(C([O-])=O)C3=CC=CC=C3N=C2)C=NC4=CC=CC=C14.[H]O[H].[Na+].[Na+]',
- "Bis(1,3-propanediamine) Copper(II) Dichloride": 'NCCCN.NCCCN.[Cu+2].[Cl-].[Cl-]',
- "Bis(1,5-cyclooctadiene)nickel(0)": '[Ni].C1=C\\CC/C=C\\CC/1.C2=C\\CC/C=C\\CC/2',
- "Bis(1,5-cyclooctadiene)rhodium(I) Tetrafluoroborate": 'F[B-](F)(F)F.[Rh+].C1=C\\CC/C=C\\CC/1.C2=C\\CC/C=C\\CC/2',
- "Bis(2,4,6-trimethylpyridine)bromonium Hexafluorophosphate": 'CC1=CC(C)=C([BrH+])C(C)=N1.CC2=CC(C)=CC(C)=N2.F[P-](F)(F)(F)(F)F',
- "Bis(2,4,6-trimethylpyridine)iodonium Hexafluorophosphate": 'CC1=CC(C)=C([IH+])C(C)=N1.CC2=CC(C)=CC(C)=N2.F[P-](F)(F)(F)(F)F',
- "Bis(2,4-pentanedionato)bis(2-propanolato)titanium(IV)": 'CC(/C=C(C)\\[O-])=O.CC(/C=C(C)\\[O-])=O.[O-]C(C)C.[O-]C(C)C.[Ti+4]',
- "Bis(2,4-pentanedionato)cobalt(II)": 'C/C([O-])=C/C(C)=O.C/C([O-])=C/C(C)=O.[Co+2].O',
- "Bis(2,4-pentanedionato)cobalt(II) Dihydrate": 'C/C([O-])=C/C(C)=O.C/C([O-])=C/C(C)=O.[Co+2].O.O',
- "Bis(2,4-pentanedionato)manganese(II) Dihydrate": 'CC(/C=C([O-])/C)=O.CC(/C=C([O-])/C)=O.[Mn+2].O.O',
- "Bis(2,4-pentanedionato)molybdenum(VI) Dioxide": 'CC(/C=C([O-])/C)=O.C/C([O-])=C/C(C)=O.[Mo+6].[O-2].[O-2]',
- "Bis(2,4-pentanedionato)nickel(II) Hydrate": 'O=C(/C=C([O-])/C)C.O=C(/C=C([O-])/C)C.[Ni+2].O',
- "Bis(2,4-pentanedionato)vanadium(IV) Oxide": 'CC(/C=C([O-])/C)=O.[O-]/C(C)=C\\C(C)=O.[V+4].[O-2]',
- "Bis(2-hydroxyethyl)dimethylammonium Chloride": 'C[N+](CCO)(CCO)C.[Cl-]',
- "Bis(4-bromophenyl)iodonium triflate": 'BrC1=CC=C([I+]C2=CC=C(Br)C=C2)C=C1.O=S([O-])(C(F)(F)F)=O',
- "Bis(4-fluorophenyl)iodonium triflate": 'FC1=CC=C([I+]C2=CC=C(F)C=C2)C=C1.O=S([O-])(C(F)(F)F)=O',
- "Bis(4-methoxyphenyl) Selenoxide": 'O=[Se](C1=CC=C(OC)C=C1)C2=CC=C(OC)C=C2',
- "Bis(4-methylphenyl)iodonium triflate": 'CC1=CC=C([I+]C2=CC=C(C)C=C2)C=C1.O=S([O-])(C(F)(F)F)=O',
- "Bis(4-nitrophenyl) Carbonate": 'O=C(OC1=CC=C([N+]([O-])=O)C=C1)OC2=CC=C([N+]([O-])=O)C=C2',
- "Bis(acetato)aqua[(S,S)-4,6-bis(4-isopropyl-2-oxazolin-2-yl)-m-xylene]rhodium": 'CC1=CC(C)=C(C2=N[C@H](CO2)C(C)C)C=C1C3=N[C@@H](C(C)C)CO3.CC([O-])=O.[O-]C(C)=O.[Rh+2].O',
- "Bis(acetonitrile)palladium(II) Dichloride": 'CC#N.CC#N.[Pd+2].[Cl-].[Cl-]',
- "Bis(benzonitrile)palladium(II) Dichloride": 'N#CC1=CC=CC=C1.N#CC2=CC=CC=C2.[Pd+2].[Cl-].[Cl-]',
- "Bis(chloromethyl)dimethylsilane": 'C[Si](CCl)(CCl)C',
- "Bis(dibenzylideneacetone)palladium(0)": 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.[Pd]',
- "Pd(dba)2": 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.[Pd]',
- "Bis(diphenylphosphino)methane": 'P(CP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "Bis(hexafluoroacetylacetonato)nickel(II) Hydrate": 'O=C(/C=C(C(F)(F)F)\\[O-])C(F)(F)F.[O-]/C(C(F)(F)F)=C\\C(C(F)(F)F)=O.[Ni+2]',
- "Bis(pentafluorophenyl) Carbonate": 'O=C(OC1=C(F)C(F)=C(F)C(F)=C1F)OC2=C(F)C(F)=C(F)C(F)=C2F',
- "Bis(pentafluorophenyl)dimethylsilane": 'C[Si](C1=C(F)C(F)=C(F)C(F)=C1F)(C2=C(F)C(F)=C(F)C(F)=C2F)C',
- "Bis(pentafluorophenyl)phenylphosphine": 'FC1=C(F)C(F)=C(F)C(F)=C1P(C2=C(F)C(F)=C(F)C(F)=C2F)C3=CC=CC=C3',
- "Bis(pinacolato)diboron": 'B1(OC(C(O1)(C)C)(C)C)B2OC(C(O2)(C)C)(C)C',
- "BPin": 'B1(OC(C(O1)(C)C)(C)C)B2OC(C(O2)(C)C)(C)C',
- "Bis(pyridine)iodonium tetrafluoroborate": '[IH+]C1=NC=CC=C1.F[B-](F)(F)F.C2=NC=CC=C2',
- "Bis(tert-butylcarbonyloxy)iodobenzene": 'IC1=CC=CC(OC(C(C)(C)C)=O)=C1OC(C(C)(C)C)=O',
- "Bis(tetrabutylammonium) Dichromate": 'CCCC[N+](CCCC)(CCCC)CCCC.CCCC[N+](CCCC)(CCCC)CCCC.O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O',
- "Bis(trichlorosilyl)acetylene": 'Cl[Si](C#C[Si](Cl)(Cl)Cl)(Cl)Cl',
- "Bis(tricyclohexylphosphine)nickel(II) Dichloride": 'P(C1CCCCC1)(C2CCCCC2)C3CCCCC3.P(C4CCCCC4)(C5CCCCC5)C6CCCCC6.[Ni+2].[Cl-].[Cl-]',
- "Bis(tricyclohexylphosphine)palladium(II) Dichloride": 'P(C1CCCCC1)(C2CCCCC2)C3CCCCC3.P(C4CCCCC4)(C5CCCCC5)C6CCCCC6.[Pd+2].[Cl-].[Cl-]',
- "Bis(trifluoro-2,4-pentanedionato)cobalt(II) Hydrate": 'C/C([O-])=C/C(C(F)(F)F)=O.C/C([O-])=C/C(C(F)(F)F)=O.[Co+2]',
- "Bis(trifluoromethanesulfonyl)imide": 'O=S(C(F)(F)F)(NS(=O)(C(F)(F)F)=O)=O',
- "Bis(trimethylsilyl) Sulfide": 'C[Si](S[Si](C)(C)C)(C)C',
- "Bis(trimethylsilyl)acetylene": 'C[Si](C#C[Si](C)(C)C)(C)C',
- "Bis(trimethylsilyl)bromomethane": 'BrC([Si](C)(C)C)[Si](C)(C)C',
- "Bis(trimethylsilyl)methane": 'C[Si](C[Si](C)(C)C)(C)C',
- "Bis(trimethylsilyl)methylamine": 'CN([Si](C)(C)C)[Si](C)(C)C',
- "Bis(tri-o-tolylphosphine)palladium(II) Dichloride": 'CC1=CC=CC=C1P(C2=CC=CC=C2C)C3=CC=CC=C3C.CC4=CC=CC=C4P(C5=CC=CC=C5C)C6=CC=CC=C6C.[Pd+2].[Cl-].[Cl-]',
- "Bis(triphenylphosphine)nickel(II) Dichloride": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.[Ni+2].[Cl-].[Cl-]',
- "Bis(triphenylphosphine)palladium(II) Diacetate": 'CC([O-])=O.CC([O-])=O.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.[Pd+2]',
- "Bis(triphenylphosphine)palladium(II) Dichloride": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.[Pd+2].[Cl-].[Cl-]',
- "Bis(triphenylsilyl) chromate": 'O=[Cr](O[Si](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3)(O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=O',
- "Bis(tri-tert-butylphosphine)palladium(0)": 'CC(P(C(C)(C)C)C(C)(C)C)(C)C.CC(P(C(C)(C)C)C(C)(C)C)(C)C.[Pd]',
- "Bis[1,2-bis(diphenylphosphino)ethane]palladium(0)": 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.P(CCP(C5=CC=CC=C5)C6=CC=CC=C6)(C7=CC=CC=C7)C8=CC=CC=C8.[Pd]',
- "Bis[2-(diphenylphosphino)phenyl] Ether": 'C1(OC2=CC=CC=C2P(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1P(C5=CC=CC=C5)C6=CC=CC=C6',
- "Bis[2-(trimethylsilyloxy)ethyl] Ether": 'C[Si](OCCOCCO[Si](C)(C)C)(C)C',
- "Bis[2-carboxyethylgermanium(IV)] Sesquioxide": 'O=[Ge](CCC(O)=O)O[Ge](CCC(O)=O)=O',
- "Bis[3-(trimethoxysilyl)propyl]amine": 'CO[Si](CCCNCCC[Si](OC)(OC)OC)(OC)OC',
- "Bis[di-tert-butyl(4-dimethylaminophenyl)phosphine]palladium(0)": 'CN(C1=CC=C(P(C(C)(C)C)C(C)(C)C)C=C1)C.CN(C2=CC=C(P(C(C)(C)C)C(C)(C)C)C=C2)C.[Pd]',
- "Bis[tris(2,4-pentanedionato)titanium(IV)] Hexachlorotitanate(IV)": 'Cl[Ti-2](Cl)(Cl)(Cl)(Cl)Cl.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.[Ti+4].[Ti+4]',
- "BISMUTH HYDROXIDE": '[Bi+3].[OH-].[OH-].[OH-]',
- "Bismuth Tripotassium Dicitrate": 'OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.[Bi+5].[K+].[K+].[K+]',
- "Bistrifluoroacetamide": 'O=C(C(F)(F)F)NC(C(F)(F)F)=O',
- "Borane - 2-Methylpyridine Complex": 'CC1=NC=CC=C1.B',
- "Borane - 5-Ethyl-2-methylpyridine Complex": 'CC1=NC=C(CC)C=C1.B',
- "Borane - Ammonia Complex": 'B.N',
- "Borane - Diisopropylamine Complex": 'CC(C)NC(C)C.B',
- "Borane - Morpholine Complex": 'O1CCNCC1.B',
- "Borane - Pyridine Complex": 'C1=CN=CC=C1.B',
- "Borane - Tetrahydrofuran Complex": 'B.C1COCC1',
- "Borane - tert-Butylamine Complex": 'NC(C)(C)C.B',
- "Boron Trichloride": 'ClB(Cl)Cl',
- "Boron Trifluoride": 'FB(F)F',
- "Boron Trifluoride - Methanol Reagent": 'FB(F)F.CO',
- "Boron Trifluoride - Propanol Reagent": 'FB(F)F.CCCO',
- "Bromine": 'BrBr',
- "Bromine - 1,4-Dioxane Complex": 'BrBr.O1CCOCC1',
- "Bromo[(2,6-pyridinediyl)bis(3-methyl-1-imidazolyl-2-ylidene)]nickel Bromide": 'CN(C=CN12)C1=[Ni-3](Br)=C3N(C)C=CN3C4=CC=CC2=N4.[Br-]',
- "Bromo[[1,3-bis[(4S,5S)-1-benzoyl-4,5-diphenyl-2-imidazolin-2-yl]benzene]palladium(II)]": 'O=C(N1[C@@H](C2=CC=CC=C2)[C@H](C3=CC=CC=C3)N=C1C4=CC(C5=N[C@@H](C6=CC=CC=C6)[C@H](C7=CC=CC=C7)N5C(C8=CC=CC=C8)=O)=CC=C4)C9=CC=CC=C9.[Pd+]Br',
- "Bromoacetic Acid": 'O=C(O)CBr',
- "Bromocholine Bromide": 'BrCC[N+](C)(C)C.[Br-]',
- "Bromodicarbonyl[bis[2-(diisopropylphosphino)ethyl]amine]manganese(I)": '[C]=O.[C]=O.CC(P(CCNCCP(C(C)C)C(C)C)C(C)C)C.[Mn]Br',
- "Bromodimethylsulfonium Bromide": 'C[S+](Br)C.[Br-]',
- "Bromotrichloromethane": 'ClC(Cl)(Br)Cl',
- "Bromotrimethylsilane": 'Br[Si](C)(C)C',
- "Bromotripyrrolidinophosphonium Hexafluorophosphate": 'Br[P+](N1CCCC1)(N2CCCC2)N3CCCC3.F[P-](F)(F)(F)(F)F',
- "Bromotris(dimethylamino)phosphonium Hexafluorophosphate": 'CN([P+](N(C)C)(Br)N(C)C)C.F[P-](F)(F)(F)(F)F',
- "Butylboronic Acid": 'CCCCB(O)O',
- "Butyllithium": 'CCCC[Li]',
- "Butylmagnesium Bromide": 'Br[Mg]CCCC',
- "Butylmagnesium Chloride": 'Cl[Mg]CCCC',
- "Butyltin Trichloride": 'CCCC[Sn](Cl)(Cl)Cl',
- "Cacodylic Acid": 'O=[As](C)(C)O',
- "CADMIUM HYDROXIDE": '[Cd+2].[OH-].[OH-]',
- "CALCIUM BROMIDE HYDRATE": '[H]O[H].[Ca+2].[Br-].[Br-]',
- "calcium carbonate": '[O-]C([O-])=O.[Ca+2]',
- "calcium chloride": '[Ca+2].[Cl-].[Cl-]',
- "calcium hydride": '[Ca+2].[H-].[H-]',
- "Calcium peroxide": '[O-][O-].[Ca+2]',
- "calcium sulfate": 'O=S([O-])([O-])=O.[Ca+2]',
- "Calcium L-Threonate": 'O[C@H]([C@H](CO)O)C([O-])=O.O[C@H]([C@H](CO)O)C([O-])=O.[Ca+2]',
- "Carbamylcholine Chloride": 'C[N+](C)(C)CCOC(N)=O.[Cl-]',
- "Carbon Tetrabromide": 'BrC(Br)(Br)Br',
- "carbon tetrachloride": 'ClC(Cl)(Cl)Cl',
- "Carbon Tetraiodide": 'IC(I)(I)I',
- "carbon tribromide": 'BrC(Br)([H])Br',
- "Carbonyl(dihydrido)tris(triphenylphosphine)ruthenium(II)": '[C]=O.[H][Ru][H].P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9',
- "Carbonylchlorobis(triphenylphosphine)iridium(I)": '[C]=O.[Ir]Cl.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6',
- "Carbonylhydridotris(triphenylphosphine)iridium(I)": '[C]=O.[Ir][H].P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9',
- "Cerium": '[Ce]',
- "Cerium tetrahydroxide": '[Ce+4].[OH-].[OH-].[OH-].[OH-]',
- "cerium trihydroxide": '[Ce+3].[OH-].[OH-].[OH-]',
- "Cerium(III) Acetate Hydrate": 'CC([O-])=O.CC([O-])=O.CC([O-])=O.[H]O[H].[Ce+3]',
- "CERIUM(III) CHLORIDE HEPTAHYDRATE": '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ce+3].[Cl-].[Cl-].[Cl-]',
- "Cerium(III) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Ce+3]',
- "Cesium Acetate": 'CC([O-])=O.[Cs+]',
- "cesium bromide": '[Cs+].[Br-]',
- "Cesium Carbonate": '[O-]C([O-])=O.[Cs+].[Cs+]',
- "Cesium Fluoride": '[Cs+].[F-]',
- "Cesium hydroxide": '[Cs+].[OH-]',
- "Cesium Pivalate": 'CC(C)(C)C([O-])=O.[Cs+]',
- "cesium sulfate": 'O=S([O-])([O-])=O.[Cs+].[Cs+]',
- "Chloramine B Hydrate": 'O=S([N-]Cl)(C1=CC=CC=C1)=O.O.[Na+]',
- "Chloramine T Trihydrate": 'CC1=CC=C(S(=O)([N-]Cl)=O)C=C1.[H]O[H].[H]O[H].[H]O[H].[Na+]',
- "Chloranil": 'O=C(C(Cl)=C1Cl)C(Cl)=C(Cl)C1=O',
- "Chloro(1,5-cyclooctadiene)iridium(I)": '[Ir]Cl.C1=C\\CC/C=C\\CC/1',
- "Chloro(1,5-cyclooctadiene)rhodium(I)": '[Rh]Cl.C1=C\\CC/C=C\\CC/1',
- "Chloro(1,5-hexadiene)rhodium(I)": 'C=CCCC=C.[Rh]Cl',
- "Chloro(2-dicyclohexylphosphino-2′,4′,6′-triisopropyl-1,1′-biphenyl)[2-(2′-amino-1,1′-biphenyl)]palladium(II)": 'Cl[Pd]1(C2=CC=CC=C2C3=CC=CC=C3N1)P(C4CCCCC4)(C5=CC=CC=C5C6=C(C(C)C)C=C(C(C)C)C=C6C(C)C)C7CCCCC7',
- "Chloro(3-chloropropyl)dimethylsilane": 'C[Si](CCCCl)(Cl)C',
- "Chloro(hexyl)dimethylsilane": 'C[Si](CCCCCC)(Cl)C',
- "Chloro(methyl)(phenyl)(vinyl)silane": 'C=C[Si](C)(Cl)C1=CC=CC=C1',
- "Chloro(pentamethylcyclopentadienyl)ruthenium(II)": 'CC1=C([Ru]Cl)C(C)(C)C(C)=C1C',
- "Chloro[(tri-tert-butylphosphine)-2-(2-aminobiphenyl)]palladium(II)": 'NC1([Pd+2])=CC=CC=C1C2=CC=CC=C2.CC(P(C(C)(C)C)(Cl)C(C)(C)C)(C)C',
- "Chloro[[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene](acetanilide)palladium(II)]": 'CC(NC1=CC=CC=C1)=O.CC(C2=C(N(C=CN3C4=C(C(C)C)C=CC=C4C(C)C)C3=[Pd-]Cl)C(C(C)C)=CC=C2)C',
- "Chloro[[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene](N,N-dimethyl-3,5-dimethoxybenzylamine)palladium(II)]": 'COC1=CC(OC)=CC(CN(C)C)=C1.CC(C2=C(N(C=CN3C4=C(C(C)C)C=CC=C4C(C)C)C3=[Pd-]Cl)C(C(C)C)=CC=C2)C',
- "Chloro[[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene](N,N-dimethylbenzylamine)palladium(II)]": 'CN(C)CC1=CC=CC=C1.CC(C2=C(N(C=CN3C4=C(C(C)C)C=CC=C4C(C)C)C3=[Pd-]Cl)C(C(C)C)=CC=C2)C',
- "Chloro[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene]copper(I)": 'CC(C1=C(N(C=CN2C3=C(C(C)C)C=CC=C3C(C)C)C2=[Cu-2]Cl)C(C(C)C)=CC=C1)C',
- "Chloroacetic Acid": 'O=C(O)CCl',
- "Chlorobis(cyclooctene)iridium(I)": '[Ir]Cl.C1=C\\CCCCCC/1.C2=C\\CCCCCC/2',
- "Chlorobis(cyclooctene)rhodium(I)": '[Rh]Cl.C1=C\\CCCCCC/1.C2=C\\CCCCCC/2',
- "Chlorobis(ethylene)iridium(I)": 'Cl[Ir-4]12(CC2)CC1',
- "Chlorobis(ethylene)rhodium(I)": 'Cl[Rh-4]12(CC2)CC1',
- "Chlorobis[dicyclohexyl(phenyl)phosphino](o-tolyl)nickel(II)": 'CC1=CC=CC=C1[Ni-2](P(C2CCCCC2)(C3CCCCC3)C4=CC=CC=C4)(Cl)P(C5CCCCC5)(C6CCCCC6)C7=CC=CC=C7',
- "Chlorocholine Chloride": 'ClCC[N+](C)(C)C.[Cl-]',
- "Chlorodicyclohexylphosphine": 'ClP(C1CCCCC1)C2CCCCC2',
- "Chlorodifluoroacetic Acid": 'O=C(O)C(F)(Cl)F',
- "Chlorodiisopropylphosphine": 'CC(P(Cl)C(C)C)C',
- "Chlorodimethylvinylsilane": 'C=C[Si](C)(Cl)C',
- "Chlorodiphenylphosphine": 'ClP(C1=CC=CC=C1)C2=CC=CC=C2',
- "Chloroform": 'ClC(Cl)Cl',
- "Chloromethyldimethylphenylsilane": 'C[Si](C)(CCl)C1=CC=CC=C1',
+ '6-Methyl-2,4-heptanedione': 'CC(CC(CC(C)C)=O)=O',
+ '7-Methyl-1,5,7-triazabicyclo[4.4.0]dec-5-ene': 'CN1C2=NCCCN2CCC1',
+ '8-Ethylquinoline N-oxide': 'CCC1=CC=CC2=CC=C[N+]([O-])=C12',
+ '8-Quinolineboronic acid': 'OB(C1=C(N=CC=C2)C2=CC=C1)O',
+ '9-(2,5-Dimethylphenyl)-10-methylacridinium Perchlorate': 'C[N+]1=C2C=CC=CC2=C(C3=CC(C)=CC=C3C)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
+ '9-(2,6-Dimethylphenyl)-10-methylacridinium Perchlorate': 'C[N+]1=C2C=CC=CC2=C(C3=C(C)C=CC=C3C)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
+ '9-(2-Biphenylyl)-10-methylacridinium Perchlorate': 'C[N+]1=C2C=CC=CC2=C(C3=CC=CC=C3C4=CC=CC=C4)C5=C1C=CC=C5.O=Cl(=O)([O-])=O',
+ '9-Azajulolidine': 'N1(CCC2)CCCC3=CN=CC2=C31',
+ '9H,9H-Triacontafluoro-8,10-heptadecanedione': 'O=C(CC(C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F)=O)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F',
+ '9-Mesityl-10-methylacridinium Perchlorate': 'C[N+]1=C2C=CC=CC2=C(C3=C(C)C=C(C)C=C3C)C4=C1C=CC=C4.O=Cl(=O)([O-])=O',
+ '9-Mesityl-2,7,10-trimethylacridinium Perchlorate': 'C[N+]1=C2C=CC(C)=CC2=C(C3=C(C)C=C(C)C=C3C)C4=C1C=CC(C)=C4.O=Cl(=O)([O-])=O',
+ '9-Methyl-3,4-dihydro-2H-pyrido[1,2-a]pyrimidin-2-one': 'O=C1N=C(C(C)=CC=C2)N2CC1',
+ Acenaphthylene: 'C12=CC=CC3=C1C(C=C2)=CC=C3',
+ 'acetic acid': 'CC(O)=O',
+ 'Acetic Acid (1R,2S)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Ester': 'CC(O[C@H](C1=CC=CC=C1)[C@@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
+ 'Acetic Acid (1S,2R)-2-[N-Benzyl-N-(mesitylenesulfonyl)amino]-1-phenylpropyl Ester': 'CC(O[C@@H](C1=CC=CC=C1)[C@H](N(CC2=CC=CC=C2)S(=O)(C(C(C)=CC(C)=C3)=C3C)=O)C)=O',
+ acetone: 'CC(C)=O',
+ acetonitrile: 'CC#N',
+ Acetylacetone: 'CC(CC(C)=O)=O',
+ AlkylFluor: 'FC(N(C=C1)C2=C(C(C)C)C=CC=C2C(C)C)=[N+]1C(C(C(C)C)=CC=C3)=C3C(C)C.F[B-](F)(F)F',
+ 'Allyl(chloromethyl)dimethylsilane': 'C[Si](CCl)(CC=C)C',
+ 'Allyl(tert-butyl)dimethylsilane': 'C[Si](C(C)(C)C)(CC=C)C',
+ Allylchlorodimethylsilane: 'C[Si](Cl)(CC=C)C',
+ 'Allylmagnesium Bromide': 'Br[Mg]CC=C',
+ 'Allylmagnesium Chloride': 'Cl[Mg]CC=C',
+ Allyloxytrimethylsilane: 'C[Si](C)(OCC=C)C',
+ 'Allylpalladium(II) Chloride': '[Pd+]CC=C.[Cl-]',
+ Allyltriethoxysilane: 'CCO[Si](OCC)(CC=C)OCC',
+ Allyltriethylsilane: 'CC[Si](CC)(CC=C)CC',
+ Allyltriisopropylsilane: 'CC([Si](C(C)C)(CC=C)C(C)C)C',
+ Allyltrimethoxysilane: 'CO[Si](OC)(CC=C)OC',
+ Allyltrimethylsilane: 'C[Si](C)(CC=C)C',
+ Allyltriphenyltin: 'C=CC[Sn](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ 'Allyltris(trimethylsilyloxy)silane': 'C[Si](O[Si](O[Si](C)(C)C)(CC=C)O[Si](C)(C)C)(C)C',
+ 'aluminium bromide': '[Al+3].[Br-].[Br-].[Br-]',
+ 'Aluminium chloride': 'Cl[Al](Cl)Cl',
+ 'Aluminium hydroxide': '[OH-].[Al+3].[OH-].[OH-]',
+ 'aluminium iodide': '[Al+3].[I-].[I-].[I-]',
+ 'Aluminum Bromide Anhydrous': '[Al+3].[Br-].[Br-].[Br-]',
+ 'Aluminum Glycinate': 'NCC([O-])=O.NCC([O-])=O.NCC([O-])=O.[Al+3]',
+ 'Aluminum Isopropoxide': 'CC([O-])C.CC([O-])C.CC([O-])C.[Al+3]',
+ 'Aluminum(III) Bromide': '[Al+3].[Br-].[Br-].[Br-]',
+ 'Aluminum(III) Chloride': '[Al+3].[Cl-].[Cl-].[Cl-]',
+ 'Aminomethanesulfonic Acid': 'O=S(CN)(O)=O',
+ Ammonia: 'N',
+ 'ammonium actetate': 'CC([O-])=O.[NH4+]',
+ 'ammonium bromide': '[NH4+].[Br-]',
+ 'ammonium carbamate': 'NC([O-])=O.[NH4+]',
+ 'Ammonium Cerium(IV) Nitrate': '[O-][N+]([O-])=O.[O-][N+]([O-])=O.[O-][N+]([O-])=O.[O-][N+]([O-])=O.[O-][N+]([O-])=O.[NH4+].[Ce+4]',
+ 'ammonium chloride': '[NH4+].[Cl-]',
+ 'Ammonium dichromate': 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.[NH4+].[NH4+]',
+ 'ammonium fluoride': '[NH4+].[F-]',
+ 'ammonium formate': 'O=C[O-].[NH4+]',
+ 'ammonium hydrogensulfate': '[O-]S(=O)(O)=O.[NH4+]',
+ 'Ammonium hydroxide': '[NH4+].[OH-]',
+ 'Ammonium phosphomolybdate hydrate': 'O=[Mo](OP(O)(O)=O)([O-])=O.[H]O[H].[NH4+]',
+ 'Ammonium sulfate': 'O=S([O-])([O-])=O.[NH4+].[NH4+]',
+ 'ammonium tetrafluoroborate': 'F[B-](F)(F)F.[NH4+]',
+ ammoniumthiosulfate: 'O=S([O-])([O-])=S.[NH4+].[NH4+]',
+ 'Amyltriethylammonium Bis(trifluoromethanesulfonyl)imide': 'CCC[N+](CCC)(CCC)CCC.FC(F)(F)S([N-]S(C(F)(F)F)(=O)=O)(=O)=O',
+ 'B(CH3)3': 'CB(C)C',
+ 'B(OH)3': 'OB(O)O',
+ 'Barium hydroxide': '[Ba+2].[OH-].[OH-]',
+ 'Barium hydroxide octahydrate': '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ba+2].[OH-].[OH-]',
+ 'Barium tert-butoxide': 'CC(C)([O-])C.CC(C)([O-])C.[Ba+2]',
+ Bathophenanthroline: 'C1(C2=CC=CC=C2)=CC=NC3=C4N=CC=C(C5=CC=CC=C5)C4=CC=C13',
+ 'Bathophenanthrolinedisulfonic Acid Disodium Salt Hydrate': 'O=S(C1=NC2=C3N=CC=C(C4=CC=CC=C4)C3=CC=C2C(C5=CC=CC=C5)=C1S(=O)([O-])=O)([O-])=O.[H]O[H].[Na+].[Na+]',
+ benzene: 'C1=CC=CC=C1',
+ 'Benzeneruthenium(II) Chloride': '[Ru+2].C1=CC=CC=C1.[Cl-].[Cl-]',
+ 'Benzenesulfonic Acid Anhydrous': 'O=S(C1=CC=CC=C1)(O)=O',
+ 'Benzenesulfonic Acid Monohydrate': 'O=S(C1=CC=CC=C1)(O)=O.[H]O[H]',
+ 'Benzoic Acid': 'O=C(O)C1=CC=CC=C1',
+ 'Benzoyl peroxide': 'O=C(OOC(C1=CC=CC=C1)=O)C2=CC=CC=C2',
+ 'Benzoyl(phenyliodonio)(trifluoromethanesulfonyl)methanide': 'O=S([C-](C(C1=CC=CC=C1)=O)[I+]C2=CC=CC=C2)(C(F)(F)F)=O',
+ 'Benzylcetyldimethylammonium Chloride Hydrate': 'C[N+](CCCCCCCCCCCCCCCC)(CC1=CC=CC=C1)C.[H]O[H].[Cl-]',
+ 'Benzyldimethyltetradecylammonium Chloride Hydrate': 'CCCCCCCCCCCCCC[N+](C)(CC1=CC=CC=C1)C.[H]O[H].[Cl-]',
+ 'Benzyldodecyldimethylammonium Bromide': 'C[N+](CCCCCCCCCCCC)(CC1=CC=CC=C1)C.[Br-]',
+ 'Benzyldodecyldimethylammonium Chloride Dihydrate': 'C[N+](CCCCCCCCCCCC)(CC1=CC=CC=C1)C.[H]O[H].[H]O[H].[Cl-]',
+ 'Benzylmagnesium Bromide': 'Br[Mg]CC1=CC=CC=C1',
+ 'Benzylmagnesium Chloride': 'Cl[Mg]CC1=CC=CC=C1',
+ 'Benzyltributylammonium Bromide': 'CCCC[N+](CCCC)(CC1=CC=CC=C1)CCCC.[Br-]',
+ 'Benzyltributylammonium Chloride': 'CCCC[N+](CCCC)(CC1=CC=CC=C1)CCCC.[Cl-]',
+ 'Benzyltriethylammonium Borohydride': 'CC[N+](CC)(CC1=CC=CC=C1)CC.[BH4-]',
+ 'Benzyltriethylammonium Bromide': 'CC[N+](CC)(CC1=CC=CC=C1)CC.[Br-]',
+ 'Benzyltriethylammonium Chloride': 'CC[N+](CC)(CC1=CC=CC=C1)CC.[Cl-]',
+ 'Benzyltriethylammonium Iodide': 'CC[N+](CC)(CC1=CC=CC=C1)CC.[I-]',
+ 'Benzyltrimethylammonium Bromide': 'C[N+](C)(CC1=CC=CC=C1)C.[Br-]',
+ 'Benzyltrimethylammonium Chloride': 'C[N+](C)(CC1=CC=CC=C1)C.[Cl-]',
+ 'Benzyltrimethylammonium Dichloroiodate': 'C[N+](C)(CC1=CC=CC=C1)C.Cl[I-]Cl',
+ 'Benzyltrimethylammonium Hydroxide': 'C[N+](C)(CC1=CC=CC=C1)C.[OH-]',
+ 'Benzyltrimethylammonium Tetrachloroiodate': 'C[N+](C)(CC1=CC=CC=C1)C.Cl[I-](Cl)(Cl)Cl',
+ 'Benzyltrimethylammonium Tribromide': 'C[N+](C)(CC1=CC=CC=C1)C.[Br-].[Br-].[Br-]',
+ Benzyltrimethylsilane: 'C[Si](C)(CC1=CC=CC=C1)C',
+ BERYLLIUM: '[Be]',
+ 'BERYLLIUM HYDROXIDE': '[Be+2].[OH-].[OH-]',
+ BF3: 'FB(F)F',
+ 'Bicinchoninic Acid Disodium Salt Hydrate': 'O=C([O-])C1=C(C2=C(C([O-])=O)C3=CC=CC=C3N=C2)C=NC4=CC=CC=C14.[H]O[H].[Na+].[Na+]',
+ 'Bis(1,3-propanediamine) Copper(II) Dichloride': 'NCCCN.NCCCN.[Cu+2].[Cl-].[Cl-]',
+ 'Bis(1,5-cyclooctadiene)nickel(0)': '[Ni].C1=C\\CC/C=C\\CC/1.C2=C\\CC/C=C\\CC/2',
+ 'Bis(1,5-cyclooctadiene)rhodium(I) Tetrafluoroborate': 'F[B-](F)(F)F.[Rh+].C1=C\\CC/C=C\\CC/1.C2=C\\CC/C=C\\CC/2',
+ 'Bis(2,4,6-trimethylpyridine)bromonium Hexafluorophosphate': 'CC1=CC(C)=C([BrH+])C(C)=N1.CC2=CC(C)=CC(C)=N2.F[P-](F)(F)(F)(F)F',
+ 'Bis(2,4,6-trimethylpyridine)iodonium Hexafluorophosphate': 'CC1=CC(C)=C([IH+])C(C)=N1.CC2=CC(C)=CC(C)=N2.F[P-](F)(F)(F)(F)F',
+ 'Bis(2,4-pentanedionato)bis(2-propanolato)titanium(IV)': 'CC(/C=C(C)\\[O-])=O.CC(/C=C(C)\\[O-])=O.[O-]C(C)C.[O-]C(C)C.[Ti+4]',
+ 'Bis(2,4-pentanedionato)cobalt(II)': 'C/C([O-])=C/C(C)=O.C/C([O-])=C/C(C)=O.[Co+2].O',
+ 'Bis(2,4-pentanedionato)cobalt(II) Dihydrate': 'C/C([O-])=C/C(C)=O.C/C([O-])=C/C(C)=O.[Co+2].O.O',
+ 'Bis(2,4-pentanedionato)manganese(II) Dihydrate': 'CC(/C=C([O-])/C)=O.CC(/C=C([O-])/C)=O.[Mn+2].O.O',
+ 'Bis(2,4-pentanedionato)molybdenum(VI) Dioxide': 'CC(/C=C([O-])/C)=O.C/C([O-])=C/C(C)=O.[Mo+6].[O-2].[O-2]',
+ 'Bis(2,4-pentanedionato)nickel(II) Hydrate': 'O=C(/C=C([O-])/C)C.O=C(/C=C([O-])/C)C.[Ni+2].O',
+ 'Bis(2,4-pentanedionato)vanadium(IV) Oxide': 'CC(/C=C([O-])/C)=O.[O-]/C(C)=C\\C(C)=O.[V+4].[O-2]',
+ 'Bis(2-hydroxyethyl)dimethylammonium Chloride': 'C[N+](CCO)(CCO)C.[Cl-]',
+ 'Bis(4-bromophenyl)iodonium triflate': 'BrC1=CC=C([I+]C2=CC=C(Br)C=C2)C=C1.O=S([O-])(C(F)(F)F)=O',
+ 'Bis(4-fluorophenyl)iodonium triflate': 'FC1=CC=C([I+]C2=CC=C(F)C=C2)C=C1.O=S([O-])(C(F)(F)F)=O',
+ 'Bis(4-methoxyphenyl) Selenoxide': 'O=[Se](C1=CC=C(OC)C=C1)C2=CC=C(OC)C=C2',
+ 'Bis(4-methylphenyl)iodonium triflate': 'CC1=CC=C([I+]C2=CC=C(C)C=C2)C=C1.O=S([O-])(C(F)(F)F)=O',
+ 'Bis(4-nitrophenyl) Carbonate': 'O=C(OC1=CC=C([N+]([O-])=O)C=C1)OC2=CC=C([N+]([O-])=O)C=C2',
+ 'Bis(acetato)aqua[(S,S)-4,6-bis(4-isopropyl-2-oxazolin-2-yl)-m-xylene]rhodium': 'CC1=CC(C)=C(C2=N[C@H](CO2)C(C)C)C=C1C3=N[C@@H](C(C)C)CO3.CC([O-])=O.[O-]C(C)=O.[Rh+2].O',
+ 'Bis(acetonitrile)palladium(II) Dichloride': 'CC#N.CC#N.[Pd+2].[Cl-].[Cl-]',
+ 'Bis(benzonitrile)palladium(II) Dichloride': 'N#CC1=CC=CC=C1.N#CC2=CC=CC=C2.[Pd+2].[Cl-].[Cl-]',
+ 'Bis(chloromethyl)dimethylsilane': 'C[Si](CCl)(CCl)C',
+ 'Bis(dibenzylideneacetone)palladium(0)': 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.[Pd]',
+ 'Pd(dba)2': 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.[Pd]',
+ 'Bis(diphenylphosphino)methane': 'P(CP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ 'Bis(hexafluoroacetylacetonato)nickel(II) Hydrate': 'O=C(/C=C(C(F)(F)F)\\[O-])C(F)(F)F.[O-]/C(C(F)(F)F)=C\\C(C(F)(F)F)=O.[Ni+2]',
+ 'Bis(pentafluorophenyl) Carbonate': 'O=C(OC1=C(F)C(F)=C(F)C(F)=C1F)OC2=C(F)C(F)=C(F)C(F)=C2F',
+ 'Bis(pentafluorophenyl)dimethylsilane': 'C[Si](C1=C(F)C(F)=C(F)C(F)=C1F)(C2=C(F)C(F)=C(F)C(F)=C2F)C',
+ 'Bis(pentafluorophenyl)phenylphosphine': 'FC1=C(F)C(F)=C(F)C(F)=C1P(C2=C(F)C(F)=C(F)C(F)=C2F)C3=CC=CC=C3',
+ 'Bis(pinacolato)diboron': 'B1(OC(C(O1)(C)C)(C)C)B2OC(C(O2)(C)C)(C)C',
+ BPin: 'B1(OC(C(O1)(C)C)(C)C)B2OC(C(O2)(C)C)(C)C',
+ 'Bis(pyridine)iodonium tetrafluoroborate': '[IH+]C1=NC=CC=C1.F[B-](F)(F)F.C2=NC=CC=C2',
+ 'Bis(tert-butylcarbonyloxy)iodobenzene': 'IC1=CC=CC(OC(C(C)(C)C)=O)=C1OC(C(C)(C)C)=O',
+ 'Bis(tetrabutylammonium) Dichromate': 'CCCC[N+](CCCC)(CCCC)CCCC.CCCC[N+](CCCC)(CCCC)CCCC.O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O',
+ 'Bis(trichlorosilyl)acetylene': 'Cl[Si](C#C[Si](Cl)(Cl)Cl)(Cl)Cl',
+ 'Bis(tricyclohexylphosphine)nickel(II) Dichloride': 'P(C1CCCCC1)(C2CCCCC2)C3CCCCC3.P(C4CCCCC4)(C5CCCCC5)C6CCCCC6.[Ni+2].[Cl-].[Cl-]',
+ 'Bis(tricyclohexylphosphine)palladium(II) Dichloride': 'P(C1CCCCC1)(C2CCCCC2)C3CCCCC3.P(C4CCCCC4)(C5CCCCC5)C6CCCCC6.[Pd+2].[Cl-].[Cl-]',
+ 'Bis(trifluoro-2,4-pentanedionato)cobalt(II) Hydrate': 'C/C([O-])=C/C(C(F)(F)F)=O.C/C([O-])=C/C(C(F)(F)F)=O.[Co+2]',
+ 'Bis(trifluoromethanesulfonyl)imide': 'O=S(C(F)(F)F)(NS(=O)(C(F)(F)F)=O)=O',
+ 'Bis(trimethylsilyl) Sulfide': 'C[Si](S[Si](C)(C)C)(C)C',
+ 'Bis(trimethylsilyl)acetylene': 'C[Si](C#C[Si](C)(C)C)(C)C',
+ 'Bis(trimethylsilyl)bromomethane': 'BrC([Si](C)(C)C)[Si](C)(C)C',
+ 'Bis(trimethylsilyl)methane': 'C[Si](C[Si](C)(C)C)(C)C',
+ 'Bis(trimethylsilyl)methylamine': 'CN([Si](C)(C)C)[Si](C)(C)C',
+ 'Bis(tri-o-tolylphosphine)palladium(II) Dichloride': 'CC1=CC=CC=C1P(C2=CC=CC=C2C)C3=CC=CC=C3C.CC4=CC=CC=C4P(C5=CC=CC=C5C)C6=CC=CC=C6C.[Pd+2].[Cl-].[Cl-]',
+ 'Bis(triphenylphosphine)nickel(II) Dichloride': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.[Ni+2].[Cl-].[Cl-]',
+ 'Bis(triphenylphosphine)palladium(II) Diacetate': 'CC([O-])=O.CC([O-])=O.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.[Pd+2]',
+ 'Bis(triphenylphosphine)palladium(II) Dichloride': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.[Pd+2].[Cl-].[Cl-]',
+ 'Bis(triphenylsilyl) chromate': 'O=[Cr](O[Si](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3)(O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=O',
+ 'Bis(tri-tert-butylphosphine)palladium(0)': 'CC(P(C(C)(C)C)C(C)(C)C)(C)C.CC(P(C(C)(C)C)C(C)(C)C)(C)C.[Pd]',
+ 'Bis[1,2-bis(diphenylphosphino)ethane]palladium(0)': 'P(CCP(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.P(CCP(C5=CC=CC=C5)C6=CC=CC=C6)(C7=CC=CC=C7)C8=CC=CC=C8.[Pd]',
+ 'Bis[2-(diphenylphosphino)phenyl] Ether': 'C1(OC2=CC=CC=C2P(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1P(C5=CC=CC=C5)C6=CC=CC=C6',
+ 'Bis[2-(trimethylsilyloxy)ethyl] Ether': 'C[Si](OCCOCCO[Si](C)(C)C)(C)C',
+ 'Bis[2-carboxyethylgermanium(IV)] Sesquioxide': 'O=[Ge](CCC(O)=O)O[Ge](CCC(O)=O)=O',
+ 'Bis[3-(trimethoxysilyl)propyl]amine': 'CO[Si](CCCNCCC[Si](OC)(OC)OC)(OC)OC',
+ 'Bis[di-tert-butyl(4-dimethylaminophenyl)phosphine]palladium(0)': 'CN(C1=CC=C(P(C(C)(C)C)C(C)(C)C)C=C1)C.CN(C2=CC=C(P(C(C)(C)C)C(C)(C)C)C=C2)C.[Pd]',
+ 'Bis[tris(2,4-pentanedionato)titanium(IV)] Hexachlorotitanate(IV)': 'Cl[Ti-2](Cl)(Cl)(Cl)(Cl)Cl.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.C/C([O-])=C\\C(C)=O.[Ti+4].[Ti+4]',
+ 'BISMUTH HYDROXIDE': '[Bi+3].[OH-].[OH-].[OH-]',
+ 'Bismuth Tripotassium Dicitrate': 'OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.[Bi+5].[K+].[K+].[K+]',
+ Bistrifluoroacetamide: 'O=C(C(F)(F)F)NC(C(F)(F)F)=O',
+ 'Borane - 2-Methylpyridine Complex': 'CC1=NC=CC=C1.B',
+ 'Borane - 5-Ethyl-2-methylpyridine Complex': 'CC1=NC=C(CC)C=C1.B',
+ 'Borane - Ammonia Complex': 'B.N',
+ 'Borane - Diisopropylamine Complex': 'CC(C)NC(C)C.B',
+ 'Borane - Morpholine Complex': 'O1CCNCC1.B',
+ 'Borane - Pyridine Complex': 'C1=CN=CC=C1.B',
+ 'Borane - Tetrahydrofuran Complex': 'B.C1COCC1',
+ 'Borane - tert-Butylamine Complex': 'NC(C)(C)C.B',
+ 'Boron Trichloride': 'ClB(Cl)Cl',
+ 'Boron Trifluoride': 'FB(F)F',
+ 'Boron Trifluoride - Methanol Reagent': 'FB(F)F.CO',
+ 'Boron Trifluoride - Propanol Reagent': 'FB(F)F.CCCO',
+ Bromine: 'BrBr',
+ 'Bromine - 1,4-Dioxane Complex': 'BrBr.O1CCOCC1',
+ 'Bromo[(2,6-pyridinediyl)bis(3-methyl-1-imidazolyl-2-ylidene)]nickel Bromide': 'CN(C=CN12)C1=[Ni-3](Br)=C3N(C)C=CN3C4=CC=CC2=N4.[Br-]',
+ 'Bromo[[1,3-bis[(4S,5S)-1-benzoyl-4,5-diphenyl-2-imidazolin-2-yl]benzene]palladium(II)]': 'O=C(N1[C@@H](C2=CC=CC=C2)[C@H](C3=CC=CC=C3)N=C1C4=CC(C5=N[C@@H](C6=CC=CC=C6)[C@H](C7=CC=CC=C7)N5C(C8=CC=CC=C8)=O)=CC=C4)C9=CC=CC=C9.[Pd+]Br',
+ 'Bromoacetic Acid': 'O=C(O)CBr',
+ 'Bromocholine Bromide': 'BrCC[N+](C)(C)C.[Br-]',
+ 'Bromodicarbonyl[bis[2-(diisopropylphosphino)ethyl]amine]manganese(I)': '[C]=O.[C]=O.CC(P(CCNCCP(C(C)C)C(C)C)C(C)C)C.[Mn]Br',
+ 'Bromodimethylsulfonium Bromide': 'C[S+](Br)C.[Br-]',
+ Bromotrichloromethane: 'ClC(Cl)(Br)Cl',
+ Bromotrimethylsilane: 'Br[Si](C)(C)C',
+ 'Bromotripyrrolidinophosphonium Hexafluorophosphate': 'Br[P+](N1CCCC1)(N2CCCC2)N3CCCC3.F[P-](F)(F)(F)(F)F',
+ 'Bromotris(dimethylamino)phosphonium Hexafluorophosphate': 'CN([P+](N(C)C)(Br)N(C)C)C.F[P-](F)(F)(F)(F)F',
+ 'Butylboronic Acid': 'CCCCB(O)O',
+ Butyllithium: 'CCCC[Li]',
+ 'Butylmagnesium Bromide': 'Br[Mg]CCCC',
+ 'Butylmagnesium Chloride': 'Cl[Mg]CCCC',
+ 'Butyltin Trichloride': 'CCCC[Sn](Cl)(Cl)Cl',
+ 'Cacodylic Acid': 'O=[As](C)(C)O',
+ 'CADMIUM HYDROXIDE': '[Cd+2].[OH-].[OH-]',
+ 'CALCIUM BROMIDE HYDRATE': '[H]O[H].[Ca+2].[Br-].[Br-]',
+ 'calcium carbonate': '[O-]C([O-])=O.[Ca+2]',
+ 'calcium chloride': '[Ca+2].[Cl-].[Cl-]',
+ 'calcium hydride': '[Ca+2].[H-].[H-]',
+ 'Calcium peroxide': '[O-][O-].[Ca+2]',
+ 'calcium sulfate': 'O=S([O-])([O-])=O.[Ca+2]',
+ 'Calcium L-Threonate': 'O[C@H]([C@H](CO)O)C([O-])=O.O[C@H]([C@H](CO)O)C([O-])=O.[Ca+2]',
+ 'Carbamylcholine Chloride': 'C[N+](C)(C)CCOC(N)=O.[Cl-]',
+ 'Carbon Tetrabromide': 'BrC(Br)(Br)Br',
+ 'carbon tetrachloride': 'ClC(Cl)(Cl)Cl',
+ 'Carbon Tetraiodide': 'IC(I)(I)I',
+ 'carbon tribromide': 'BrC(Br)([H])Br',
+ 'Carbonyl(dihydrido)tris(triphenylphosphine)ruthenium(II)': '[C]=O.[H][Ru][H].P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9',
+ 'Carbonylchlorobis(triphenylphosphine)iridium(I)': '[C]=O.[Ir]Cl.P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6',
+ 'Carbonylhydridotris(triphenylphosphine)iridium(I)': '[C]=O.[Ir][H].P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9',
+ Cerium: '[Ce]',
+ 'Cerium tetrahydroxide': '[Ce+4].[OH-].[OH-].[OH-].[OH-]',
+ 'cerium trihydroxide': '[Ce+3].[OH-].[OH-].[OH-]',
+ 'Cerium(III) Acetate Hydrate': 'CC([O-])=O.CC([O-])=O.CC([O-])=O.[H]O[H].[Ce+3]',
+ 'CERIUM(III) CHLORIDE HEPTAHYDRATE': '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ce+3].[Cl-].[Cl-].[Cl-]',
+ 'Cerium(III) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Ce+3]',
+ 'Cesium Acetate': 'CC([O-])=O.[Cs+]',
+ 'cesium bromide': '[Cs+].[Br-]',
+ 'Cesium Carbonate': '[O-]C([O-])=O.[Cs+].[Cs+]',
+ 'Cesium Fluoride': '[Cs+].[F-]',
+ 'Cesium hydroxide': '[Cs+].[OH-]',
+ 'Cesium Pivalate': 'CC(C)(C)C([O-])=O.[Cs+]',
+ 'cesium sulfate': 'O=S([O-])([O-])=O.[Cs+].[Cs+]',
+ 'Chloramine B Hydrate': 'O=S([N-]Cl)(C1=CC=CC=C1)=O.O.[Na+]',
+ 'Chloramine T Trihydrate': 'CC1=CC=C(S(=O)([N-]Cl)=O)C=C1.[H]O[H].[H]O[H].[H]O[H].[Na+]',
+ Chloranil: 'O=C(C(Cl)=C1Cl)C(Cl)=C(Cl)C1=O',
+ 'Chloro(1,5-cyclooctadiene)iridium(I)': '[Ir]Cl.C1=C\\CC/C=C\\CC/1',
+ 'Chloro(1,5-cyclooctadiene)rhodium(I)': '[Rh]Cl.C1=C\\CC/C=C\\CC/1',
+ 'Chloro(1,5-hexadiene)rhodium(I)': 'C=CCCC=C.[Rh]Cl',
+ 'Chloro(2-dicyclohexylphosphino-2′,4′,6′-triisopropyl-1,1′-biphenyl)[2-(2′-amino-1,1′-biphenyl)]palladium(II)': 'Cl[Pd]1(C2=CC=CC=C2C3=CC=CC=C3N1)P(C4CCCCC4)(C5=CC=CC=C5C6=C(C(C)C)C=C(C(C)C)C=C6C(C)C)C7CCCCC7',
+ 'Chloro(3-chloropropyl)dimethylsilane': 'C[Si](CCCCl)(Cl)C',
+ 'Chloro(hexyl)dimethylsilane': 'C[Si](CCCCCC)(Cl)C',
+ 'Chloro(methyl)(phenyl)(vinyl)silane': 'C=C[Si](C)(Cl)C1=CC=CC=C1',
+ 'Chloro(pentamethylcyclopentadienyl)ruthenium(II)': 'CC1=C([Ru]Cl)C(C)(C)C(C)=C1C',
+ 'Chloro[(tri-tert-butylphosphine)-2-(2-aminobiphenyl)]palladium(II)': 'NC1([Pd+2])=CC=CC=C1C2=CC=CC=C2.CC(P(C(C)(C)C)(Cl)C(C)(C)C)(C)C',
+ 'Chloro[[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene](acetanilide)palladium(II)]': 'CC(NC1=CC=CC=C1)=O.CC(C2=C(N(C=CN3C4=C(C(C)C)C=CC=C4C(C)C)C3=[Pd-]Cl)C(C(C)C)=CC=C2)C',
+ 'Chloro[[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene](N,N-dimethyl-3,5-dimethoxybenzylamine)palladium(II)]': 'COC1=CC(OC)=CC(CN(C)C)=C1.CC(C2=C(N(C=CN3C4=C(C(C)C)C=CC=C4C(C)C)C3=[Pd-]Cl)C(C(C)C)=CC=C2)C',
+ 'Chloro[[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene](N,N-dimethylbenzylamine)palladium(II)]': 'CN(C)CC1=CC=CC=C1.CC(C2=C(N(C=CN3C4=C(C(C)C)C=CC=C4C(C)C)C3=[Pd-]Cl)C(C(C)C)=CC=C2)C',
+ 'Chloro[1,3-bis(2,6-diisopropylphenyl)imidazol-2-ylidene]copper(I)': 'CC(C1=C(N(C=CN2C3=C(C(C)C)C=CC=C3C(C)C)C2=[Cu-2]Cl)C(C(C)C)=CC=C1)C',
+ 'Chloroacetic Acid': 'O=C(O)CCl',
+ 'Chlorobis(cyclooctene)iridium(I)': '[Ir]Cl.C1=C\\CCCCCC/1.C2=C\\CCCCCC/2',
+ 'Chlorobis(cyclooctene)rhodium(I)': '[Rh]Cl.C1=C\\CCCCCC/1.C2=C\\CCCCCC/2',
+ 'Chlorobis(ethylene)iridium(I)': 'Cl[Ir-4]12(CC2)CC1',
+ 'Chlorobis(ethylene)rhodium(I)': 'Cl[Rh-4]12(CC2)CC1',
+ 'Chlorobis[dicyclohexyl(phenyl)phosphino](o-tolyl)nickel(II)': 'CC1=CC=CC=C1[Ni-2](P(C2CCCCC2)(C3CCCCC3)C4=CC=CC=C4)(Cl)P(C5CCCCC5)(C6CCCCC6)C7=CC=CC=C7',
+ 'Chlorocholine Chloride': 'ClCC[N+](C)(C)C.[Cl-]',
+ Chlorodicyclohexylphosphine: 'ClP(C1CCCCC1)C2CCCCC2',
+ 'Chlorodifluoroacetic Acid': 'O=C(O)C(F)(Cl)F',
+ Chlorodiisopropylphosphine: 'CC(P(Cl)C(C)C)C',
+ Chlorodimethylvinylsilane: 'C=C[Si](C)(Cl)C',
+ Chlorodiphenylphosphine: 'ClP(C1=CC=CC=C1)C2=CC=CC=C2',
+ Chloroform: 'ClC(Cl)Cl',
+ Chloromethyldimethylphenylsilane: 'C[Si](C)(CCl)C1=CC=CC=C1',
"Chloro-N,N,N',N'-tetramethylformamidinium Hexafluorophosphate": 'C[N+](C)=C(Cl)N(C)C.F[P-](F)(F)(F)(F)F',
"Chloronitrosyl[N,N'-bis(3,5-di-tert-butylsalicylidene)-1,1,2,2-tetramethylethylenediaminato]ruthenium(IV)": '[O-]C1=C(/C=N/C(C)(C)C(C)(C)/N=C/C2=C([O-])C(C(C)(C)C)=CC(C(C)(C)C)=C2)C=C(C(C)(C)C)C=C1C(C)(C)C.[N-]=O.[Ru+4].[Cl-]',
- "Chloropentamethyldisilane": 'C[Si](C)(C)[Si](C)(Cl)C',
- "Chlorotriethoxysilane": 'CCO[Si](OCC)(Cl)OCC',
- "Chlorotripyrrolidinophosphonium Hexafluorophosphate": 'Cl[P+](N1CCCC1)(N2CCCC2)N3CCCC3.F[P-](F)(F)(F)(F)F',
- "Choline": 'OCC[N+](C)(C)C',
- "Choline Chloride": 'OCC[N+](C)(C)C.[Cl-]',
- "Choline hydroxide": 'OCC[N+](C)(C)C.[OH-]',
- "Chromium": '[Cr]',
- "CHROMIUM (III) HYDROXIDE N-HYDRATE": '[OH-].[Cr+3].[OH-].[OH-]',
- "Chromium(VI) oxide": '[Cr+6].[O-2].[O-2].[O-2]',
- "Cinchonidine": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34',
- "Cinchonidine Dihydrochloride": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34.[H]Cl.[H]Cl',
- "Cinchonidine Sulfate Dihydrate": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34.O=S(O)(O)=O.[H]O[H].[H]O[H]',
- "Cinchonine": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34',
- "Cinchonine Hydrochloride Hydrate": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34.[H]Cl.[H]O[H]',
- "Citric Acid": 'OC(C(O)=O)(CC(O)=O)CC(O)=O',
- "Cobalt": '[Co]',
- "Cobalt hydroxide": '[Co+2].[OH-].[OH-]',
- "cobalt trihydroxide": '[Co+3].[OH-].[OH-].[OH-]',
- "Copper": '[Cu]',
- "copper (I) bromide": '[Cu+].[Br-]',
- "copper (I) chloride": '[Cu+].[Cl-]',
- "copper (II) bromide": '[Cu+2].[Br-].[Br-]',
- "copper (II) chloride": '[Cu+2].[Cl-].[Cl-]',
- "copper (II) iodide": '[Cu+2].[I-].[I-]',
- "copper fluoride": '[Cu+2].[F-].[F-]',
- "Copper sulfate": 'O=S([O-])([O-])=O.[Cu+2]',
- "Copper(I) 2-Thiophenecarboxylate": 'O=C(C1=CC=CS1)[O-].[Cu+]',
- "Copper(I) Acetate": 'CC([O-])=O.[Cu+]',
- "Copper(I) Cyanide": '[C-]#N.[Cu+]',
- "Copper(I) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.[Cu+]',
- "Copper(I) Trifluoromethanethiolate": '[S-]C(F)(F)F.[Cu+]',
- "copper(I)bromide DMS-complex": 'CSC.[Cu+].[Br-]',
- "Copper(I)iodide": '[Cu+].[I-]',
- "Copper(II) Acetate Monohydrate": 'CC([O-])=O.CC([O-])=O.[H]O[H].[Cu+2]',
- "Copper(II) Tetrafluoroborate": 'F[B-](F)(F)F.F[B-](F)(F)F.[Cu+2]',
- "Copper(II) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Cu+2]',
- "Croconic Acid": 'OC1=C(C(C(C1=O)=O)=O)O',
- "Cumene Hydroperoxide": 'CC(C1=CC=C(OO)C=C1)C',
- "Cupric hydroxide": '[Cu+2].[OH-].[OH-]',
- "Cyanomethylenetributylphosphorane": 'CCCCP(CCCC)(CCCC)=CC#N',
- "Cyanuric Chloride": 'ClC1=NC(Cl)=NC(Cl)=N1',
- "cyclohexane": 'C1CCCCC1',
- "Cyclohexyl(dimethoxy)methylsilane": 'C[Si](OC)(C1CCCCC1)OC',
- "Cyclohexylboronic Acid": 'OB(C1CCCCC1)O',
- "Cyclohexyldiphenylphosphine": 'P(C1=CC=CC=C1)(C2CCCCC2)C3=CC=CC=C3',
- "Cyclohexylmagnesium Bromide": 'Br[Mg]C1CCCCC1',
- "Cyclohexyltrimethylammonium Bis(trifluoromethanesulfonyl)imide": 'C[N+](C)(C)C1CCCCC1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "Cyclooctene": 'C1=C\\CCCCCC/1',
- "Cyclopentadienyl Thallium": '[Tl]C1=CC=CC1',
- "Cyclopentadienylbis(triphenylphosphine)ruthenium(II) Chloride": '[Ru+]C1=CC=CC1.P(C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.P(C5=CC=CC=C5)(C6=CC=CC=C6)C7=CC=CC=C7.[Cl-]',
- "Cyclopentadienyliron Dicarbonyl Dimer": '[C]=O.[C]=O.[Fe]C1=CC=CC1',
- "Cyclopentadienyltitanium(IV) Trichloride": '[Ti+3]C1=CC=CC1.[Cl-].[Cl-].[Cl-]',
- "cyclopentane": 'C1CCCC1',
- "Cyclopentylboronic Acid": 'OB(C1CCCC1)O',
- "Cyclopentylmagnesium Bromide": 'Br[Mg]C1CCCC1',
- "Cyclopentylmethylether": 'COC1CCCC1',
- "Cyclopropylmagnesium Bromide": 'Br[Mg]C1CC1',
- "D-(-)-Leucinol": 'N[C@H](CC(C)C)CO',
- "D-(+)-Threonine": 'N[C@H]([C@@H](O)C)C(O)=O',
- "D-Alanine": 'N[C@H](C)C(O)=O',
- "Decamethylcyclopentasiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Decamethyltetrasiloxane": 'C[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)C',
- "Decyltriethoxysilane": 'CCO[Si](OCC)(CCCCCCCCCC)OCC',
- "Decyltrimethoxysilane": 'CO[Si](OC)(CCCCCCCCCC)OC',
- "Decyltrimethylammonium Bromide": 'C[N+](C)(CCCCCCCCCC)C.[Br-]',
- "Decyltrimethylammonium Chloride": 'C[N+](C)(CCCCCCCCCC)C.[Cl-]',
- "Dehydroacetic Acid": 'CC(C(C(C=C(O1)C)=O)C1=O)=O',
- "Dess-Martin periodinane (DMP)": 'O=C(O1)C2=CC=CC=C2I1(OC(C)=O)(OC(C)=O)OC(C)=O',
- "Di(N-succinimidyl) Carbonate": 'O=C(ON1C(CCC1=O)=O)ON2C(CCC2=O)=O',
- "Di-1-adamantylphosphine": 'C12CC3(PC45CC6CC(C5)CC(C6)C4)CC(C2)CC(C3)C1',
- "Di-2-pyridyl Carbonate": 'O=C(OC1=NC=CC=C1)OC2=NC=CC=C2',
- "Diacetoxydimethylsilane": 'C[Si](OC(C)=O)(OC(C)=O)C',
- "Diallyldimethylammonium Chloride": 'C[N+](CC=C)(CC=C)C.[Cl-]',
- "Diallyldimethylsilane": 'C[Si](CC=C)(CC=C)C',
- "Dibenzo[a,e]cyclooctene": 'C12=CC=CC=C1/C=C\\C3=CC=CC=C3/C=C\\2',
- "Dibenzyl L-Tartrate": 'O[C@H]([C@H](C(OCC1=CC=CC=C1)=O)O)C(OCC2=CC=CC=C2)=O',
- "Dibromoisocyanuric Acid": 'O=C(N(Br)C(N1)=O)N(Br)C1=O',
- "Dibutyltin Bis(trifluoromethanesulfonate)": 'CCCC[Sn+2]CCCC.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O',
- "Dibutyltin Diacetate": 'CCCC[Sn+2]CCCC.CC([O-])=O.CC([O-])=O',
- "Dibutyltin Dichloride": 'CCCC[Sn](Cl)(Cl)CCCC',
- "Dibutyltin Dilaurate": 'CCCC[Sn+2]CCCC.CCCCCCCCCCCC([O-])=O.CCCCCCCCCCCC([O-])=O',
- "Dibutyltin Oxide": 'CCCC[Sn](CCCC)=O',
- "Dichloramine B": 'O=S(N(Cl)Cl)(C1=CC=CC=C1)=O',
- "Dichloramine T": 'CC1=CC=C(S(=O)([N-]Cl)=O)C=C1.[Na+]',
- "Dichloro(1,10-phenanthroline)copper(II)": 'Cl[Cu]Cl.C12=CC=C3C=CC=NC3=C1N=CC=C2',
- "Dichloro(diethylamino)phosphine": 'CCN(P(Cl)Cl)CC',
- "Dichloro(methyl)(3,3,3-trifluoropropyl)silane": 'FC(F)(F)CC[Si](Cl)(Cl)C',
- "Dichloro(methyl)-n-octylsilane": 'CCCCCCCC[Si](Cl)(Cl)C',
+ Chloropentamethyldisilane: 'C[Si](C)(C)[Si](C)(Cl)C',
+ Chlorotriethoxysilane: 'CCO[Si](OCC)(Cl)OCC',
+ 'Chlorotripyrrolidinophosphonium Hexafluorophosphate': 'Cl[P+](N1CCCC1)(N2CCCC2)N3CCCC3.F[P-](F)(F)(F)(F)F',
+ Choline: 'OCC[N+](C)(C)C',
+ 'Choline Chloride': 'OCC[N+](C)(C)C.[Cl-]',
+ 'Choline hydroxide': 'OCC[N+](C)(C)C.[OH-]',
+ Chromium: '[Cr]',
+ 'CHROMIUM (III) HYDROXIDE N-HYDRATE': '[OH-].[Cr+3].[OH-].[OH-]',
+ 'Chromium(VI) oxide': '[Cr+6].[O-2].[O-2].[O-2]',
+ Cinchonidine: 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34',
+ 'Cinchonidine Dihydrochloride': 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34.[H]Cl.[H]Cl',
+ 'Cinchonidine Sulfate Dihydrate': 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34.O=S(O)(O)=O.[H]O[H].[H]O[H]',
+ Cinchonine: 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34',
+ 'Cinchonine Hydrochloride Hydrate': 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=CC=C34.[H]Cl.[H]O[H]',
+ 'Citric Acid': 'OC(C(O)=O)(CC(O)=O)CC(O)=O',
+ Cobalt: '[Co]',
+ 'Cobalt hydroxide': '[Co+2].[OH-].[OH-]',
+ 'cobalt trihydroxide': '[Co+3].[OH-].[OH-].[OH-]',
+ Copper: '[Cu]',
+ 'copper (I) bromide': '[Cu+].[Br-]',
+ 'copper (I) chloride': '[Cu+].[Cl-]',
+ 'copper (II) bromide': '[Cu+2].[Br-].[Br-]',
+ 'copper (II) chloride': '[Cu+2].[Cl-].[Cl-]',
+ 'copper (II) iodide': '[Cu+2].[I-].[I-]',
+ 'copper fluoride': '[Cu+2].[F-].[F-]',
+ 'Copper sulfate': 'O=S([O-])([O-])=O.[Cu+2]',
+ 'Copper(I) 2-Thiophenecarboxylate': 'O=C(C1=CC=CS1)[O-].[Cu+]',
+ 'Copper(I) Acetate': 'CC([O-])=O.[Cu+]',
+ 'Copper(I) Cyanide': '[C-]#N.[Cu+]',
+ 'Copper(I) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.[Cu+]',
+ 'Copper(I) Trifluoromethanethiolate': '[S-]C(F)(F)F.[Cu+]',
+ 'copper(I)bromide DMS-complex': 'CSC.[Cu+].[Br-]',
+ 'Copper(I)iodide': '[Cu+].[I-]',
+ 'Copper(II) Acetate Monohydrate': 'CC([O-])=O.CC([O-])=O.[H]O[H].[Cu+2]',
+ 'Copper(II) Tetrafluoroborate': 'F[B-](F)(F)F.F[B-](F)(F)F.[Cu+2]',
+ 'Copper(II) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Cu+2]',
+ 'Croconic Acid': 'OC1=C(C(C(C1=O)=O)=O)O',
+ 'Cumene Hydroperoxide': 'CC(C1=CC=C(OO)C=C1)C',
+ 'Cupric hydroxide': '[Cu+2].[OH-].[OH-]',
+ Cyanomethylenetributylphosphorane: 'CCCCP(CCCC)(CCCC)=CC#N',
+ 'Cyanuric Chloride': 'ClC1=NC(Cl)=NC(Cl)=N1',
+ cyclohexane: 'C1CCCCC1',
+ 'Cyclohexyl(dimethoxy)methylsilane': 'C[Si](OC)(C1CCCCC1)OC',
+ 'Cyclohexylboronic Acid': 'OB(C1CCCCC1)O',
+ Cyclohexyldiphenylphosphine: 'P(C1=CC=CC=C1)(C2CCCCC2)C3=CC=CC=C3',
+ 'Cyclohexylmagnesium Bromide': 'Br[Mg]C1CCCCC1',
+ 'Cyclohexyltrimethylammonium Bis(trifluoromethanesulfonyl)imide': 'C[N+](C)(C)C1CCCCC1.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ Cyclooctene: 'C1=C\\CCCCCC/1',
+ 'Cyclopentadienyl Thallium': '[Tl]C1=CC=CC1',
+ 'Cyclopentadienylbis(triphenylphosphine)ruthenium(II) Chloride': '[Ru+]C1=CC=CC1.P(C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4.P(C5=CC=CC=C5)(C6=CC=CC=C6)C7=CC=CC=C7.[Cl-]',
+ 'Cyclopentadienyliron Dicarbonyl Dimer': '[C]=O.[C]=O.[Fe]C1=CC=CC1',
+ 'Cyclopentadienyltitanium(IV) Trichloride': '[Ti+3]C1=CC=CC1.[Cl-].[Cl-].[Cl-]',
+ cyclopentane: 'C1CCCC1',
+ 'Cyclopentylboronic Acid': 'OB(C1CCCC1)O',
+ 'Cyclopentylmagnesium Bromide': 'Br[Mg]C1CCCC1',
+ Cyclopentylmethylether: 'COC1CCCC1',
+ 'Cyclopropylmagnesium Bromide': 'Br[Mg]C1CC1',
+ 'D-(-)-Leucinol': 'N[C@H](CC(C)C)CO',
+ 'D-(+)-Threonine': 'N[C@H]([C@@H](O)C)C(O)=O',
+ 'D-Alanine': 'N[C@H](C)C(O)=O',
+ Decamethylcyclopentasiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
+ Decamethyltetrasiloxane: 'C[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)C',
+ Decyltriethoxysilane: 'CCO[Si](OCC)(CCCCCCCCCC)OCC',
+ Decyltrimethoxysilane: 'CO[Si](OC)(CCCCCCCCCC)OC',
+ 'Decyltrimethylammonium Bromide': 'C[N+](C)(CCCCCCCCCC)C.[Br-]',
+ 'Decyltrimethylammonium Chloride': 'C[N+](C)(CCCCCCCCCC)C.[Cl-]',
+ 'Dehydroacetic Acid': 'CC(C(C(C=C(O1)C)=O)C1=O)=O',
+ 'Dess-Martin periodinane (DMP)': 'O=C(O1)C2=CC=CC=C2I1(OC(C)=O)(OC(C)=O)OC(C)=O',
+ 'Di(N-succinimidyl) Carbonate': 'O=C(ON1C(CCC1=O)=O)ON2C(CCC2=O)=O',
+ 'Di-1-adamantylphosphine': 'C12CC3(PC45CC6CC(C5)CC(C6)C4)CC(C2)CC(C3)C1',
+ 'Di-2-pyridyl Carbonate': 'O=C(OC1=NC=CC=C1)OC2=NC=CC=C2',
+ Diacetoxydimethylsilane: 'C[Si](OC(C)=O)(OC(C)=O)C',
+ 'Diallyldimethylammonium Chloride': 'C[N+](CC=C)(CC=C)C.[Cl-]',
+ Diallyldimethylsilane: 'C[Si](CC=C)(CC=C)C',
+ 'Dibenzo[a,e]cyclooctene': 'C12=CC=CC=C1/C=C\\C3=CC=CC=C3/C=C\\2',
+ 'Dibenzyl L-Tartrate': 'O[C@H]([C@H](C(OCC1=CC=CC=C1)=O)O)C(OCC2=CC=CC=C2)=O',
+ 'Dibromoisocyanuric Acid': 'O=C(N(Br)C(N1)=O)N(Br)C1=O',
+ 'Dibutyltin Bis(trifluoromethanesulfonate)': 'CCCC[Sn+2]CCCC.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O',
+ 'Dibutyltin Diacetate': 'CCCC[Sn+2]CCCC.CC([O-])=O.CC([O-])=O',
+ 'Dibutyltin Dichloride': 'CCCC[Sn](Cl)(Cl)CCCC',
+ 'Dibutyltin Dilaurate': 'CCCC[Sn+2]CCCC.CCCCCCCCCCCC([O-])=O.CCCCCCCCCCCC([O-])=O',
+ 'Dibutyltin Oxide': 'CCCC[Sn](CCCC)=O',
+ 'Dichloramine B': 'O=S(N(Cl)Cl)(C1=CC=CC=C1)=O',
+ 'Dichloramine T': 'CC1=CC=C(S(=O)([N-]Cl)=O)C=C1.[Na+]',
+ 'Dichloro(1,10-phenanthroline)copper(II)': 'Cl[Cu]Cl.C12=CC=C3C=CC=NC3=C1N=CC=C2',
+ 'Dichloro(diethylamino)phosphine': 'CCN(P(Cl)Cl)CC',
+ 'Dichloro(methyl)(3,3,3-trifluoropropyl)silane': 'FC(F)(F)CC[Si](Cl)(Cl)C',
+ 'Dichloro(methyl)-n-octylsilane': 'CCCCCCCC[Si](Cl)(Cl)C',
"Dichloro(N,N,N',N'-tetramethylethylenediamine)zinc(II)": 'CN(C)CCN(C)C.Cl[Zn]Cl',
- "Dichloro(p-cymene)ruthenium(II)": 'CC1=CC=C(C(C)C)C=C1.Cl[Ru]Cl',
- "Dichloro[9,9-dimethyl-4,5-bis(diphenylphosphino)xanthene]palladium(II)": 'CC1(C)C2=C(OC3=C1C=CC=C3P(C4=CC=CC=C4)C5=CC=CC=C5)C(P(C6=CC=CC=C6)C7=CC=CC=C7)=CC=C2.Cl[Pd]Cl',
- "Dichloroacetic Acid": 'O=C(O)C(Cl)Cl',
- "Dichlorocyclohexylmethylsilane": 'C[Si](Cl)(Cl)C1CCCCC1',
- "Dichlorodecylmethylsilane": 'C[Si](Cl)(Cl)CCCCCCCCCC',
- "Dichlorododecylmethylsilane": 'C[Si](Cl)(Cl)CCCCCCCCCCCC',
- "Dichlorohexylmethylsilane": 'C[Si](Cl)(Cl)CCCCCC',
- "dichloromethane": 'ClCCl',
- "Dichloromethylvinylsilane": 'C=C[Si](Cl)(Cl)C',
- "Dichlorophenylphosphine": 'ClP(Cl)C1=CC=CC=C1',
- "Dichlorotitanium Diisopropoxide": 'Cl[Ti+2]Cl.CC([O-])C.CC([O-])C',
- "Dicobalt Octacarbonyl": '[CH-]=O.[CH-]=O.[C-]#[O+].[C-]#[O+].[C-]#[O+].[C-]#[O+].[C-]#[O+].[C-]#[O+].[Co].[Co+2]',
- "Dicumyl peroxide": 'CC(OOC(C)(C1=CC=CC=C1)C)(C2=CC=CC=C2)C',
- "Dicyclohexyl(2,4,6-triisopropylphenyl)phosphine": 'CC(C1=C(P(C2CCCCC2)C3CCCCC3)C(C(C)C)=CC(C(C)C)=C1)C',
- "Dicyclohexyl(trifluoromethanesulfonyloxy)borane": 'O=S(OB(C1CCCCC1)C2CCCCC2)(C(F)(F)F)=O',
- "Dicyclohexylamine Borane": 'C1(NC2CCCCC2)CCCCC1.B',
- "Dicyclohexylphenylphosphine": 'P(C1CCCCC1)(C2CCCCC2)C3=CC=CC=C3',
- "Dicyclopentadiene": 'C12C=CCC1C3C=CC2C3',
- "Dicyclopentyl(dimethoxy)silane": 'CO[Si](C1CCCC1)(C2CCCC2)OC',
- "Didecyldimethylammonium Bromide": 'C[N+](CCCCCCCCCC)(CCCCCCCCCC)C.[Br-]',
- "Didodecyldimethylammonium Chloride": 'C[N+](CCCCCCCCCCCC)(CCCCCCCCCCCC)C.[Cl-]',
- "Diethoxy(methyl)phenylsilane": 'C[Si](OCC)(OCC)C1=CC=CC=C1',
- "Diethoxydimethylsilane": 'C[Si](OCC)(OCC)C',
- "Diethoxydiphenylsilane": 'CCO[Si](C1=CC=CC=C1)(OCC)C2=CC=CC=C2',
- "Diethoxymethylsilane": 'C[SiH](OCC)OCC',
- "Diethoxymethylvinylsilane": 'C=C[Si](OCC)(OCC)C',
- "Diethyl (Bromodifluoromethyl)phosphonate": 'FC(Br)(P(OCC)(OCC)=O)F',
- "Diethyl 1,4-Dihydro-2,6-dimethyl-3,5-pyridinedicarboxylate": 'O=C(C1=C(C)NC(C)=C(C(OCC)=O)C1)OCC',
+ 'Dichloro(p-cymene)ruthenium(II)': 'CC1=CC=C(C(C)C)C=C1.Cl[Ru]Cl',
+ 'Dichloro[9,9-dimethyl-4,5-bis(diphenylphosphino)xanthene]palladium(II)': 'CC1(C)C2=C(OC3=C1C=CC=C3P(C4=CC=CC=C4)C5=CC=CC=C5)C(P(C6=CC=CC=C6)C7=CC=CC=C7)=CC=C2.Cl[Pd]Cl',
+ 'Dichloroacetic Acid': 'O=C(O)C(Cl)Cl',
+ Dichlorocyclohexylmethylsilane: 'C[Si](Cl)(Cl)C1CCCCC1',
+ Dichlorodecylmethylsilane: 'C[Si](Cl)(Cl)CCCCCCCCCC',
+ Dichlorododecylmethylsilane: 'C[Si](Cl)(Cl)CCCCCCCCCCCC',
+ Dichlorohexylmethylsilane: 'C[Si](Cl)(Cl)CCCCCC',
+ dichloromethane: 'ClCCl',
+ Dichloromethylvinylsilane: 'C=C[Si](Cl)(Cl)C',
+ Dichlorophenylphosphine: 'ClP(Cl)C1=CC=CC=C1',
+ 'Dichlorotitanium Diisopropoxide': 'Cl[Ti+2]Cl.CC([O-])C.CC([O-])C',
+ 'Dicobalt Octacarbonyl': '[CH-]=O.[CH-]=O.[C-]#[O+].[C-]#[O+].[C-]#[O+].[C-]#[O+].[C-]#[O+].[C-]#[O+].[Co].[Co+2]',
+ 'Dicumyl peroxide': 'CC(OOC(C)(C1=CC=CC=C1)C)(C2=CC=CC=C2)C',
+ 'Dicyclohexyl(2,4,6-triisopropylphenyl)phosphine': 'CC(C1=C(P(C2CCCCC2)C3CCCCC3)C(C(C)C)=CC(C(C)C)=C1)C',
+ 'Dicyclohexyl(trifluoromethanesulfonyloxy)borane': 'O=S(OB(C1CCCCC1)C2CCCCC2)(C(F)(F)F)=O',
+ 'Dicyclohexylamine Borane': 'C1(NC2CCCCC2)CCCCC1.B',
+ Dicyclohexylphenylphosphine: 'P(C1CCCCC1)(C2CCCCC2)C3=CC=CC=C3',
+ Dicyclopentadiene: 'C12C=CCC1C3C=CC2C3',
+ 'Dicyclopentyl(dimethoxy)silane': 'CO[Si](C1CCCC1)(C2CCCC2)OC',
+ 'Didecyldimethylammonium Bromide': 'C[N+](CCCCCCCCCC)(CCCCCCCCCC)C.[Br-]',
+ 'Didodecyldimethylammonium Chloride': 'C[N+](CCCCCCCCCCCC)(CCCCCCCCCCCC)C.[Cl-]',
+ 'Diethoxy(methyl)phenylsilane': 'C[Si](OCC)(OCC)C1=CC=CC=C1',
+ Diethoxydimethylsilane: 'C[Si](OCC)(OCC)C',
+ Diethoxydiphenylsilane: 'CCO[Si](C1=CC=CC=C1)(OCC)C2=CC=CC=C2',
+ Diethoxymethylsilane: 'C[SiH](OCC)OCC',
+ Diethoxymethylvinylsilane: 'C=C[Si](OCC)(OCC)C',
+ 'Diethyl (Bromodifluoromethyl)phosphonate': 'FC(Br)(P(OCC)(OCC)=O)F',
+ 'Diethyl 1,4-Dihydro-2,6-dimethyl-3,5-pyridinedicarboxylate': 'O=C(C1=C(C)NC(C)=C(C(OCC)=O)C1)OCC',
"Diethyl 2,2':6',2''-Terpyridine-4'-phosphonate": 'O=P(C1=CC(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=C1)(OCC)OCC',
- "Diethyl Cyanophosphonate": 'N#CP(OCC)(OCC)=O',
- "diethyl ether": 'CCOCC',
- "Et2O": 'CCOCC',
- "Diethyl D-(-)-Tartrate": 'O[C@@H]([C@@H](C(OCC)=O)O)C(OCC)=O',
- "Diethyl L-(+)-Tartrate": 'O[C@H]([C@H](C(OCC)=O)O)C(OCC)=O',
- "Diethyl(2-methoxyethyl)methylammonium Bis(fluorosulfonyl)imide": 'FC(F)(F)S(=O)([N-]S(=O)(C(F)(F)F)=O)=O.C[N+](CC)(CC)CCOC',
- "Diethyl(isopropyl)silanol": 'O[Si](CC)(CC)C(C)C',
- "Diethylamine": 'CCNCC',
- "NEt2": 'CCNCC',
- "Diethyldimethylammonium hydroxide": 'C[N+](CC)(CC)C.[OH-]',
- "Diethylenetriamine": 'NCCNCCN',
- "Diethylphenylphosphine": 'CCP(CC)C1=CC=CC=C1',
- "Difluoroacetic Acid": 'O=C(O)C(F)F',
- "Difluoroacetic Anhydride": 'O=C(OC(C(F)F)=O)C(F)F',
- "Difluoromethyl 2-Pyridyl Sulfone": 'O=S(C1=NC=CC=C1)(C(F)F)=O',
- "Difluoromethyl Phenyl Sulfide": 'FC(SC1=CC=CC=C1)F',
- "Difluoromethyl Phenyl Sulfone": 'O=S(C1=CC=CC=C1)(C(F)F)=O',
- "Dihydrogen hexahydroxyplatinate": 'O[Pt-2](O)(O)(O)(O)O.[H+].[H+]',
- "Diisobutyldimethoxysilane": 'CO[Si](CC(C)C)(CC(C)C)OC',
- "Diisopropyl D-(-)-Tartrate": 'O[C@@H]([C@@H](C(OC(C)C)=O)O)C(OC(C)C)=O',
- "Diisopropyl L-(+)-Tartrate": 'O[C@H]([C@H](C(OC(C)C)=O)O)C(OC(C)C)=O',
- "Diisopropylamine": 'CC(NC(C)C)C',
- "DIPA": 'CC(NC(C)C)C',
- "Dilauryldimethylammonium Bromide": 'C[N+](CCCCCCCCCCCC)(CCCCCCCCCCCC)C.[Br-]',
- "Dilithium Tetrachlorocopper(II)": 'Cl[Cu-](Cl)(Cl)Cl.Cl[Cu-](Cl)(Cl)Cl.[Li+].[Li+]',
- "Dimesitylammonium Pentafluorobenzenesulfonate": 'CC1=CC(C)=CC(C)=C1[NH2+]C2=C(C)C=C(C)C=C2C.O=S(C3=C(F)C(F)=C(F)C(F)=C3F)([O-])=O',
- "Dimesitylfluoroborane": 'CC1=CC(C)=CC(C)=C1B(F)C2=C(C)C=C(C)C=C2C',
- "Dimethoxy(methyl)(3,3,3-trifluoropropyl)silane": 'FC(F)(F)CC[Si](OC)(OC)C',
- "Dimethoxy(methyl)silane": 'C[SiH](OC)OC',
- "Dimethoxydimethylsilane": 'C[Si](OC)(OC)C',
- "Dimethoxydiphenylsilane": 'CO[Si](C1=CC=CC=C1)(OC)C2=CC=CC=C2',
- "Dimethoxydi-p-tolylsilane": 'CC1=CC=C([Si](OC)(OC)C2=CC=C(C)C=C2)C=C1',
- "Dimethoxymethylvinylsilane": 'C=C[Si](OC)(OC)C',
+ 'Diethyl Cyanophosphonate': 'N#CP(OCC)(OCC)=O',
+ 'diethyl ether': 'CCOCC',
+ Et2O: 'CCOCC',
+ 'Diethyl D-(-)-Tartrate': 'O[C@@H]([C@@H](C(OCC)=O)O)C(OCC)=O',
+ 'Diethyl L-(+)-Tartrate': 'O[C@H]([C@H](C(OCC)=O)O)C(OCC)=O',
+ 'Diethyl(2-methoxyethyl)methylammonium Bis(fluorosulfonyl)imide': 'FC(F)(F)S(=O)([N-]S(=O)(C(F)(F)F)=O)=O.C[N+](CC)(CC)CCOC',
+ 'Diethyl(isopropyl)silanol': 'O[Si](CC)(CC)C(C)C',
+ Diethylamine: 'CCNCC',
+ NEt2: 'CCNCC',
+ 'Diethyldimethylammonium hydroxide': 'C[N+](CC)(CC)C.[OH-]',
+ Diethylenetriamine: 'NCCNCCN',
+ Diethylphenylphosphine: 'CCP(CC)C1=CC=CC=C1',
+ 'Difluoroacetic Acid': 'O=C(O)C(F)F',
+ 'Difluoroacetic Anhydride': 'O=C(OC(C(F)F)=O)C(F)F',
+ 'Difluoromethyl 2-Pyridyl Sulfone': 'O=S(C1=NC=CC=C1)(C(F)F)=O',
+ 'Difluoromethyl Phenyl Sulfide': 'FC(SC1=CC=CC=C1)F',
+ 'Difluoromethyl Phenyl Sulfone': 'O=S(C1=CC=CC=C1)(C(F)F)=O',
+ 'Dihydrogen hexahydroxyplatinate': 'O[Pt-2](O)(O)(O)(O)O.[H+].[H+]',
+ Diisobutyldimethoxysilane: 'CO[Si](CC(C)C)(CC(C)C)OC',
+ 'Diisopropyl D-(-)-Tartrate': 'O[C@@H]([C@@H](C(OC(C)C)=O)O)C(OC(C)C)=O',
+ 'Diisopropyl L-(+)-Tartrate': 'O[C@H]([C@H](C(OC(C)C)=O)O)C(OC(C)C)=O',
+ Diisopropylamine: 'CC(NC(C)C)C',
+ DIPA: 'CC(NC(C)C)C',
+ 'Dilauryldimethylammonium Bromide': 'C[N+](CCCCCCCCCCCC)(CCCCCCCCCCCC)C.[Br-]',
+ 'Dilithium Tetrachlorocopper(II)': 'Cl[Cu-](Cl)(Cl)Cl.Cl[Cu-](Cl)(Cl)Cl.[Li+].[Li+]',
+ 'Dimesitylammonium Pentafluorobenzenesulfonate': 'CC1=CC(C)=CC(C)=C1[NH2+]C2=C(C)C=C(C)C=C2C.O=S(C3=C(F)C(F)=C(F)C(F)=C3F)([O-])=O',
+ Dimesitylfluoroborane: 'CC1=CC(C)=CC(C)=C1B(F)C2=C(C)C=C(C)C=C2C',
+ 'Dimethoxy(methyl)(3,3,3-trifluoropropyl)silane': 'FC(F)(F)CC[Si](OC)(OC)C',
+ 'Dimethoxy(methyl)silane': 'C[SiH](OC)OC',
+ Dimethoxydimethylsilane: 'C[Si](OC)(OC)C',
+ Dimethoxydiphenylsilane: 'CO[Si](C1=CC=CC=C1)(OC)C2=CC=CC=C2',
+ 'Dimethoxydi-p-tolylsilane': 'CC1=CC=C([Si](OC)(OC)C2=CC=C(C)C=C2)C=C1',
+ Dimethoxymethylvinylsilane: 'C=C[Si](OC)(OC)C',
"Dimethyl 2,2'-Bipyridine-4,4'-dicarboxylate": 'O=C(C1=CC(C2=NC=CC(C(OC)=O)=C2)=NC=C1)OC',
"Dimethyl 2,2'-Bipyridine-6,6'-dicarboxylate": 'O=C(C1=CC=CC(C2=NC(C(OC)=O)=CC=C2)=N1)OC',
- "Dimethyl Sulfide Borane": 'CSC.B',
- "Dimethyl D-(-)-Tartrate": 'O[C@@H]([C@@H](C(OC)=O)O)C(OC)=O',
- "Dimethyl L-(+)-Tartrate": 'O[C@H]([C@H](C(OC)=O)O)C(OC)=O',
- "Dimethylamin": 'CNC',
- "NMe2": 'CNC',
- "Dimethylamine Borane": 'CNC.B',
- "Dimethylbis(phenylethynyl)silane": 'C[Si](C#CC1=CC=CC=C1)(C)C#CC2=CC=CC=C2',
- "Dimethyldimyristylammonium Bromide": 'CCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCC.[Br-]',
- "Dimethyldioctadecylammonium Bromide": 'CCCCCCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCCCCCC.[Br-]',
- "Dimethyldioctadecylammonium Iodide": 'CCCCCCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCCCCCC.[I-]',
- "Dimethyldioctylammonium Bromide": 'CCCCCCCC[N+](C)(C)CCCCCCCC.[Br-]',
- "Dimethyldipalmitylammonium Bromide": 'CCCCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCCCC.[Br-]',
- "Dimethyldiphenylsilane": 'C[Si](C1=CC=CC=C1)(C)C2=CC=CC=C2',
- "Dimethyldivinylsilane": 'C=C[Si](C)(C)C=C',
- "Dimethylformamide": 'CN(C)C=O',
- "DMF": 'CN(C)C=O',
- "Dimethylphenylphosphine Borane": 'CP(C)C1=CC=CC=C1.B',
- "Dimethylphenylsilane": 'C[SiH](C)C1=CC=CC=C1',
- "Dimethylthiophosphinoyl Chloride": 'ClP(C)(C)=S',
- "Dimethyltin Dichloride": 'C[Sn](Cl)(Cl)C',
- "Dimethyltin Oxide": 'C[Sn](C)=O',
- "Dimethyltitanocene": 'C[Ti]C.c1cccc1.c2cccc2',
- "Di-n-octyltin Oxide": 'CCCCCCCC[Sn](CCCCCCCC)=O',
- "Diphenyl-2-pyridylphosphine": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=NC=CC=C3',
- "Diphenylammonium Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.C1([NH2+]C2=CC=CC=C2)=CC=CC=C1',
- "Diphenylbis(phenylethynyl)silane": 'C1(C#C[Si](C2=CC=CC=C2)(C3=CC=CC=C3)C#CC4=CC=CC=C4)=CC=CC=C1',
- "Diphenyldichlorogermane": 'Cl[Ge](C1=CC=CC=C1)(C2=CC=CC=C2)Cl',
- "Diphenyliodonium chloride": 'C1([I+]C2=CC=CC=C2)=CC=CC=C1.[Cl-]',
- "Diphenylphosphine Oxide": 'O=P(C1=CC=CC=C1)C2=CC=CC=C2',
- "Diphenylphosphinic Chloride": 'O=P(C1=CC=CC=C1)(C2=CC=CC=C2)Cl',
- "Diphenylphosphoryl Azide": 'O=P(C1=CC=CC=C1)(N=[N+]=[N-])C2=CC=CC=C2',
- "Diphenylpropylphosphine": 'CCCP(C1=CC=CC=C1)C2=CC=CC=C2',
- "Diphenylsilane": 'C1([SiH2]C2=CC=CC=C2)=CC=CC=C1',
- "Diphenylsilanediol": 'O[Si](C1=CC=CC=C1)(C2=CC=CC=C2)O',
- "Diphosphoryl Chloride": 'O=P(OP(O)(O)=O)(Cl)O',
- "Dipivaloylmethane": 'CC(C)(C)C(CC(C(C)(C)C)=O)=O',
+ 'Dimethyl Sulfide Borane': 'CSC.B',
+ 'Dimethyl D-(-)-Tartrate': 'O[C@@H]([C@@H](C(OC)=O)O)C(OC)=O',
+ 'Dimethyl L-(+)-Tartrate': 'O[C@H]([C@H](C(OC)=O)O)C(OC)=O',
+ Dimethylamin: 'CNC',
+ NMe2: 'CNC',
+ 'Dimethylamine Borane': 'CNC.B',
+ 'Dimethylbis(phenylethynyl)silane': 'C[Si](C#CC1=CC=CC=C1)(C)C#CC2=CC=CC=C2',
+ 'Dimethyldimyristylammonium Bromide': 'CCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCC.[Br-]',
+ 'Dimethyldioctadecylammonium Bromide': 'CCCCCCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCCCCCC.[Br-]',
+ 'Dimethyldioctadecylammonium Iodide': 'CCCCCCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCCCCCC.[I-]',
+ 'Dimethyldioctylammonium Bromide': 'CCCCCCCC[N+](C)(C)CCCCCCCC.[Br-]',
+ 'Dimethyldipalmitylammonium Bromide': 'CCCCCCCCCCCCCCCC[N+](C)(C)CCCCCCCCCCCCCCCC.[Br-]',
+ Dimethyldiphenylsilane: 'C[Si](C1=CC=CC=C1)(C)C2=CC=CC=C2',
+ Dimethyldivinylsilane: 'C=C[Si](C)(C)C=C',
+ Dimethylformamide: 'CN(C)C=O',
+ DMF: 'CN(C)C=O',
+ 'Dimethylphenylphosphine Borane': 'CP(C)C1=CC=CC=C1.B',
+ Dimethylphenylsilane: 'C[SiH](C)C1=CC=CC=C1',
+ 'Dimethylthiophosphinoyl Chloride': 'ClP(C)(C)=S',
+ 'Dimethyltin Dichloride': 'C[Sn](Cl)(Cl)C',
+ 'Dimethyltin Oxide': 'C[Sn](C)=O',
+ Dimethyltitanocene: 'C[Ti]C.c1cccc1.c2cccc2',
+ 'Di-n-octyltin Oxide': 'CCCCCCCC[Sn](CCCCCCCC)=O',
+ 'Diphenyl-2-pyridylphosphine': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=NC=CC=C3',
+ 'Diphenylammonium Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.C1([NH2+]C2=CC=CC=C2)=CC=CC=C1',
+ 'Diphenylbis(phenylethynyl)silane': 'C1(C#C[Si](C2=CC=CC=C2)(C3=CC=CC=C3)C#CC4=CC=CC=C4)=CC=CC=C1',
+ Diphenyldichlorogermane: 'Cl[Ge](C1=CC=CC=C1)(C2=CC=CC=C2)Cl',
+ 'Diphenyliodonium chloride': 'C1([I+]C2=CC=CC=C2)=CC=CC=C1.[Cl-]',
+ 'Diphenylphosphine Oxide': 'O=P(C1=CC=CC=C1)C2=CC=CC=C2',
+ 'Diphenylphosphinic Chloride': 'O=P(C1=CC=CC=C1)(C2=CC=CC=C2)Cl',
+ 'Diphenylphosphoryl Azide': 'O=P(C1=CC=CC=C1)(N=[N+]=[N-])C2=CC=CC=C2',
+ Diphenylpropylphosphine: 'CCCP(C1=CC=CC=C1)C2=CC=CC=C2',
+ Diphenylsilane: 'C1([SiH2]C2=CC=CC=C2)=CC=CC=C1',
+ Diphenylsilanediol: 'O[Si](C1=CC=CC=C1)(C2=CC=CC=C2)O',
+ 'Diphosphoryl Chloride': 'O=P(OP(O)(O)=O)(Cl)O',
+ Dipivaloylmethane: 'CC(C)(C)C(CC(C(C)(C)C)=O)=O',
"Dipotassium (R)-1,1'-Binaphthyl-2,2'-disulfonate": 'O=S(C1=CC=C2C=CC=CC2=C1C3=C4C=CC=CC4=CC=C3S(=O)([O-])=O)([O-])=O.[K+].[K+]',
"Dipyrido[3,2-a:2',3'-c]phenazine": 'C12=CC=CN=C1C3=NC=CC=C3C4=NC5=CC=CC=C5N=C42',
- "Di-sec-butylmagnesium - Lithium Chloride": 'CCC([Mg]C(C)CC)C.[Li+].[Cl-]',
- "Di-tert-butyl 1,4-Dihydro-2,6-dimethyl-3,5-pyridinedicarboxylate": 'O=C(C1=C(C)NC(C)=C(C(OC(C)(C)C)=O)C1)OC(C)(C)C',
- "Di-tert-butyl Peroxide": 'CC(OOC(C)(C)C)(C)C',
- "DTBP": 'CC(OOC(C)(C)C)(C)C',
- "Di-tert-butyl L-(+)-Tartrate": 'O[C@H]([C@H](C(OC(C)(C)C)=O)O)C(OC(C)(C)C)=O',
- "Di-tert-butylchlorophosphine": 'ClP(C(C)(C)C)C(C)(C)C',
- "Di-tert-butylmethylphosphonium Tetraphenylborate": 'C[PH+](C(C)(C)C)C(C)(C)C.C1([B-](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
- "Di-tert-butylphenylphosphine": 'CC(P(C(C)(C)C)C1=CC=CC=C1)(C)C',
- "Di-tert-Butylsilane": 'CC([SiH2]C(C)(C)C)(C)C',
- "DL-Dithiothreitol": 'SC[C@H]([C@@H](CO)O)S',
- "DL-Lactic Acid": 'OC(C)C(O)=O',
- "DL-Malic Acid": 'OC(CC(O)=O)C(O)=O',
- "DL-α-Lipoic Acid": 'O=C(CCCCC1SSCC1)O',
- "D-Methionine": 'N[C@H](CCSC)C(O)=O',
- "DMSO": 'CS(C)=O',
- "Dodecamethylcyclohexasiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Dodecamethylpentasiloxane": 'C[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)C',
- "Dodecyltriethoxysilane": 'CCO[Si](OCC)(CCCCCCCCCCCC)OCC',
- "Dodecyltrimethoxysilane": 'CO[Si](OC)(CCCCCCCCCCCC)OC',
- "Dodecyltrimethylammonium Bromide": 'C[N+](C)(CCCCCCCCCCCC)C.[Br-]',
- "Dodecyltrimethylammonium Chloride": 'C[N+](C)(CCCCCCCCCCCC)C.[Cl-]',
- "D-Phenylalanine": 'N[C@H](CC1=CC=CC=C1)C(O)=O',
- "D-Pipecolic Acid": 'O=C(O)C1CCCCN1',
- "D-Proline": 'O=C(O)[C@@H]1NCCC1',
- "D-Tryptophan": 'N[C@H](CC1=CNC2=C1C=CC=C2)C(O)=O',
- "ethanol": 'OCC',
- "EtOH": 'OCC',
- "Ethoxydiphenylphosphine": 'CCOP(C1=CC=CC=C1)C2=CC=CC=C2',
- "Ethoxytriethylsilane": 'CC[Si](CC)(OCC)CC',
+ 'Di-sec-butylmagnesium - Lithium Chloride': 'CCC([Mg]C(C)CC)C.[Li+].[Cl-]',
+ 'Di-tert-butyl 1,4-Dihydro-2,6-dimethyl-3,5-pyridinedicarboxylate': 'O=C(C1=C(C)NC(C)=C(C(OC(C)(C)C)=O)C1)OC(C)(C)C',
+ 'Di-tert-butyl Peroxide': 'CC(OOC(C)(C)C)(C)C',
+ DTBP: 'CC(OOC(C)(C)C)(C)C',
+ 'Di-tert-butyl L-(+)-Tartrate': 'O[C@H]([C@H](C(OC(C)(C)C)=O)O)C(OC(C)(C)C)=O',
+ 'Di-tert-butylchlorophosphine': 'ClP(C(C)(C)C)C(C)(C)C',
+ 'Di-tert-butylmethylphosphonium Tetraphenylborate': 'C[PH+](C(C)(C)C)C(C)(C)C.C1([B-](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
+ 'Di-tert-butylphenylphosphine': 'CC(P(C(C)(C)C)C1=CC=CC=C1)(C)C',
+ 'Di-tert-Butylsilane': 'CC([SiH2]C(C)(C)C)(C)C',
+ 'DL-Dithiothreitol': 'SC[C@H]([C@@H](CO)O)S',
+ 'DL-Lactic Acid': 'OC(C)C(O)=O',
+ 'DL-Malic Acid': 'OC(CC(O)=O)C(O)=O',
+ 'DL-α-Lipoic Acid': 'O=C(CCCCC1SSCC1)O',
+ 'D-Methionine': 'N[C@H](CCSC)C(O)=O',
+ DMSO: 'CS(C)=O',
+ Dodecamethylcyclohexasiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
+ Dodecamethylpentasiloxane: 'C[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)C',
+ Dodecyltriethoxysilane: 'CCO[Si](OCC)(CCCCCCCCCCCC)OCC',
+ Dodecyltrimethoxysilane: 'CO[Si](OC)(CCCCCCCCCCCC)OC',
+ 'Dodecyltrimethylammonium Bromide': 'C[N+](C)(CCCCCCCCCCCC)C.[Br-]',
+ 'Dodecyltrimethylammonium Chloride': 'C[N+](C)(CCCCCCCCCCCC)C.[Cl-]',
+ 'D-Phenylalanine': 'N[C@H](CC1=CC=CC=C1)C(O)=O',
+ 'D-Pipecolic Acid': 'O=C(O)C1CCCCN1',
+ 'D-Proline': 'O=C(O)[C@@H]1NCCC1',
+ 'D-Tryptophan': 'N[C@H](CC1=CNC2=C1C=CC=C2)C(O)=O',
+ ethanol: 'OCC',
+ EtOH: 'OCC',
+ Ethoxydiphenylphosphine: 'CCOP(C1=CC=CC=C1)C2=CC=CC=C2',
+ Ethoxytriethylsilane: 'CC[Si](CC)(OCC)CC',
"Ethyl (11bR)-4-Amino-2,6-bis(3,5-di-tert-butylphenyl)-4,5-dihydro-3H-cyclohepta[1,2-a:7,6-a']dinaphthalene-4-carboxylate": 'O=C(C1(N)CC2=C(C3=CC(C(C)(C)C)=CC(C(C)(C)C)=C3)C=C4C=CC=CC4=C2C5=C6C=CC=CC6=CC(C7=CC(C(C)(C)C)=CC(C(C)(C)C)=C7)=C5C1)OCC',
- "Ethyl 1-Hydroxy-1H-1,2,3-triazole-4-carboxylate": 'O=C(C1=CN(O)N=N1)OCC',
- "ethyl acetate": 'CC(OCC)=O',
- "Ethyl Chloroglyoxylate": 'O=C(Cl)C(OCC)=O',
- "Ethyl chlorooxoacetate": 'O=C(OCC)C(Cl)=O',
- "Ethyl Cyano(hydroxyimino)acetate": 'O=C(OCC)/C(C#N)=N/O',
- "Ethylamine": 'NCC',
- "Ethylamine Hydrochloride": 'NCC.[H]Cl',
- "Ethylboronic Acid": 'CCB(O)O',
- "Ethyldiphenylphosphine": 'CCP(C1=CC=CC=C1)C2=CC=CC=C2',
- "Ethylene diamine": 'NCCN',
- "Ethylenediaminetetraacetic Acid": 'O=C(CN(CCN(CC(O)=O)CC(O)=O)CC(O)=O)O',
- "Ethylenedithiobis(trimethylsilane)": 'C[Si](C)(C)SCCS[Si](C)(C)C',
- "Ethyllithium": '[Li]CC',
- "Ethylmagnesium Bromide": 'Br[Mg]CC',
- "Ethylmagnesium Chloride": 'Cl[Mg]CC',
- "Ethyltrimethylammonium Iodide": 'C[N+](C)(CC)C.[I-]',
- "Europium": '[Eu]',
+ 'Ethyl 1-Hydroxy-1H-1,2,3-triazole-4-carboxylate': 'O=C(C1=CN(O)N=N1)OCC',
+ 'ethyl acetate': 'CC(OCC)=O',
+ 'Ethyl Chloroglyoxylate': 'O=C(Cl)C(OCC)=O',
+ 'Ethyl chlorooxoacetate': 'O=C(OCC)C(Cl)=O',
+ 'Ethyl Cyano(hydroxyimino)acetate': 'O=C(OCC)/C(C#N)=N/O',
+ Ethylamine: 'NCC',
+ 'Ethylamine Hydrochloride': 'NCC.[H]Cl',
+ 'Ethylboronic Acid': 'CCB(O)O',
+ Ethyldiphenylphosphine: 'CCP(C1=CC=CC=C1)C2=CC=CC=C2',
+ 'Ethylene diamine': 'NCCN',
+ 'Ethylenediaminetetraacetic Acid': 'O=C(CN(CCN(CC(O)=O)CC(O)=O)CC(O)=O)O',
+ 'Ethylenedithiobis(trimethylsilane)': 'C[Si](C)(C)SCCS[Si](C)(C)C',
+ Ethyllithium: '[Li]CC',
+ 'Ethylmagnesium Bromide': 'Br[Mg]CC',
+ 'Ethylmagnesium Chloride': 'Cl[Mg]CC',
+ 'Ethyltrimethylammonium Iodide': 'C[N+](C)(CC)C.[I-]',
+ Europium: '[Eu]',
"Fluoro-N,N,N',N'-tetramethylformamidinium Hexafluorophosphate": 'C[N+](C)=C(F)N(C)C.F[P-](F)(F)(F)(F)F',
- "Folic Acid Hydrate": 'O=C(O)C(NC(C1=CC=C(NCC2=NC3=C(N=C2)N=C(N)NC3=O)C=C1)=O)CCC(O)=O.[H]O[H]',
- "Formic acid": 'O=CO',
- "Fumaric Acid": 'O=C(O)/C=C/C(O)=O',
- "Gallic Acid Hydrate": 'OC1=CC(C(O)=O)=CC(O)=C1O.[H]O[H]',
- "Glycolic Acid": 'OCC(O)=O',
- "Gold": '[Au]',
- "Gold hydroxide": '[Au+3].[OH-].[OH-].[OH-]',
- "Hafnium": '[Hf]',
- "Hafnium(IV) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Hf+4]',
- "Heptafluorobutyric Anhydride": 'O=C(OC(C(F)(F)C(F)(F)C(F)(F)F)=O)C(F)(F)C(F)(F)C(F)(F)F',
- "Heptafluorobutyryl Chloride": 'O=C(Cl)C(F)(F)C(F)(F)C(F)(F)F',
- "Heptylmagnesium Bromide": 'Br[Mg]CCCCCCC',
- "Hexachlorodisilane": 'Cl[Si](Cl)(Cl)[Si](Cl)(Cl)Cl',
- "Hexadecamethylcyclooctasiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Hexadecyltrimethoxysilane": 'CO[Si](OC)(CCCCCCCCCCCCCCCC)OC',
- "Hexadecyltrimethylammonium Bromide": 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[Br-]',
- "Hexadecyltrimethylammonium Chloride": 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[Cl-]',
- "Hexadecyltrimethylammonium hydroxide": 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[OH-]',
- "Hexadecyltrimethylammonium Hydroxide": 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[OH-]',
- "Hexafluoroacetylacetone": 'O=C(C(F)(F)C(CF)=O)C(F)(F)F',
- "Hexamethonium hydroxide": 'C[N+](CCCCCC[N+](C)(C)C)(C)C.[OH-].[OH-]',
- "Hexamethylbenzene": 'CC1=C(C)C(C)=C(C)C(C)=C1C',
- "Hexamethylcyclotrisiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Hexamethyldisilane": 'C[Si](C)(C)[Si](C)(C)C',
- "Hexamethyldisiloxane": 'C[Si](C)(C)O[Si](C)(C)C',
- "Hexamethylditin": 'C[Sn](C)(C)[Sn](C)(C)C',
- "Hexamethylenetetramine": 'N12CN3CN(C2)CN(C3)C1',
- "Hexaphenylcyclotrisiloxane": 'C1([Si]2(C3=CC=CC=C3)O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)O[Si](C6=CC=CC=C6)(C7=CC=CC=C7)O2)=CC=CC=C1',
- "Hexaphenyldisilane": 'C1([Si](C2=CC=CC=C2)(C3=CC=CC=C3)[Si](C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC=C1',
- "Hexaphenyldisiloxane": 'C1([Si](C2=CC=CC=C2)(C3=CC=CC=C3)O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC=C1',
- "Hexylboronic Acid": 'CCCCCCB(O)O',
- "Hexyllithium": '[Li]CCCCCC',
- "Hexylmagnesium Bromide": 'Br[Mg]CCCCCC',
- "Hexyltriethoxysilane": 'CCO[Si](OCC)(CCCCCC)OCC',
- "Hexyltrimethoxysilane": 'CO[Si](OC)(CCCCCC)OC',
- "Hexyltrimethylammonium Bromide": 'C[N+](C)(CCCCCC)C.[Br-]',
- "Hydriodic Acid": '[H]I',
- "HI": '[H]I',
- "Hydrochloric Acid": '[H]Cl',
- "HCl": '[H]Cl',
- "Hydrogen Bromide": '[H]Br',
- "Hydrogen Chloride": '[H]Cl',
- "Hydrogen peroxide": '[H]OO[H]',
- "H2O2": '[H]OO[H]',
- "Hydroquinidine Hydrochloride": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)CC)C3=CC=NC4=CC=C(OC)C=C34.[H]Cl',
- "Hydroxylamine-O-sulfonic Acid": 'NOS(O)(=O)=O',
- "I0801 (S)-4-Isopropyl-3-(1-naphthylmethyl)-2,5,5-triphenyl-1,3,2-oxazaborolidine (ca. 6% in Toluene, ca. 0.1mol/L)": 'CC([C@@H]1N(CC2=C3C=CC=CC3=CC=C2)B(C4=CC=CC=C4)OC1(C5=CC=CC=C5)C6=CC=CC=C6)C',
- "IF5-Pyridine-HF": '[H]F.FI(F)(F)(F)F.C1=CN=CC=C1',
- "Imidazole": 'C1=NC=CN1',
- "Imidazolium dichromate": 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.C1=[NH+]C=CN1.C2=[NH+]C=CN2',
- "Indan": 'C12=C(CCC2)C=CC=C1',
- "Indene": 'C12=C(CC=C2)C=CC=C1',
- "INDIUM HYDROXIDE": '[In+3].[OH-].[OH-].[OH-]',
- "Indoline": 'C12=C(NCC2)C=CC=C1',
- "Iodine": 'II',
- "Iodobenzene Diacetate": 'IC1=CC=CC=C1.CC(O)=O.CC(O)=O',
- "Iodomesitylene Diacetate": 'CC1=C(I)C(C)=CC(C)=C1.CC(O)=O.CC(O)=O',
- "Iodosodilactone": 'O=C1OI2C3=C1C=CC=C3C(O2)=O',
- "Iridium": '[Ir]',
- "Iridium(III) Chloride Hydrate": '[H]O[H].[Ir+3].[Cl-].[Cl-].[Cl-]',
- "Iron": '[Fe]',
- "Fe": '[Fe]',
- "Iron hydroxide": '[Fe+3].[OH-].[OH-].[OH-]',
- "FeOH": '[Fe+3].[OH-].[OH-].[OH-]',
- "Iron(II) Acetate": 'CC([O-])=O.CC([O-])=O.[Fe+2]',
- "Iron(III) Chloride": '[Fe+3].[Cl-].[Cl-].[Cl-]',
- "FeCl3": '[Fe+3].[Cl-].[Cl-].[Cl-]',
+ 'Folic Acid Hydrate': 'O=C(O)C(NC(C1=CC=C(NCC2=NC3=C(N=C2)N=C(N)NC3=O)C=C1)=O)CCC(O)=O.[H]O[H]',
+ 'Formic acid': 'O=CO',
+ 'Fumaric Acid': 'O=C(O)/C=C/C(O)=O',
+ 'Gallic Acid Hydrate': 'OC1=CC(C(O)=O)=CC(O)=C1O.[H]O[H]',
+ 'Glycolic Acid': 'OCC(O)=O',
+ Gold: '[Au]',
+ 'Gold hydroxide': '[Au+3].[OH-].[OH-].[OH-]',
+ Hafnium: '[Hf]',
+ 'Hafnium(IV) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Hf+4]',
+ 'Heptafluorobutyric Anhydride': 'O=C(OC(C(F)(F)C(F)(F)C(F)(F)F)=O)C(F)(F)C(F)(F)C(F)(F)F',
+ 'Heptafluorobutyryl Chloride': 'O=C(Cl)C(F)(F)C(F)(F)C(F)(F)F',
+ 'Heptylmagnesium Bromide': 'Br[Mg]CCCCCCC',
+ Hexachlorodisilane: 'Cl[Si](Cl)(Cl)[Si](Cl)(Cl)Cl',
+ Hexadecamethylcyclooctasiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
+ Hexadecyltrimethoxysilane: 'CO[Si](OC)(CCCCCCCCCCCCCCCC)OC',
+ 'Hexadecyltrimethylammonium Bromide': 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[Br-]',
+ 'Hexadecyltrimethylammonium Chloride': 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[Cl-]',
+ 'Hexadecyltrimethylammonium hydroxide': 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[OH-]',
+ 'Hexadecyltrimethylammonium Hydroxide': 'C[N+](C)(CCCCCCCCCCCCCCCC)C.[OH-]',
+ Hexafluoroacetylacetone: 'O=C(C(F)(F)C(CF)=O)C(F)(F)F',
+ 'Hexamethonium hydroxide': 'C[N+](CCCCCC[N+](C)(C)C)(C)C.[OH-].[OH-]',
+ Hexamethylbenzene: 'CC1=C(C)C(C)=C(C)C(C)=C1C',
+ Hexamethylcyclotrisiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O1',
+ Hexamethyldisilane: 'C[Si](C)(C)[Si](C)(C)C',
+ Hexamethyldisiloxane: 'C[Si](C)(C)O[Si](C)(C)C',
+ Hexamethylditin: 'C[Sn](C)(C)[Sn](C)(C)C',
+ Hexamethylenetetramine: 'N12CN3CN(C2)CN(C3)C1',
+ Hexaphenylcyclotrisiloxane: 'C1([Si]2(C3=CC=CC=C3)O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)O[Si](C6=CC=CC=C6)(C7=CC=CC=C7)O2)=CC=CC=C1',
+ Hexaphenyldisilane: 'C1([Si](C2=CC=CC=C2)(C3=CC=CC=C3)[Si](C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC=C1',
+ Hexaphenyldisiloxane: 'C1([Si](C2=CC=CC=C2)(C3=CC=CC=C3)O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC=C1',
+ 'Hexylboronic Acid': 'CCCCCCB(O)O',
+ Hexyllithium: '[Li]CCCCCC',
+ 'Hexylmagnesium Bromide': 'Br[Mg]CCCCCC',
+ Hexyltriethoxysilane: 'CCO[Si](OCC)(CCCCCC)OCC',
+ Hexyltrimethoxysilane: 'CO[Si](OC)(CCCCCC)OC',
+ 'Hexyltrimethylammonium Bromide': 'C[N+](C)(CCCCCC)C.[Br-]',
+ 'Hydriodic Acid': '[H]I',
+ HI: '[H]I',
+ 'Hydrochloric Acid': '[H]Cl',
+ HCl: '[H]Cl',
+ 'Hydrogen Bromide': '[H]Br',
+ 'Hydrogen Chloride': '[H]Cl',
+ 'Hydrogen peroxide': '[H]OO[H]',
+ H2O2: '[H]OO[H]',
+ 'Hydroquinidine Hydrochloride': 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)CC)C3=CC=NC4=CC=C(OC)C=C34.[H]Cl',
+ 'Hydroxylamine-O-sulfonic Acid': 'NOS(O)(=O)=O',
+ 'I0801 (S)-4-Isopropyl-3-(1-naphthylmethyl)-2,5,5-triphenyl-1,3,2-oxazaborolidine (ca. 6% in Toluene, ca. 0.1mol/L)': 'CC([C@@H]1N(CC2=C3C=CC=CC3=CC=C2)B(C4=CC=CC=C4)OC1(C5=CC=CC=C5)C6=CC=CC=C6)C',
+ 'IF5-Pyridine-HF': '[H]F.FI(F)(F)(F)F.C1=CN=CC=C1',
+ Imidazole: 'C1=NC=CN1',
+ 'Imidazolium dichromate': 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.C1=[NH+]C=CN1.C2=[NH+]C=CN2',
+ Indan: 'C12=C(CCC2)C=CC=C1',
+ Indene: 'C12=C(CC=C2)C=CC=C1',
+ 'INDIUM HYDROXIDE': '[In+3].[OH-].[OH-].[OH-]',
+ Indoline: 'C12=C(NCC2)C=CC=C1',
+ Iodine: 'II',
+ 'Iodobenzene Diacetate': 'IC1=CC=CC=C1.CC(O)=O.CC(O)=O',
+ 'Iodomesitylene Diacetate': 'CC1=C(I)C(C)=CC(C)=C1.CC(O)=O.CC(O)=O',
+ Iodosodilactone: 'O=C1OI2C3=C1C=CC=C3C(O2)=O',
+ Iridium: '[Ir]',
+ 'Iridium(III) Chloride Hydrate': '[H]O[H].[Ir+3].[Cl-].[Cl-].[Cl-]',
+ Iron: '[Fe]',
+ Fe: '[Fe]',
+ 'Iron hydroxide': '[Fe+3].[OH-].[OH-].[OH-]',
+ FeOH: '[Fe+3].[OH-].[OH-].[OH-]',
+ 'Iron(II) Acetate': 'CC([O-])=O.CC([O-])=O.[Fe+2]',
+ 'Iron(III) Chloride': '[Fe+3].[Cl-].[Cl-].[Cl-]',
+ FeCl3: '[Fe+3].[Cl-].[Cl-].[Cl-]',
"Ishikawa's Reagent": 'FC(N(CC)CC)(C(C(F)(F)F)F)F',
- "Isobutylboronic Acid": 'CC(C)CB(O)O',
- "Isobutyllithium": '[Li]CC(C)C',
- "Isobutylmagnesium Bromide": 'Br[Mg]CC(C)C',
- "isopropanpol": 'CC(O)C',
- "iPr": 'CC(O)C',
- "Isopropenyloxytris(trimethylsilyl)silane": 'C[Si]([Si]([Si](C)(C)C)(OC(C)=C)[Si](C)(C)C)(C)C',
- "isopropyl alcohol": 'CC(O)C',
- "Isopropylboronic Acid": 'CC(B(O)O)C',
- "Isopropyldiphenylphosphine": 'CC(P(C1=CC=CC=C1)C2=CC=CC=C2)C',
- "Isopropyllithium": '[Li]C(C)C',
- "Isopropylmagnesium Bromide": 'Br[Mg]C(C)C',
- "Isopropylmagnesium Chloride": 'Cl[Mg]C(C)C',
- "Isopropylmagnesium Chloride - Lithium Chloride": 'Cl[Mg]C(C)C.[Li+].[Cl-]',
- "Isopropylmagnesium chloride lithium chloride complex": '[Mg+]C(C)C.[Li+].[Cl-].[Cl-]',
- "L-(-)-Threonine": 'N[C@@H]([C@H](O)C)C(O)=O',
- "L-(+)-Leucinol": 'N[C@@H](CC(C)C)CO',
- "L-(+)-Tartaric Acid": 'O[C@H]([C@H](C(O)=O)O)C(O)=O',
- "L-Alanine": 'N[C@@H](C)C(O)=O',
- "Lanthanum": '[La]',
- "LANTHANUM HYDROXIDE": '[La+3].[OH-].[OH-].[OH-]',
- "Lanthanum(III) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[La+3]',
- "L-Ascorbic Acid": 'OC([C@H](O1)[C@H](CO)O)=C(O)C1=O',
- "L-Azetidine-2-carboxylic Acid": 'O=C(C1NCC1)O',
- "LEAD HYDROXIDE": '[Pb+2].[OH-].[OH-]',
- "Lead Tetraacetate": 'CC([O-])=O.CC([O-])=O.CC([O-])=O.CC([O-])=O.[Pb+4]',
- "Pb(OAc)4": 'CC([O-])=O.CC([O-])=O.CC([O-])=O.CC([O-])=O.[Pb+4]',
- "Lead(II) Iodide": '[Pb+2].[I-].[I-]',
- "Lithium (E)-4-oxopent-2-en-2-olate": 'C/C([O-])=C\\C(C)=O.[Li+]',
- "Lithium 2,2,6,6-tetramethylpiperidide": 'CC1(C)CCCC(C)(C)[N-]1.[Li+]',
- "Lithium Acetylide Ethylenediamine Complex": 'NCCN.[C-]#[C-].[Li+].[Li+]',
- "Lithium Aluminum Hydride": '[Li+].[Al+3].[H-].[H-].[H-].[H-]',
- "Lithium amide": '[Li+].[NH2-]',
- "Lithium Bis(trimethylsilyl)amide": 'C[Si]([N-][Si](C)(C)C)(C)C.[Li+]',
- "Lithium Borohydride": '[Li+].[BH4-]',
- "LiBH4": '[Li+].[BH4-]',
- "lithium bromid": '[Li+].[Br-]',
- "LiBr": '[Li+].[Br-]',
- "lithium chloride": '[Li+].[Cl-]',
- "LiCl": '[Li+].[Cl-]',
- "Lithium dicyclohexylamide": 'C1([N-]C2CCCCC2)CCCCC1.[Li+]',
- "Lithium diethylamide": 'CC[N-]CC.[Li+]',
- "Lithium Diisopropylamide": 'CC([N-]C(C)C)C.[Li+]',
- "LDA": 'CC([N-]C(C)C)C.[Li+]',
- "Lithium dimethylamide": 'C[N-]C.[Li+]',
- "Lithium Diphenylphosphide (ca. 0.5mol/L in Tetrahydrofuran)": 'C1([P-]C2=CC=CC=C2)=CC=CC=C1.[Li+]',
- "Lithium ethoxide": 'CC[O-].[Li+]',
- "Lithium hydroxide": '[Li+].[OH-]',
- "LiOH": '[Li+].[OH-]',
- "Lithium isopropoxide": 'CC([O-])C.[Li+]',
- "Lithium methoxide": 'C[O-].[Li+]',
- "LiOMe": 'C[O-].[Li+]',
- "Lithium peroxide": '[O-][O-].[Li+].[Li+]',
- "lithium tetrafluoroborate": 'F[B-](F)(F)F.[Li+]',
- "LiBF4": 'F[B-](F)(F)F.[Li+]',
- "Lithium Triethylborohydride": 'CC[BH-](CC)CC.[Li+]',
- "Lithium triisobutyl(2,2,6,6 tetramethylpiperdino)aluminate": 'CC1(C)CCCC(C)(C)N1[Al-](CC(C)C)(CC(C)C)CC(C)C.[Li+]',
- "Lithium trimethylsilanolate": '[O-][Si](C)(C)C.[Li+]',
- "Lithium Tri-tert-butoxyaluminum Hydride": 'CC(O[Al](OC(C)(C)C)OC(C)(C)C)(C)C.[Li+].[H-]',
- "Lithium tert-butoxide": 'CC(C)([O-])C.[Li+]',
- "Lithium tert-Butoxide": 'CC(C)([O-])C.[Li+]',
- "L-Lactic Acid": 'OC(C)C(O)=O',
- "L-Methionine": 'N[C@@H](CCSC)C(O)=O',
- "L-Phenylalanine": 'N[C@@H](CC1=CC=CC=C1)C(O)=O',
- "L-Pipecolic Acid": 'O=C(O)C1CCCCN1',
- "L-Prolinamide": 'O=C(N)[C@H]1NCCC1',
- "L-Prolinanilide": 'O=C(NC1=CC=CC=C1)[C@H]2NCCC2',
- "L-Proline": 'O=C(O)[C@H]1NCCC1',
- "L-Thioproline": 'O=C(O)[C@H]1NCCC1=S',
- "L-Tryptophan": 'N[C@@H](CC1=CNC2=C1C=CC=C2)C(O)=O',
- "Magnesium bis(diisopropyl)amide": 'CC([N-]C(C)C)C.CC([N-]C(C)C)C.[Mg+2]',
- "Magnesium bis(hexamethyldisilazide)": 'C[Si](C)(C)[N-][Si](C)(C)C.C[Si](C)(C)[N-][Si](C)(C)C.[Mg+2]',
- "magnesium bromide": '[Mg+2].[Br-].[Br-]',
- "MgBr2": '[Mg+2].[Br-].[Br-]',
- "magnesium carbonate": '[O-]C([O-])=O.[Mg+2]',
- "MgCO3": '[O-]C([O-])=O.[Mg+2]',
- "magnesium chloride": '[Mg+2].[Cl-].[Cl-]',
- "MgCl2": '[Mg+2].[Cl-].[Cl-]',
- "Magnesium di-tert-butoxide": 'CC(C)([O-])C.CC(C)([O-])C.[Mg+2]',
- "Magnesium ethoxide": 'CC[O-].CC[O-].[Mg+2]',
- "Mg(OEt)2": 'CC[O-].CC[O-].[Mg+2]',
- "MAGNESIUM HYDROXIDE": '[Mg+2].[OH-].[OH-]',
- "Mg(OH)2": '[Mg+2].[OH-].[OH-]',
- "magnesium iodide": '[Mg+2].[I-].[I-]',
- "MgI2": '[Mg+2].[I-].[I-]',
- "Magnesium methoxide": 'C[O-].C[O-].[Mg+2]',
- "Mg(OMe)2": 'C[O-].C[O-].[Mg+2]',
- "magnesium permanganate": 'O=[Mn](=O)([O-])=O.O=[Mn](=O)([O-])=O.[Mg+2]',
- "Mg(MnO4)2": 'O=[Mn](=O)([O-])=O.O=[Mn](=O)([O-])=O.[Mg+2]',
- "Magnesium permanganate hydrate": 'O=[Mn](=O)([O-])=O.O=[Mn](=O)([O-])=O.[H]O[H].[Mg+2]',
- "Magnesium peroxide": '[O-][O-].[Mg+2]',
- "magnesium sulfate": 'O=S([O-])([O-])=O.[Mg+2]',
- "MgSO4": 'O=S([O-])([O-])=O.[Mg+2]',
- "Maleic Acid": 'O=C(O)/C=C\\C(O)=O',
- "Malonic Acid": 'O=C(O)CC(O)=O',
- "Manganese": '[Mn]',
- "manganese molybdate": 'O=[Mo]([O-])([O-])=O.[Mn+2]',
- "manganese perchlorate": 'O=Cl(=O)([O-])=O.O=Cl(=O)([O-])=O.[Mn+2]',
- "manganese sulfate": 'O=S([O-])([O-])=O.[Mn+2]',
- "MnSO4": 'O=S([O-])([O-])=O.[Mn+2]',
- "Manganese(II) Bis(trifluoromethanesulfonyl)imide": 'FC(F)(S(=O)([N-]S(=O)(C(F)(F)F)=O)=O)F.FC(F)(S(=O)([N-]S(=O)(C(F)(F)F)=O)=O)F.[Mn+2]',
- "Manganese(II) Chloride Tetrahydrate": '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Mn+2].[Cl-].[Cl-]',
- "meso-Tetraphenylchlorin": 'C1(C2=CC=CC=C2)=C(N3)CCC3=C(C4=CC=CC=C4)C5=NC(C=C5)=C(C6=CC=CC=C6)C(N7)=CC=C7C(C8=CC=CC=C8)=C9CCC1=N9',
- "Methallyltrimethylsilane": 'C[Si](C)(CC(C)=C)C',
- "Methanesulfonic Acid": 'CS(=O)(O)=O',
- "methanol": 'CO',
- "MeOH": 'CO',
- "Methoxydimethyl(phenyl)silane": 'C[Si](C)(OC)C1=CC=CC=C1',
- "Methoxydiphenylphosphine": 'COP(C1=CC=CC=C1)C2=CC=CC=C2',
- "Methoxymethyl(diphenyl)phosphine Oxide": 'COCP(C1=CC=CC=C1)(C2=CC=CC=C2)=O',
- "Methoxymethyltrimethylsilane": 'C[Si](C)(COC)C',
- "Methoxytrimethylsilane": 'C[Si](C)(OC)C',
+ 'Isobutylboronic Acid': 'CC(C)CB(O)O',
+ Isobutyllithium: '[Li]CC(C)C',
+ 'Isobutylmagnesium Bromide': 'Br[Mg]CC(C)C',
+ isopropanpol: 'CC(O)C',
+ iPr: 'CC(O)C',
+ 'Isopropenyloxytris(trimethylsilyl)silane': 'C[Si]([Si]([Si](C)(C)C)(OC(C)=C)[Si](C)(C)C)(C)C',
+ 'isopropyl alcohol': 'CC(O)C',
+ 'Isopropylboronic Acid': 'CC(B(O)O)C',
+ Isopropyldiphenylphosphine: 'CC(P(C1=CC=CC=C1)C2=CC=CC=C2)C',
+ Isopropyllithium: '[Li]C(C)C',
+ 'Isopropylmagnesium Bromide': 'Br[Mg]C(C)C',
+ 'Isopropylmagnesium Chloride': 'Cl[Mg]C(C)C',
+ 'Isopropylmagnesium Chloride - Lithium Chloride': 'Cl[Mg]C(C)C.[Li+].[Cl-]',
+ 'Isopropylmagnesium chloride lithium chloride complex': '[Mg+]C(C)C.[Li+].[Cl-].[Cl-]',
+ 'L-(-)-Threonine': 'N[C@@H]([C@H](O)C)C(O)=O',
+ 'L-(+)-Leucinol': 'N[C@@H](CC(C)C)CO',
+ 'L-(+)-Tartaric Acid': 'O[C@H]([C@H](C(O)=O)O)C(O)=O',
+ 'L-Alanine': 'N[C@@H](C)C(O)=O',
+ Lanthanum: '[La]',
+ 'LANTHANUM HYDROXIDE': '[La+3].[OH-].[OH-].[OH-]',
+ 'Lanthanum(III) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[La+3]',
+ 'L-Ascorbic Acid': 'OC([C@H](O1)[C@H](CO)O)=C(O)C1=O',
+ 'L-Azetidine-2-carboxylic Acid': 'O=C(C1NCC1)O',
+ 'LEAD HYDROXIDE': '[Pb+2].[OH-].[OH-]',
+ 'Lead Tetraacetate': 'CC([O-])=O.CC([O-])=O.CC([O-])=O.CC([O-])=O.[Pb+4]',
+ 'Pb(OAc)4': 'CC([O-])=O.CC([O-])=O.CC([O-])=O.CC([O-])=O.[Pb+4]',
+ 'Lead(II) Iodide': '[Pb+2].[I-].[I-]',
+ 'Lithium (E)-4-oxopent-2-en-2-olate': 'C/C([O-])=C\\C(C)=O.[Li+]',
+ 'Lithium 2,2,6,6-tetramethylpiperidide': 'CC1(C)CCCC(C)(C)[N-]1.[Li+]',
+ 'Lithium Acetylide Ethylenediamine Complex': 'NCCN.[C-]#[C-].[Li+].[Li+]',
+ 'Lithium Aluminum Hydride': '[Li+].[Al+3].[H-].[H-].[H-].[H-]',
+ 'Lithium amide': '[Li+].[NH2-]',
+ 'Lithium Bis(trimethylsilyl)amide': 'C[Si]([N-][Si](C)(C)C)(C)C.[Li+]',
+ 'Lithium Borohydride': '[Li+].[BH4-]',
+ LiBH4: '[Li+].[BH4-]',
+ 'lithium bromid': '[Li+].[Br-]',
+ LiBr: '[Li+].[Br-]',
+ 'lithium chloride': '[Li+].[Cl-]',
+ LiCl: '[Li+].[Cl-]',
+ 'Lithium dicyclohexylamide': 'C1([N-]C2CCCCC2)CCCCC1.[Li+]',
+ 'Lithium diethylamide': 'CC[N-]CC.[Li+]',
+ 'Lithium Diisopropylamide': 'CC([N-]C(C)C)C.[Li+]',
+ LDA: 'CC([N-]C(C)C)C.[Li+]',
+ 'Lithium dimethylamide': 'C[N-]C.[Li+]',
+ 'Lithium Diphenylphosphide (ca. 0.5mol/L in Tetrahydrofuran)': 'C1([P-]C2=CC=CC=C2)=CC=CC=C1.[Li+]',
+ 'Lithium ethoxide': 'CC[O-].[Li+]',
+ 'Lithium hydroxide': '[Li+].[OH-]',
+ LiOH: '[Li+].[OH-]',
+ 'Lithium isopropoxide': 'CC([O-])C.[Li+]',
+ 'Lithium methoxide': 'C[O-].[Li+]',
+ LiOMe: 'C[O-].[Li+]',
+ 'Lithium peroxide': '[O-][O-].[Li+].[Li+]',
+ 'lithium tetrafluoroborate': 'F[B-](F)(F)F.[Li+]',
+ LiBF4: 'F[B-](F)(F)F.[Li+]',
+ 'Lithium Triethylborohydride': 'CC[BH-](CC)CC.[Li+]',
+ 'Lithium triisobutyl(2,2,6,6 tetramethylpiperdino)aluminate': 'CC1(C)CCCC(C)(C)N1[Al-](CC(C)C)(CC(C)C)CC(C)C.[Li+]',
+ 'Lithium trimethylsilanolate': '[O-][Si](C)(C)C.[Li+]',
+ 'Lithium Tri-tert-butoxyaluminum Hydride': 'CC(O[Al](OC(C)(C)C)OC(C)(C)C)(C)C.[Li+].[H-]',
+ 'Lithium tert-butoxide': 'CC(C)([O-])C.[Li+]',
+ 'Lithium tert-Butoxide': 'CC(C)([O-])C.[Li+]',
+ 'L-Lactic Acid': 'OC(C)C(O)=O',
+ 'L-Methionine': 'N[C@@H](CCSC)C(O)=O',
+ 'L-Phenylalanine': 'N[C@@H](CC1=CC=CC=C1)C(O)=O',
+ 'L-Pipecolic Acid': 'O=C(O)C1CCCCN1',
+ 'L-Prolinamide': 'O=C(N)[C@H]1NCCC1',
+ 'L-Prolinanilide': 'O=C(NC1=CC=CC=C1)[C@H]2NCCC2',
+ 'L-Proline': 'O=C(O)[C@H]1NCCC1',
+ 'L-Thioproline': 'O=C(O)[C@H]1NCCC1=S',
+ 'L-Tryptophan': 'N[C@@H](CC1=CNC2=C1C=CC=C2)C(O)=O',
+ 'Magnesium bis(diisopropyl)amide': 'CC([N-]C(C)C)C.CC([N-]C(C)C)C.[Mg+2]',
+ 'Magnesium bis(hexamethyldisilazide)': 'C[Si](C)(C)[N-][Si](C)(C)C.C[Si](C)(C)[N-][Si](C)(C)C.[Mg+2]',
+ 'magnesium bromide': '[Mg+2].[Br-].[Br-]',
+ MgBr2: '[Mg+2].[Br-].[Br-]',
+ 'magnesium carbonate': '[O-]C([O-])=O.[Mg+2]',
+ MgCO3: '[O-]C([O-])=O.[Mg+2]',
+ 'magnesium chloride': '[Mg+2].[Cl-].[Cl-]',
+ MgCl2: '[Mg+2].[Cl-].[Cl-]',
+ 'Magnesium di-tert-butoxide': 'CC(C)([O-])C.CC(C)([O-])C.[Mg+2]',
+ 'Magnesium ethoxide': 'CC[O-].CC[O-].[Mg+2]',
+ 'Mg(OEt)2': 'CC[O-].CC[O-].[Mg+2]',
+ 'MAGNESIUM HYDROXIDE': '[Mg+2].[OH-].[OH-]',
+ 'Mg(OH)2': '[Mg+2].[OH-].[OH-]',
+ 'magnesium iodide': '[Mg+2].[I-].[I-]',
+ MgI2: '[Mg+2].[I-].[I-]',
+ 'Magnesium methoxide': 'C[O-].C[O-].[Mg+2]',
+ 'Mg(OMe)2': 'C[O-].C[O-].[Mg+2]',
+ 'magnesium permanganate': 'O=[Mn](=O)([O-])=O.O=[Mn](=O)([O-])=O.[Mg+2]',
+ 'Mg(MnO4)2': 'O=[Mn](=O)([O-])=O.O=[Mn](=O)([O-])=O.[Mg+2]',
+ 'Magnesium permanganate hydrate': 'O=[Mn](=O)([O-])=O.O=[Mn](=O)([O-])=O.[H]O[H].[Mg+2]',
+ 'Magnesium peroxide': '[O-][O-].[Mg+2]',
+ 'magnesium sulfate': 'O=S([O-])([O-])=O.[Mg+2]',
+ MgSO4: 'O=S([O-])([O-])=O.[Mg+2]',
+ 'Maleic Acid': 'O=C(O)/C=C\\C(O)=O',
+ 'Malonic Acid': 'O=C(O)CC(O)=O',
+ Manganese: '[Mn]',
+ 'manganese molybdate': 'O=[Mo]([O-])([O-])=O.[Mn+2]',
+ 'manganese perchlorate': 'O=Cl(=O)([O-])=O.O=Cl(=O)([O-])=O.[Mn+2]',
+ 'manganese sulfate': 'O=S([O-])([O-])=O.[Mn+2]',
+ MnSO4: 'O=S([O-])([O-])=O.[Mn+2]',
+ 'Manganese(II) Bis(trifluoromethanesulfonyl)imide': 'FC(F)(S(=O)([N-]S(=O)(C(F)(F)F)=O)=O)F.FC(F)(S(=O)([N-]S(=O)(C(F)(F)F)=O)=O)F.[Mn+2]',
+ 'Manganese(II) Chloride Tetrahydrate': '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Mn+2].[Cl-].[Cl-]',
+ 'meso-Tetraphenylchlorin': 'C1(C2=CC=CC=C2)=C(N3)CCC3=C(C4=CC=CC=C4)C5=NC(C=C5)=C(C6=CC=CC=C6)C(N7)=CC=C7C(C8=CC=CC=C8)=C9CCC1=N9',
+ Methallyltrimethylsilane: 'C[Si](C)(CC(C)=C)C',
+ 'Methanesulfonic Acid': 'CS(=O)(O)=O',
+ methanol: 'CO',
+ MeOH: 'CO',
+ 'Methoxydimethyl(phenyl)silane': 'C[Si](C)(OC)C1=CC=CC=C1',
+ Methoxydiphenylphosphine: 'COP(C1=CC=CC=C1)C2=CC=CC=C2',
+ 'Methoxymethyl(diphenyl)phosphine Oxide': 'COCP(C1=CC=CC=C1)(C2=CC=CC=C2)=O',
+ Methoxymethyltrimethylsilane: 'C[Si](C)(COC)C',
+ Methoxytrimethylsilane: 'C[Si](C)(OC)C',
"Methyl 2,2':6',2''-Terpyridine-4'-carboxylate": 'O=C(C1=CC(C2=NC=CC=C2)=NC(C3=NC=CC=C3)=C1)OC',
- "Methyl 3-(Trimethylsilyloxy)crotonate": 'C/C(O[Si](C)(C)C)=C/C(OC)=O',
- "Methyl Chlorodifluoroacetate": 'O=C(OC)C(F)(Cl)F',
- "Methyl Chloroglyoxylate": 'O=C(Cl)C(OC)=O',
- "Methyl chlorooxoacetate": 'O=C(OC)C(Cl)=O',
- "Methyl Difluoro(fluorosulfonyl)acetate": 'O=C(OC)C(F)(F)S(=O)(F)=O',
- "Methyl(diphenyl)phosphine Oxide": 'CP(C1=CC=CC=C1)(C2=CC=CC=C2)=O',
- "Methylamine": 'NC',
- "Methylboronic Acid": 'CB(O)O',
- "Methyl-d3-magnesium iodide": '[2H]C([Mg]I)([2H])[2H]',
- "Methyldiphenylphosphine": 'CP(C1=CC=CC=C1)C2=CC=CC=C2',
- "Methyldiphenylsilane": 'C[SiH](C1=CC=CC=C1)C2=CC=CC=C2',
- "methylene chloride": 'ClCCl',
- "Methyllithium lithium bromide": '[Li]C.[Li+].[Br-]',
- "Methylmagnesium Bromide": 'Br[Mg]C',
- "MeMgBr": 'Br[Mg]C',
- "Methylmagnesium chloride": 'Cl[Mg]C',
- "MeMgCl": 'Cl[Mg]C',
- "Methylmagnesium Iodide": 'I[Mg]C',
- "MeMgI": 'I[Mg]C',
- "Methyltri-n-octylammonium Bis(trifluoromethanesulfonyl)imide": 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.C[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC',
- "Methyltri-n-octylammonium Chloride": 'CCCCCCCC[N+](CCCCCCCC)(C)CCCCCCCC.[Cl-]',
- "Methyltri-n-octylammonium Hydrogen Sulfate": 'CCCCCCCC[N+](CCCCCCCC)(C)CCCCCCCC.O=S(O)([O-])=O',
- "Methyltriphenylarsonium Iodide": 'C[As+](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.[I-]',
- "Molybdenum": '[Mo]',
- "Monobutyltin Oxide": 'CCCC[SnH]=O',
- "Monosodium Bromoisocyanurate Hydrate": 'BrC([N-]C(N1)=O)=NC1=O.[Na+]',
- "Morpholine": 'C1CNCCO1',
- "Morpholinosulfur Trifluoride": 'FS(F)(F)N1CCOCC1',
- "m-Tolylmagnesium Bromide": 'Br[Mg]C1=CC=CC(C)=C1',
- "N-(2-Pyridyl)bis(trifluoromethanesulfonimide)": 'O=S(N(C1=NC=CC=C1)S(=O)(C(F)(F)F)=O)(C(F)(F)F)=O',
- "N-(2-Thiophenesulfonyl)-L-prolinamide": 'O=C(NS(=O)(C1=CC=CS1)=O)[C@H]2NCCC2',
- "N-(9-Deoxy-epi-cinchonidin-9-yl)picolinamide": 'O=C(N[C@H]([C@H]1N2CCC(C1)C(C=C)C2)C3=CC=NC4=CC=CC=C34)C5=NC=CC=C5',
- "N-(9-Deoxy-epi-cinchonin-9-yl)picolinamide": 'O=C(N[C@@H](C1N2CCC(C1)C(C=C)C2)C3=CC=NC4=CC=CC=C34)C5=NC=CC=C5',
- "N-(Trifluoromethylthio)phthalimide": 'O=C(N1SC(F)(F)F)C2=CC=CC=C2C1=O',
+ 'Methyl 3-(Trimethylsilyloxy)crotonate': 'C/C(O[Si](C)(C)C)=C/C(OC)=O',
+ 'Methyl Chlorodifluoroacetate': 'O=C(OC)C(F)(Cl)F',
+ 'Methyl Chloroglyoxylate': 'O=C(Cl)C(OC)=O',
+ 'Methyl chlorooxoacetate': 'O=C(OC)C(Cl)=O',
+ 'Methyl Difluoro(fluorosulfonyl)acetate': 'O=C(OC)C(F)(F)S(=O)(F)=O',
+ 'Methyl(diphenyl)phosphine Oxide': 'CP(C1=CC=CC=C1)(C2=CC=CC=C2)=O',
+ Methylamine: 'NC',
+ 'Methylboronic Acid': 'CB(O)O',
+ 'Methyl-d3-magnesium iodide': '[2H]C([Mg]I)([2H])[2H]',
+ Methyldiphenylphosphine: 'CP(C1=CC=CC=C1)C2=CC=CC=C2',
+ Methyldiphenylsilane: 'C[SiH](C1=CC=CC=C1)C2=CC=CC=C2',
+ 'methylene chloride': 'ClCCl',
+ 'Methyllithium lithium bromide': '[Li]C.[Li+].[Br-]',
+ 'Methylmagnesium Bromide': 'Br[Mg]C',
+ MeMgBr: 'Br[Mg]C',
+ 'Methylmagnesium chloride': 'Cl[Mg]C',
+ MeMgCl: 'Cl[Mg]C',
+ 'Methylmagnesium Iodide': 'I[Mg]C',
+ MeMgI: 'I[Mg]C',
+ 'Methyltri-n-octylammonium Bis(trifluoromethanesulfonyl)imide': 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.C[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC',
+ 'Methyltri-n-octylammonium Chloride': 'CCCCCCCC[N+](CCCCCCCC)(C)CCCCCCCC.[Cl-]',
+ 'Methyltri-n-octylammonium Hydrogen Sulfate': 'CCCCCCCC[N+](CCCCCCCC)(C)CCCCCCCC.O=S(O)([O-])=O',
+ 'Methyltriphenylarsonium Iodide': 'C[As+](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.[I-]',
+ Molybdenum: '[Mo]',
+ 'Monobutyltin Oxide': 'CCCC[SnH]=O',
+ 'Monosodium Bromoisocyanurate Hydrate': 'BrC([N-]C(N1)=O)=NC1=O.[Na+]',
+ Morpholine: 'C1CNCCO1',
+ 'Morpholinosulfur Trifluoride': 'FS(F)(F)N1CCOCC1',
+ 'm-Tolylmagnesium Bromide': 'Br[Mg]C1=CC=CC(C)=C1',
+ 'N-(2-Pyridyl)bis(trifluoromethanesulfonimide)': 'O=S(N(C1=NC=CC=C1)S(=O)(C(F)(F)F)=O)(C(F)(F)F)=O',
+ 'N-(2-Thiophenesulfonyl)-L-prolinamide': 'O=C(NS(=O)(C1=CC=CS1)=O)[C@H]2NCCC2',
+ 'N-(9-Deoxy-epi-cinchonidin-9-yl)picolinamide': 'O=C(N[C@H]([C@H]1N2CCC(C1)C(C=C)C2)C3=CC=NC4=CC=CC=C34)C5=NC=CC=C5',
+ 'N-(9-Deoxy-epi-cinchonin-9-yl)picolinamide': 'O=C(N[C@@H](C1N2CCC(C1)C(C=C)C2)C3=CC=NC4=CC=CC=C34)C5=NC=CC=C5',
+ 'N-(Trifluoromethylthio)phthalimide': 'O=C(N1SC(F)(F)F)C2=CC=CC=C2C1=O',
"N,N,N',N'-Tetraethylethylenediamine": 'CCN(CC)CCN(CC)CC',
"N,N,N',N'-Tetrakis(2-pyridylmethyl)ethylenediamine": 'N(CC1=NC=CC=C1)(CC2=NC=CC=C2)CCN(CC3=NC=CC=C3)CC4=NC=CC=C4',
"N,N,N',N'-Tetramethyl-1,3-diaminopropane": 'CN(C)CCCN(C)C',
@@ -1516,86 +1516,86 @@ export const reagents_kombi = {
"N,N'-Bis(salicylidene)-1,2-propanediamine": 'CC(/N=C/C1=CC=CC=C1O)C/N=C/C2=CC=CC=C2O',
"N,N'-Bis(salicylidene)-1,3-propanediamine": 'OC1=CC=CC=C1/C=N/CCC/N=C/C2=CC=CC=C2O',
"N,N'-Bis(salicylidene)ethylenediamine": 'OC1=CC=CC=C1/C=N/CC/N=C/C2=CC=CC=C2O',
- "N,N-Dichloro-p-toluenesulfonamide": 'CC1=CC=C(S(=O)(N(Cl)Cl)=O)C=C1',
+ 'N,N-Dichloro-p-toluenesulfonamide': 'CC1=CC=C(S(=O)(N(Cl)Cl)=O)C=C1',
"N,N'-Dicyclohexyl-1,2-ethanediamine Hydrate": '[H]O[H].C1(NCCNC2CCCCC2)CCCCC1',
"N,N'-Dicyclohexylcarbodiimide": 'C1(N=C=NC2CCCCC2)CCCCC1',
- "DCC": 'C1(N=C=NC2CCCCC2)CCCCC1',
- "N,N-Diethylaniline Borane": 'CCN(CC)C1=CC=CC=C1.B',
+ DCC: 'C1(N=C=NC2CCCCC2)CCCCC1',
+ 'N,N-Diethylaniline Borane': 'CCN(CC)C1=CC=CC=C1.B',
"N,N'-Diisopropylcarbodiimide": 'CC(N=C=NC(C)C)C',
- "DIC": 'CC(N=C=NC(C)C)C',
- "N,N-Diisopropylethylamine": 'CCN(C(C)C)C(C)C',
- "DIPEA": 'CCN(C(C)C)C(C)C',
- "N,N-Diisopropylmethylamine": 'CN(C(C)C)C(C)C',
+ DIC: 'CC(N=C=NC(C)C)C',
+ 'N,N-Diisopropylethylamine': 'CCN(C(C)C)C(C)C',
+ DIPEA: 'CCN(C(C)C)C(C)C',
+ 'N,N-Diisopropylmethylamine': 'CN(C(C)C)C(C)C',
"N,N'-Dimethylethylenediamine": 'CNCCNC',
- "N,N-Dimethyl-N-(methylsulfanylmethylene)ammonium Iodide": 'CSC=[N+](C)C.[I-]',
+ 'N,N-Dimethyl-N-(methylsulfanylmethylene)ammonium Iodide': 'CSC=[N+](C)C.[I-]',
"N,N'-Diphenylethylenediamine": 'C1(NCCNC2=CC=CC=C2)=CC=CC=C1',
"N,N'-Di-tert-butylcarbodiimide": 'CC(N=C=NC(C)(C)C)(C)C',
"N,N'-Di-tert-butylethylenediamine": 'CC(NCCNC(C)(C)C)(C)C',
"N-[(11bS)-4,5-Dihydro-3H-dinaphtho[2,1-c:1',2'-e]azepin-2-yl]trifluoromethanesulfonamide": 'O=S(C(F)(F)F)(NC1=C2CNCC3=CC=C4C=CC=CC4=C3C2=C5C=CC=CC5=C1)=O',
- "N-[(9S)-8α-Cinchonan-9-yl]quinoline-8-sulfonamide": 'O=S(C1=C2N=CC=CC2=CC=C1)(N[C@H]([C@@H]3C[C@H]4[C@H](C[N@@]3CC4)C=C)C5=CC=NC6=CC=CC=C56)=O',
- "N-[2-(Trimethylsilyl)ethoxycarbonyloxy]succinimide": 'O=C(N1OC(OCC[Si](C)(C)C)=O)CCC1=O',
- "N-Benzylcinchonidinium Chloride": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=CC=C35.[Cl-]',
- "N-Benzylcinchoninium Chloride": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=CC=C35.[Cl-]',
- "N-Benzylquinidinium Chloride": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=C(OC)C=C35.[Cl-]',
- "N-Benzylquininium Chloride": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=C(OC)C=C35.[Cl-]',
- "N-Bromoacetamide": 'CC(NBr)=O',
- "N-Bromophthalimide": 'O=C(N1Br)C2=CC=CC=C2C1=O',
- "N-Bromosaccharin": 'O=C1N(Br)S(=O)(C2=C1C=CC=C2)=O',
- "N-Bromosuccinimide": 'O=C(N1Br)CCC1=O',
- "NBS": 'O=C(N1Br)CCC1=O',
- "n-Butanol": 'CCCCO',
- "n-Butyllithium solution": '[Li]CCCC',
- "BuLi": '[Li]CCCC',
- "N-Chlorobenzenesulfonamide sodium salt": 'O=S(C1=CC=CC=C1)([N-]Cl)=O.[Na+]',
- "N-Chlorophthalimide": 'O=C(N1Cl)C2=CC=CC=C2C1=O',
- "N-Chlorosaccharin": 'O=C1N(Cl)S(=O)(C2=C1C=CC=C2)=O',
- "N-Chlorosuccinimide": 'O=C(N1Cl)CCC1=O',
- "NCS": 'O=C(N1Cl)CCC1=O',
- "Neodymium": '[Nd]',
- "NEODYMIUM HYDRATE": '[H]O[H].[Nd]',
- "Neodymium(III) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Nd+3]',
- "N-Ethyldiisopropylamine": 'CC(N(CC)C(C)C)C',
- "N-Fluorobenzenesulfonimide": 'FN(S(=O)(C1=CC=CC=C1)=O)S(=O)(C2=CC=CC=C2)=O',
+ 'N-[(9S)-8α-Cinchonan-9-yl]quinoline-8-sulfonamide': 'O=S(C1=C2N=CC=CC2=CC=C1)(N[C@H]([C@@H]3C[C@H]4[C@H](C[N@@]3CC4)C=C)C5=CC=NC6=CC=CC=C56)=O',
+ 'N-[2-(Trimethylsilyl)ethoxycarbonyloxy]succinimide': 'O=C(N1OC(OCC[Si](C)(C)C)=O)CCC1=O',
+ 'N-Benzylcinchonidinium Chloride': 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=CC=C35.[Cl-]',
+ 'N-Benzylcinchoninium Chloride': 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=CC=C35.[Cl-]',
+ 'N-Benzylquinidinium Chloride': 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=C(OC)C=C35.[Cl-]',
+ 'N-Benzylquininium Chloride': 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=[N+](CC4=CC=CC=C4)C5=CC=C(OC)C=C35.[Cl-]',
+ 'N-Bromoacetamide': 'CC(NBr)=O',
+ 'N-Bromophthalimide': 'O=C(N1Br)C2=CC=CC=C2C1=O',
+ 'N-Bromosaccharin': 'O=C1N(Br)S(=O)(C2=C1C=CC=C2)=O',
+ 'N-Bromosuccinimide': 'O=C(N1Br)CCC1=O',
+ NBS: 'O=C(N1Br)CCC1=O',
+ 'n-Butanol': 'CCCCO',
+ 'n-Butyllithium solution': '[Li]CCCC',
+ BuLi: '[Li]CCCC',
+ 'N-Chlorobenzenesulfonamide sodium salt': 'O=S(C1=CC=CC=C1)([N-]Cl)=O.[Na+]',
+ 'N-Chlorophthalimide': 'O=C(N1Cl)C2=CC=CC=C2C1=O',
+ 'N-Chlorosaccharin': 'O=C1N(Cl)S(=O)(C2=C1C=CC=C2)=O',
+ 'N-Chlorosuccinimide': 'O=C(N1Cl)CCC1=O',
+ NCS: 'O=C(N1Cl)CCC1=O',
+ Neodymium: '[Nd]',
+ 'NEODYMIUM HYDRATE': '[H]O[H].[Nd]',
+ 'Neodymium(III) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Nd+3]',
+ 'N-Ethyldiisopropylamine': 'CC(N(CC)C(C)C)C',
+ 'N-Fluorobenzenesulfonimide': 'FN(S(=O)(C1=CC=CC=C1)=O)S(=O)(C2=CC=CC=C2)=O',
"N-Fluoro-N'-(chloromethyl)triethylenediamine Bis(tetrafluoroborate)": 'F[N+]1(CC2)CC[N+]2(CCl)CC1.F[B-](F)(F)F.F[B-](F)(F)F',
- "n-hexane": 'CCCCCC',
- "N-Hydroxy-5-norbornene-2,3-dicarboximide": 'O=C(C1C2C3C=CC1C3)N(O)C2=O',
- "N-Hydroxyphthalimide": 'O=C(N1O)C2=CC=CC=C2C1=O',
- "N-Hydroxysuccinimide": 'O=C(N1O)CCC1=O',
- "N-Hydroxysulfosuccinimide Sodium": 'O=C(N1O)C(S(=O)([O-])=O)CC1=O.[Na+]',
- "N-Hydroxytetrachlorophthalimide": 'O=C(N1O)C2=C(Cl)C(Cl)=C(Cl)C(Cl)=C2C1=O',
- "Nickel": '[Ni]',
- "Nickel peroxide": '[O-][O-].[Ni+2]',
- "Nickel(II) Benzenesulfonate Hexahydrate": 'O=S(C1=CC=CC=C1)([O-])=O.O=S(C2=CC=CC=C2)([O-])=O.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ni+2]',
- "NICKEL(II) HYDROXIDE": '[Ni+2].[OH-].[OH-]',
- "Nickel(II) peroxide hydrate ": '[O-][O-].[H]O[H].[Ni+2]',
- "Nickel(II) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Ni+2]',
- "Nickel(II) p-Toluenesulfonate Hexahydrate": 'CC1=CC=C(S(=O)([O-])=O)C=C1.CC2=CC=C(S(=O)([O-])=O)C=C2.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ni+2]',
- "Niobium hydroxide oxide": '[Nb+5].[Nb+5].[Nb+5].[OH-].[O-2].[OH-].[O-2].[OH-].[O-2].[OH-].[O-2].[OH-].[O-2]',
- "N-Iodosaccharin": 'O=C1N(I)S(=O)(C2=C1C=CC=C2)=O',
- "N-Iodosuccinimide": 'O=C(N1I)CCC1=O',
+ 'n-hexane': 'CCCCCC',
+ 'N-Hydroxy-5-norbornene-2,3-dicarboximide': 'O=C(C1C2C3C=CC1C3)N(O)C2=O',
+ 'N-Hydroxyphthalimide': 'O=C(N1O)C2=CC=CC=C2C1=O',
+ 'N-Hydroxysuccinimide': 'O=C(N1O)CCC1=O',
+ 'N-Hydroxysulfosuccinimide Sodium': 'O=C(N1O)C(S(=O)([O-])=O)CC1=O.[Na+]',
+ 'N-Hydroxytetrachlorophthalimide': 'O=C(N1O)C2=C(Cl)C(Cl)=C(Cl)C(Cl)=C2C1=O',
+ Nickel: '[Ni]',
+ 'Nickel peroxide': '[O-][O-].[Ni+2]',
+ 'Nickel(II) Benzenesulfonate Hexahydrate': 'O=S(C1=CC=CC=C1)([O-])=O.O=S(C2=CC=CC=C2)([O-])=O.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ni+2]',
+ 'NICKEL(II) HYDROXIDE': '[Ni+2].[OH-].[OH-]',
+ 'Nickel(II) peroxide hydrate ': '[O-][O-].[H]O[H].[Ni+2]',
+ 'Nickel(II) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Ni+2]',
+ 'Nickel(II) p-Toluenesulfonate Hexahydrate': 'CC1=CC=C(S(=O)([O-])=O)C=C1.CC2=CC=C(S(=O)([O-])=O)C=C2.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Ni+2]',
+ 'Niobium hydroxide oxide': '[Nb+5].[Nb+5].[Nb+5].[OH-].[O-2].[OH-].[O-2].[OH-].[O-2].[OH-].[O-2].[OH-].[O-2]',
+ 'N-Iodosaccharin': 'O=C1N(I)S(=O)(C2=C1C=CC=C2)=O',
+ 'N-Iodosuccinimide': 'O=C(N1I)CCC1=O',
"N'-Isopropylidene-2-nitrobenzenesulfonohydrazide": 'O=S(C1=CC=CC=C1[N+]([O-])=O)(NN=C(C)C)=O',
- "Nitric acid": 'O[N+]([O-])=O',
- "HNO3": 'O[N+]([O-])=O',
- "Nitrilotriacetic Acid": 'O=C(O)CN(CC(O)=O)CC(O)=O',
- "nitromethane": 'C[N+]([O-])=O',
- "MeNO2": 'C[N+]([O-])=O',
- "Nitrosyl tetrafluoroborate": 'F[B-](F)(F)(N=O)F',
- "N-Methylbis(trifluoroacetamide)": 'O=C(C(F)(F)F)N(C)C(C(F)(F)F)=O',
- "N-Methyl-N-(trifluoromethylthio)aniline": 'FC(F)(F)SN(C)C1=CC=CC=C1',
- "n-octanol": 'CCCCCCCCO',
- "n-Octyl p-Toluenesulfonate": 'CC1=CC=C(S(=O)(OCCCCCCCC)=O)C=C1',
- "n-Octylboronic Acid": 'CCCCCCCCB(O)O',
- "n-Octylmagnesium Bromide": 'Br[Mg]CCCCCCCC',
- "n-Octyltrimethylammonium Bromide": 'C[N+](C)(CCCCCCCC)C.[Br-]',
- "n-Octyltrimethylammonium Chloride": 'C[N+](C)(CCCCCCCC)C.[Cl-]',
- "Norbornadiene Rhodium(I) Chloride": 'C12C=CC(C2)C=C1.[Rh+].[Cl-]',
- "N-Phenylbis(trifluoromethanesulfonimide)": 'O=S(N(S(=O)(C(F)(F)F)=O)C1=CC=CC=C1)(C(F)(F)F)=O',
- "n-propanol": 'CCCO',
- "N-Salicylideneaniline": 'OC1=CC=CC=C1/C=N/C2=CC=CC=C2',
- "N-tert-Butyl-5-methylisoxazolium Perchlorate": 'CC1=CC=[N+](C(C)(C)C)O1.O=Cl(=O)([O-])=O',
- "N-tert-Butylbenzenesulfenamide": 'CC(NSC1=CC=CC=C1)(C)C',
- "N-tert-Butylbenzenesulfinimidoyl Chloride": 'CC(/N=S(Cl)/C1=CC=CC=C1)(C)C',
- "N-Trimethylsilylimidazole": 'C[Si](N1C=NC=C1)(C)C',
+ 'Nitric acid': 'O[N+]([O-])=O',
+ HNO3: 'O[N+]([O-])=O',
+ 'Nitrilotriacetic Acid': 'O=C(O)CN(CC(O)=O)CC(O)=O',
+ nitromethane: 'C[N+]([O-])=O',
+ MeNO2: 'C[N+]([O-])=O',
+ 'Nitrosyl tetrafluoroborate': 'F[B-](F)(F)(N=O)F',
+ 'N-Methylbis(trifluoroacetamide)': 'O=C(C(F)(F)F)N(C)C(C(F)(F)F)=O',
+ 'N-Methyl-N-(trifluoromethylthio)aniline': 'FC(F)(F)SN(C)C1=CC=CC=C1',
+ 'n-octanol': 'CCCCCCCCO',
+ 'n-Octyl p-Toluenesulfonate': 'CC1=CC=C(S(=O)(OCCCCCCCC)=O)C=C1',
+ 'n-Octylboronic Acid': 'CCCCCCCCB(O)O',
+ 'n-Octylmagnesium Bromide': 'Br[Mg]CCCCCCCC',
+ 'n-Octyltrimethylammonium Bromide': 'C[N+](C)(CCCCCCCC)C.[Br-]',
+ 'n-Octyltrimethylammonium Chloride': 'C[N+](C)(CCCCCCCC)C.[Cl-]',
+ 'Norbornadiene Rhodium(I) Chloride': 'C12C=CC(C2)C=C1.[Rh+].[Cl-]',
+ 'N-Phenylbis(trifluoromethanesulfonimide)': 'O=S(N(S(=O)(C(F)(F)F)=O)C1=CC=CC=C1)(C(F)(F)F)=O',
+ 'n-propanol': 'CCCO',
+ 'N-Salicylideneaniline': 'OC1=CC=CC=C1/C=N/C2=CC=CC=C2',
+ 'N-tert-Butyl-5-methylisoxazolium Perchlorate': 'CC1=CC=[N+](C(C)(C)C)O1.O=Cl(=O)([O-])=O',
+ 'N-tert-Butylbenzenesulfenamide': 'CC(NSC1=CC=CC=C1)(C)C',
+ 'N-tert-Butylbenzenesulfinimidoyl Chloride': 'CC(/N=S(Cl)/C1=CC=CC=C1)(C)C',
+ 'N-Trimethylsilylimidazole': 'C[Si](N1C=NC=C1)(C)C',
"O-(3,4-Dihydro-4-oxo-1,2,3-benzotriazin-3-yl)-N,N,N',N'-tetramethyluronium Tetrafluoroborate": 'CN(C)C(N(C)C)=[O+]N1N=NC2=CC=CC=C2C1=O.F[B-](F)(F)F',
"O-(6-Chlorobenzotriazol-1-yl)-N,N,N',N'-tetramethyluronium Hexafluorophosphate": 'CN(C)C(N(C)C)=[O+]N1N=NC2=CC=C(Cl)C=C21.F[P-](F)(F)(F)(F)F',
"O-(6-Chlorobenzotriazol-1-yl)-N,N,N',N'-tetramethyluronium Tetrafluoroborate": 'CN(C)C(N(C)C)=[O+]N1N=NC2=CC=C(Cl)C=C21.F[B-](F)(F)F',
@@ -1608,652 +1608,654 @@ export const reagents_kombi = {
"O-[(Ethoxycarbonyl)cyanomethylenamino]-N,N,N',N'-tetramethyluronium Hexafluorophosphate": 'CN(C)C(N(C)C)=[O+]/N=C(C(OCC)=O)\\C#N.F[P-](F)(F)(F)(F)F',
"O-[(Ethoxycarbonyl)cyanomethylenamino]-N,N,N',N'-tetramethyluronium Tetrafluoroborate": 'CN(C)C(N(C)C)=[O+]/N=C(C(OCC)=O)\\C#N.F[B-](F)(F)F',
"O-[2-Oxo-1(2H)-pyridyl]-N,N,N',N'-tetramethyluronium Tetrafluoroborate": 'CN(C)C(N(C)C)=[O+]N1C=CC=CC1=O.F[B-](F)(F)F',
- "o-Chloramine T": 'CC1=CC=CC=C1S([N-]Cl)(=O)=O.[Na+]',
- "Octadecamethylcyclononasiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Octadecyltriethoxysilane": 'CCO[Si](OCC)(CCCCCCCCCCCCCCCCCC)OCC',
- "Octadecyltrimethoxysilane": 'CO[Si](OC)(CCCCCCCCCCCCCCCCCC)OC',
- "Octakis(dimethylsilyloxy)octasilsesquioxane": 'C[SiH](C)O[Si]1(O[Si]2(O[SiH](C)C)O[Si](O3)(O[SiH](C)C)O[Si](O4)(O[SiH](C)C)O[Si]5(O[SiH](C)C)O2)O[Si]3(O[SiH](C)C)O[Si]4(O[SiH](C)C)O[Si](O5)(O[SiH](C)C)O1',
- "Octamethylcyclotetrasiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Octamethyltrisiloxane": 'C[Si](C)(C)O[Si](C)(C)O[Si](C)(C)C',
- "Octaphenylcyclotetrasiloxane": 'C1([Si]2(C3=CC=CC=C3)O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)O[Si](C6=CC=CC=C6)(C7=CC=CC=C7)O[Si](C8=CC=CC=C8)(C9=CC=CC=C9)O2)=CC=CC=C1',
- "Octaphenyloctasilsesquioxane": 'C1([Si]2(O3)O[Si](O[Si](O4)(C5=CC=CC=C5)O[Si](O6)(C7=CC=CC=C7)O8)(C9=CC=CC=C9)O[Si]8(C%10=CC=CC=C%10)O[Si]3(C%11=CC=CC=C%11)O[Si]6(C%12=CC=CC=C%12)O[Si]4(C%13=CC=CC=C%13)O2)=CC=CC=C1',
- "Osmium": '[Os]',
- "Osmium Tetroxide": '[Os+8].[O-2].[O-2].[O-2].[O-2]',
- "OsO4": '[Os+8].[O-2].[O-2].[O-2].[O-2]',
- "O-TBDPS-D-Thr-N-Boc-L-tert-Leu-Diphenylphosphine": 'O=C(OC(C)(C)C)N[C@@H](C(C)(C)C)C(N[C@H]([C@@H](O[Si](C1=CC=CC=C1)(C(C)(C)C)C2=CC=CC=C2)C)CP(C3=CC=CC=C3)C4=CC=CC=C4)=O',
- "O-tert-Butyl-L-threonine": 'N[C@@H]([C@H](OC(C)(C)C)C)C(O)=O',
- "o-Tolylmagnesium Bromide": 'Br[Mg]C1=CC=CC=C1C',
- "Oxalyl bromide": 'O=C(Br)C(Br)=O',
- "Oxalyl Chloride": 'O=C(Cl)C(Cl)=O',
- "Oxone": '[O-]S(=O)(=O)[O-].[O-]S(=O)(=O)O.[O-]OS(=O)(=O)O.[O-]OS(=O)(=O)O.[K+].[K+].[K+].[K+].[K+]',
- "Oxygen": 'OO',
- "O2": 'OO',
- "Ozone": 'O=[O+][O-]',
- "O3": 'O=[O+][O-]',
- "Palladium Carbon": '[Pd]',
- "Pd-C": '[Pd]',
- "PdC": '[Pd]',
- "Pd/C": '[Pd]',
- "Palladium hydroxide": '[Pd+2].[OH-].[OH-]',
- "Pd(OH)2": '[Pd+2].[OH-].[OH-]',
- "Palladium(II) Acetate": 'CC([O-])=O.CC([O-])=O.[Pd+2]',
- "Pd(OAc)2": 'CC([O-])=O.CC([O-])=O.[Pd+2]',
- "Palladium(II) Chloride": '[Pd+2].[Cl-].[Cl-]',
- "PdCl2": '[Pd+2].[Cl-].[Cl-]',
- "Palladium(II) Trifluoroacetate": 'O=C([O-])C(F)(F)F.O=C([O-])C(F)(F)F.[Pd+2]',
- "Palmitic Acid": 'CCCCCCCCCCCCCCCC(O)=O',
- "p-Cymene": 'CC1=CC=C(C(C)C)C=C1',
- "Pentadecylmagnesium Bromide": 'Br[Mg]CCCCCCCCCCCCCCC',
- "Pentafluoroanilinium Trifluoromethanesulfonate": 'F[N+](F)(F)C1=CC=CC(F)=C1F.O=S(C(F)(F)F)([O-])=O',
- "Pentafluorobenzoyl Chloride": 'O=C(Cl)C1=C(F)C(F)=C(F)C(F)=C1F',
- "Pentafluorophenol": 'OC1=C(F)C(F)=C(F)C(F)=C1F',
- "Pentafluorophenyl 4-Nitrobenzenesulfonate": 'O=S(C1=CC=C([N+]([O-])=O)C=C1)(OC2=C(F)C(F)=C(F)C(F)=C2F)=O',
- "Pentafluorophenyl Trifluoroacetate": 'O=C(OC1=C(F)C(F)=C(F)C(F)=C1F)C(F)(F)F',
- "Pentafluoropropionic Anhydride": 'O=C(OC(C(F)(F)C(F)(F)F)=O)C(F)(F)C(F)(F)F',
- "pentane": 'CCCCC',
- "Pentylboronic Acid": 'CCCCCB(O)O',
- "Pentylmagnesium Bromide": 'Br[Mg]CCCCC',
- "Pentylmagnesium chloride": 'Cl[Mg]CCCCC',
- "Pentyltriethoxysilane": 'CCO[Si](OCC)(CCCCC)OCC',
- "Periodic acid": 'O=I(=O)(O)=O',
- "HIO4": 'O=I(=O)(O)=O',
- "Perylene": 'C12=CC=CC(C3=CC=CC4=C3C5=CC=C4)=C1C5=CC=C2',
- "PhenoFluor™ Mix": '[Cs]F.Cl[C+](N(C=C1)C2=C(C(C)C)C=CC=C2C(C)C)=[N]1C(C(C(C)C)=CC=C3)=C3C(C)C.[Cl-]',
- "Phenol nitroprusside solution": 'O=N[Fe-2](C#N)(C#N)(C#N)(C#N)C#N.OC1=CC=CC=C1',
- "Phenyl Trifluoromethyl Sulfone": 'O=S(C(F)(F)F)(C1=CC=CC=C1)=O',
- "Phenyl Trifluoromethyl Sulfoxide": 'O=S(C1=CC=CC=C1)C(F)(F)F',
- "Phenyl[3-(trifluoromethyl)phenyl]iodonium triflate": 'FC(C1=CC([I+]C2=CC=CC=C2)=CC=C1)(F)F.O=S([O-])(C(F)(F)F)=O',
- "Phenylarsine Oxide": 'O=[As]C1=CC=CC=C1',
- "Phenylarsonic Acid": 'O=[As](C1=CC=CC=C1)(O)O',
- "Phenylgermanium Trichloride": 'Cl[Ge](Cl)(Cl)C1=CC=CC=C1',
- "Phenylmagnesium Bromide": 'Br[Mg]C1=CC=CC=C1',
- "Phenylmagnesium Chloride": 'Cl[Mg]C1=CC=CC=C1',
- "Phenylmagnesium Iodide": 'I[Mg]C1=CC=CC=C1',
- "Phenylphosphonic Dichloride": 'O=P(C1=CC=CC=C1)(Cl)Cl',
- "Phenylsilane": '[SiH3]C1=CC=CC=C1',
- "Phenyltin Trichloride": 'Cl[Sn](Cl)(Cl)C1=CC=CC=C1',
- "Phosphomolybdic acid": 'O=[Mo](OP(O)(O)=O)(O)=O',
- "Phosphomolybdic Acid Ethanol Solution": 'O=[Mo](OP(O)(O)=O)(O)=O.CCO',
- "Phosphomolybdic Acid Hydrate": 'O=[Mo](OP(O)(O)=O)(O)=O.[H]O[H]',
- "Phosphorus(V) oxychloride": 'ClP(Cl)(Cl)=O',
- "Phosphoryl chloride": 'O=P(Cl)(Cl)Cl',
- "Phthalic Acid": 'O=C(O)C1=CC=CC=C1C(O)=O',
- "Phthalocyanine": 'C1(C2=N3)=C(C=CC=C1)C(N2)=NC4=NC(C5=C4C=CC=C5)=NC(N6)=C7C=CC=CC7=C6N=C8C9=C(C=CC=C9)C3=N8',
- "Piperidine": 'N1CCCCC1',
- "Platinum": '[Pt]',
- "Platinum(IV) Oxide": '[Pt+4].[O-2].[O-2]',
- "Potassium (2-Formylphenyl)trifluoroborate": 'F[B-](F)(C1=CC=CC=C1C=O)F.[K+]',
- "Potassium (2-Methoxyphenyl)trifluoroborate": 'F[B-](F)(C1=CC=CC=C1OC)F.[K+]',
- "Potassium (3-Cyanophenyl)trifluoroborate": 'F[B-](F)(C1=CC=CC(C#N)=C1)F.[K+]',
- "Potassium (3-Methoxyphenyl)trifluoroborate": 'F[B-](F)(C1=CC=CC(OC)=C1)F.[K+]',
- "Potassium (3-Nitrophenyl)trifluoroborate": 'F[B-](F)(C1=CC=CC([N+]([O-])=O)=C1)F.[K+]',
- "Potassium (4-Cyanophenyl)trifluoroborate": 'F[B-](F)(C1=CC=C(C#N)C=C1)F.[K+]',
- "Potassium (4-Methoxyphenyl)trifluoroborate": 'F[B-](F)(C1=CC=C(OC)C=C1)F.[K+]',
- "Potassium (Acetoxymethyl)trifluoroborate": 'F[B-](F)(COC(C)=O)F.[K+]',
- "Potassium (Bromomethyl)trifluoroborate": 'F[B-](F)(CBr)F.[K+]',
- "Potassium (Iodomethyl)trifluoroborate": 'F[B-](F)(CI)F.[K+]',
- "Potassium (Methoxymethyl)trifluoroborate": 'F[B-](F)(COC)F.[K+]',
- "Potassium [[(tert-Butoxycarbonyl)amino]methyl]trifluoroborate": 'F[B-](F)(CNC(OC(C)(C)C)=O)F.[K+]',
- "Potassium 2-iodo-5-methylbenzenesulfonate": 'O=S(C1=CC(C)=CC=C1I)([O-])=O.[K+]',
- "Potassium 2-Thienyltrifluoroborate": 'F[B-](F)(C1=CC=CS1)F.[K+]',
- "Potassium 3-Pyridyltrifluoroborate": 'F[B-](F)(C1=CC=CN=C1)F.[K+]',
- "Potassium 4-Pyridyltrifluoroborate": 'F[B-](F)(C1=CC=NC=C1)F.[K+]',
- "potassium acetate": 'CC([O-])=O.[K+]',
- "KOAc": 'CC([O-])=O.[K+]',
- "Potassium Allyltrifluoroborate": 'F[B-](F)(CC=C)F.[K+]',
- "Potassium Bis(1-pyrazolyl)borohydride": 'N1([BH2-]N2N=CC=C2)N=CC=C1.[K+]',
- "Potassium Bis(trimethylsilyl)amide": 'C[Si]([N-][Si](C)(C)C)(C)C.[K+]',
- "Potassium Borohydride": '[K+].[BH4-]',
- "KBH4": '[K+].[BH4-]',
- "Potassium butanolate": 'CC([O-])(C)C.[K+]',
- "potassium carbonate": '[O-]C([O-])=O.[K+].[K+]',
- "K2CO3": '[O-]C([O-])=O.[K+].[K+]',
- "potassium chloride": '[K+].[Cl-]',
- "KCl": '[K+].[Cl-]',
- "Potassium cyanide": '[C-]#N.[K+]',
- "KCN": '[C-]#N.[K+]',
- "Potassium Cyclopropyltrifluoroborate": 'F[B-](F)(C1CC1)F.[K+]',
- "Potassium dichromate": 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.[K+].[K+]',
- "Potassium ethoxide": 'CC[O-].[K+]',
- "potassium fluoride": '[K+].[F-]',
- "KF": '[K+].[F-]',
- "Potassium Hexafluoroarsenate": 'F[As-](F)(F)(F)(F)F.[K+]',
- "Potassium hydroxide": '[K+].[OH-]',
- "Potassium hydroxide solution": '[K+].[OH-]',
- "KOH": '[K+].[OH-]',
- "potassium iodide": '[K+].[I-]',
- "KI": '[K+].[I-]',
- "Potassium methoxide": 'C[O-].[K+]',
- "KOMe": 'C[O-].[K+]',
- "Potassium monopersulfate triple salt": 'OS(=O)(=O)[O-].OS(=O)(=O)O[O-].OS(=O)(=O)O[O-].[O-]S(=O)(=O)[O-].[K+].[K+].[K+].[K+].[K+]',
- "Potassium nitrate": '[N+](=O)([O-])[O-].[K+]',
- "KNO3": '[N+](=O)([O-])[O-].[K+]',
- "Potassium permanganate": 'O=[Mn](=O)(=O)([K])=O',
- "KMnO4": 'O=[Mn](=O)(=O)([K])=O',
- "Potassium Perrhenate": 'O=[Re](=O)([O-])=O.[K+]',
- "Potassium perruthenate": 'O=[Ru](=O)([O-])=O.[K+]',
- "potassium persulfate": '[O-]S(=O)(OOS(=O)([O-])=O)=O.[K+].[K+]',
- "Potassium Phenyltrifluoroborate": 'F[B-](F)(C1=CC=CC=C1)F.[K+]',
- "Potassium Trifluoro(trifluoromethyl)borate": 'FC([B-](F)(F)F)(F)F.[K+]',
- "Potassium Trifluoroacetate": 'O=C([O-])C(F)(F)F.[K+]',
- "Potassium Trimethoxy(trifluoromethyl)borate": 'FC([B-](OC)(OC)OC)(F)F.[K+]',
- "Potassium trimethylsilanolate": '[O-][Si](C)(C)C.[K+]',
- "Potassium Tris(1-pyrazolyl)borohydride": '[BH-](N1N=CC=C1)(N2N=CC=C2)N3N=CC=C3.[K+]',
- "Potassium Vinyltrifluoroborate": 'F[B-](F)(C=C)F.[K+]',
- "Potassium o-Tolyltrifluoroborate": 'F[B-](F)(C1=CC=CC=C1C)F.[K+]',
- "Potassium p-Tolyltrifluoroborate": 'F[B-](F)(C1=CC=C(C)C=C1)F.[K+]',
- "Potassium tert-Butoxide": 'CC(C)([O-])C.[K+]',
- "Potassium tert-Pentoxide": 'CCC(C)([O-])C.[K+]',
- "Propionic Acid": 'CCC(O)=O',
- "Propylboronic Acid": 'CCCB(O)O',
- "Propylmagnesium Bromide": 'Br[Mg]CCC',
- "Propylmagnesium chloride": 'Cl[Mg]CCC',
- "p-Toluenesulfonic Acid Monohydrate": 'CC1=CC=C(S(=O)(O)=O)C=C1.[H]O[H]',
- "p-Tolylmagnesium Bromide": 'Br[Mg]C1=CC=C(C)C=C1',
- "Pyridine": 'C1=CN=CC=C1',
- "Pyridine - Sulfur Trioxide Complex": 'O=S(=O)=O.C1=CC=NC=C1',
- "Pyridine Iodine Monochloride": 'IC1=NC=CC=C1Cl',
- "Pyridine-2-sulfonyl Fluoride": 'O=S(C1=NC=CC=C1)(F)=O',
- "Pyridinium 3-Nitrobenzenesulfonate": 'O=S(C1=CC=CC([N+]([O-])=O)=C1)([O-])=O.C2=CC=CC=[NH+]2',
- "Pyridinium Bromide Perbromide": 'BrBr.C1=[NH+]C=CC=C1.[Br-]',
- "Pyridinium chlorochromate": '[O-][Cr](=O)(Cl)=O.C1=CC=CC=[NH+]1',
- "Pyridinium dichromate": 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.C1=CC=CC=[NH+]1.C2=CC=CC=[NH+]2',
- "Pyridinium Fluorochromate": '[O-][Cr](=O)(F)=O.C1=CC=CC=[NH+]1',
- "Pyridinium p-Toluenesulfonate": 'CC1=CC=C(S(=O)([O-])=O)C=C1.C2=CC=CC=[NH+]2',
- "Pyrimidine-2-sulfonyl Fluoride": 'O=S(C1=NC=CC=N1)(F)=O',
- "Quincoridine": 'OC[C@H]1C[C@@H]2CC[N@]1C[C@@H]2C=C',
- "Quincorine": 'OC[C@@H]1C[C@@H]2CC[N@]1C[C@@H]2C=C',
- "Quinidine": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34',
- "Quinidine Sulfate Dihydrate": 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34.O=S(O)(O)=O.[H]O[H].[H]O[H]',
- "Quinine": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34',
- "Quinine Hydrochloride Dihydrate": 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34.[H]Cl.[H]O[H].[H]O[H]',
- "Quinolinium Dichromate": 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.C12=CC=C[NH+]=C1C=CC=C2.C34=CC=C[NH+]=C3C=CC=C4',
- "Quinuclidine": 'N12CCC(CC2)CC1',
- "Rhenium": '[Re]',
- "Rhodium": '[Rh]',
- "rhodium trihydroxide": '[Rh+3].[OH-].[OH-].[OH-]',
- "Rhodium(II) Acetate": 'CC([O-])=O.CC([O-])=O.[Rh+2]',
- "Rhodium(II) Octanoate": 'CCCCCCCC([O-])=O.CCCCCCCC([O-])=O.[Rh+2]',
- "RHODIUM(III) OXIDE HYDRATE": '[H]O[H].[Rh+3].[Rh+3].[O-2].[O-2].[O-2]',
- "Rubidium hydroxide": '[Rb+].[OH-]',
- "Ruthenium": '[Ru]',
- "Ruthenium(III) Chloride": '[Ru+3].[Cl-].[Cl-].[Cl-]',
- "RuCl3": '[Ru+3].[Cl-].[Cl-].[Cl-]',
+ 'o-Chloramine T': 'CC1=CC=CC=C1S([N-]Cl)(=O)=O.[Na+]',
+ Octadecamethylcyclononasiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
+ Octadecyltriethoxysilane: 'CCO[Si](OCC)(CCCCCCCCCCCCCCCCCC)OCC',
+ Octadecyltrimethoxysilane: 'CO[Si](OC)(CCCCCCCCCCCCCCCCCC)OC',
+ 'Octakis(dimethylsilyloxy)octasilsesquioxane': 'C[SiH](C)O[Si]1(O[Si]2(O[SiH](C)C)O[Si](O3)(O[SiH](C)C)O[Si](O4)(O[SiH](C)C)O[Si]5(O[SiH](C)C)O2)O[Si]3(O[SiH](C)C)O[Si]4(O[SiH](C)C)O[Si](O5)(O[SiH](C)C)O1',
+ Octamethylcyclotetrasiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
+ Octamethyltrisiloxane: 'C[Si](C)(C)O[Si](C)(C)O[Si](C)(C)C',
+ Octaphenylcyclotetrasiloxane: 'C1([Si]2(C3=CC=CC=C3)O[Si](C4=CC=CC=C4)(C5=CC=CC=C5)O[Si](C6=CC=CC=C6)(C7=CC=CC=C7)O[Si](C8=CC=CC=C8)(C9=CC=CC=C9)O2)=CC=CC=C1',
+ Octaphenyloctasilsesquioxane: 'C1([Si]2(O3)O[Si](O[Si](O4)(C5=CC=CC=C5)O[Si](O6)(C7=CC=CC=C7)O8)(C9=CC=CC=C9)O[Si]8(C%10=CC=CC=C%10)O[Si]3(C%11=CC=CC=C%11)O[Si]6(C%12=CC=CC=C%12)O[Si]4(C%13=CC=CC=C%13)O2)=CC=CC=C1',
+ Osmium: '[Os]',
+ 'Osmium Tetroxide': '[Os+8].[O-2].[O-2].[O-2].[O-2]',
+ OsO4: '[Os+8].[O-2].[O-2].[O-2].[O-2]',
+ 'O-TBDPS-D-Thr-N-Boc-L-tert-Leu-Diphenylphosphine': 'O=C(OC(C)(C)C)N[C@@H](C(C)(C)C)C(N[C@H]([C@@H](O[Si](C1=CC=CC=C1)(C(C)(C)C)C2=CC=CC=C2)C)CP(C3=CC=CC=C3)C4=CC=CC=C4)=O',
+ 'O-tert-Butyl-L-threonine': 'N[C@@H]([C@H](OC(C)(C)C)C)C(O)=O',
+ 'o-Tolylmagnesium Bromide': 'Br[Mg]C1=CC=CC=C1C',
+ 'Oxalyl bromide': 'O=C(Br)C(Br)=O',
+ 'Oxalyl Chloride': 'O=C(Cl)C(Cl)=O',
+ Oxone: '[O-]S(=O)(=O)[O-].[O-]S(=O)(=O)O.[O-]OS(=O)(=O)O.[O-]OS(=O)(=O)O.[K+].[K+].[K+].[K+].[K+]',
+ Oxygen: 'OO',
+ O2: 'OO',
+ Ozone: 'O=[O+][O-]',
+ O3: 'O=[O+][O-]',
+ 'Palladium Carbon': '[Pd]',
+ 'Pd-C': '[Pd]',
+ PdC: '[Pd]',
+ 'Pd/C': '[Pd]',
+ 'Palladium hydroxide': '[Pd+2].[OH-].[OH-]',
+ 'Pd(OH)2': '[Pd+2].[OH-].[OH-]',
+ 'Palladium(II) Acetate': 'CC([O-])=O.CC([O-])=O.[Pd+2]',
+ 'Pd(OAc)2': 'CC([O-])=O.CC([O-])=O.[Pd+2]',
+ 'Palladium(II) Chloride': '[Pd+2].[Cl-].[Cl-]',
+ PdCl2: '[Pd+2].[Cl-].[Cl-]',
+ 'Palladium(II) Trifluoroacetate': 'O=C([O-])C(F)(F)F.O=C([O-])C(F)(F)F.[Pd+2]',
+ 'Palmitic Acid': 'CCCCCCCCCCCCCCCC(O)=O',
+ 'p-Cymene': 'CC1=CC=C(C(C)C)C=C1',
+ 'Pentadecylmagnesium Bromide': 'Br[Mg]CCCCCCCCCCCCCCC',
+ 'Pentafluoroanilinium Trifluoromethanesulfonate': 'F[N+](F)(F)C1=CC=CC(F)=C1F.O=S(C(F)(F)F)([O-])=O',
+ 'Pentafluorobenzoyl Chloride': 'O=C(Cl)C1=C(F)C(F)=C(F)C(F)=C1F',
+ Pentafluorophenol: 'OC1=C(F)C(F)=C(F)C(F)=C1F',
+ 'Pentafluorophenyl 4-Nitrobenzenesulfonate': 'O=S(C1=CC=C([N+]([O-])=O)C=C1)(OC2=C(F)C(F)=C(F)C(F)=C2F)=O',
+ 'Pentafluorophenyl Trifluoroacetate': 'O=C(OC1=C(F)C(F)=C(F)C(F)=C1F)C(F)(F)F',
+ 'Pentafluoropropionic Anhydride': 'O=C(OC(C(F)(F)C(F)(F)F)=O)C(F)(F)C(F)(F)F',
+ pentane: 'CCCCC',
+ 'Pentylboronic Acid': 'CCCCCB(O)O',
+ 'Pentylmagnesium Bromide': 'Br[Mg]CCCCC',
+ 'Pentylmagnesium chloride': 'Cl[Mg]CCCCC',
+ Pentyltriethoxysilane: 'CCO[Si](OCC)(CCCCC)OCC',
+ 'Periodic acid': 'O=I(=O)(O)=O',
+ HIO4: 'O=I(=O)(O)=O',
+ Perylene: 'C12=CC=CC(C3=CC=CC4=C3C5=CC=C4)=C1C5=CC=C2',
+ 'PhenoFluor™ Mix': '[Cs]F.Cl[C+](N(C=C1)C2=C(C(C)C)C=CC=C2C(C)C)=[N]1C(C(C(C)C)=CC=C3)=C3C(C)C.[Cl-]',
+ 'Phenol nitroprusside solution': 'O=N[Fe-2](C#N)(C#N)(C#N)(C#N)C#N.OC1=CC=CC=C1',
+ 'Phenyl Trifluoromethyl Sulfone': 'O=S(C(F)(F)F)(C1=CC=CC=C1)=O',
+ 'Phenyl Trifluoromethyl Sulfoxide': 'O=S(C1=CC=CC=C1)C(F)(F)F',
+ 'Phenyl[3-(trifluoromethyl)phenyl]iodonium triflate': 'FC(C1=CC([I+]C2=CC=CC=C2)=CC=C1)(F)F.O=S([O-])(C(F)(F)F)=O',
+ 'Phenylarsine Oxide': 'O=[As]C1=CC=CC=C1',
+ 'Phenylarsonic Acid': 'O=[As](C1=CC=CC=C1)(O)O',
+ 'Phenylgermanium Trichloride': 'Cl[Ge](Cl)(Cl)C1=CC=CC=C1',
+ 'Phenylmagnesium Bromide': 'Br[Mg]C1=CC=CC=C1',
+ 'Phenylmagnesium Chloride': 'Cl[Mg]C1=CC=CC=C1',
+ 'Phenylmagnesium Iodide': 'I[Mg]C1=CC=CC=C1',
+ 'Phenylphosphonic Dichloride': 'O=P(C1=CC=CC=C1)(Cl)Cl',
+ Phenylsilane: '[SiH3]C1=CC=CC=C1',
+ 'Phenyltin Trichloride': 'Cl[Sn](Cl)(Cl)C1=CC=CC=C1',
+ 'Phosphomolybdic acid': 'O=[Mo](OP(O)(O)=O)(O)=O',
+ 'Phosphomolybdic Acid Ethanol Solution': 'O=[Mo](OP(O)(O)=O)(O)=O.CCO',
+ 'Phosphomolybdic Acid Hydrate': 'O=[Mo](OP(O)(O)=O)(O)=O.[H]O[H]',
+ 'Phosphorus(V) oxychloride': 'ClP(Cl)(Cl)=O',
+ 'Phosphoryl chloride': 'O=P(Cl)(Cl)Cl',
+ 'Phthalic Acid': 'O=C(O)C1=CC=CC=C1C(O)=O',
+ Phthalocyanine: 'C1(C2=N3)=C(C=CC=C1)C(N2)=NC4=NC(C5=C4C=CC=C5)=NC(N6)=C7C=CC=CC7=C6N=C8C9=C(C=CC=C9)C3=N8',
+ Piperidine: 'N1CCCCC1',
+ Platinum: '[Pt]',
+ 'Platinum(IV) Oxide': '[Pt+4].[O-2].[O-2]',
+ 'Potassium (2-Formylphenyl)trifluoroborate': 'F[B-](F)(C1=CC=CC=C1C=O)F.[K+]',
+ 'Potassium (2-Methoxyphenyl)trifluoroborate': 'F[B-](F)(C1=CC=CC=C1OC)F.[K+]',
+ 'Potassium (3-Cyanophenyl)trifluoroborate': 'F[B-](F)(C1=CC=CC(C#N)=C1)F.[K+]',
+ 'Potassium (3-Methoxyphenyl)trifluoroborate': 'F[B-](F)(C1=CC=CC(OC)=C1)F.[K+]',
+ 'Potassium (3-Nitrophenyl)trifluoroborate': 'F[B-](F)(C1=CC=CC([N+]([O-])=O)=C1)F.[K+]',
+ 'Potassium (4-Cyanophenyl)trifluoroborate': 'F[B-](F)(C1=CC=C(C#N)C=C1)F.[K+]',
+ 'Potassium (4-Methoxyphenyl)trifluoroborate': 'F[B-](F)(C1=CC=C(OC)C=C1)F.[K+]',
+ 'Potassium (Acetoxymethyl)trifluoroborate': 'F[B-](F)(COC(C)=O)F.[K+]',
+ 'Potassium (Bromomethyl)trifluoroborate': 'F[B-](F)(CBr)F.[K+]',
+ 'Potassium (Iodomethyl)trifluoroborate': 'F[B-](F)(CI)F.[K+]',
+ 'Potassium (Methoxymethyl)trifluoroborate': 'F[B-](F)(COC)F.[K+]',
+ 'Potassium [[(tert-Butoxycarbonyl)amino]methyl]trifluoroborate': 'F[B-](F)(CNC(OC(C)(C)C)=O)F.[K+]',
+ 'Potassium 2-iodo-5-methylbenzenesulfonate': 'O=S(C1=CC(C)=CC=C1I)([O-])=O.[K+]',
+ 'Potassium 2-Thienyltrifluoroborate': 'F[B-](F)(C1=CC=CS1)F.[K+]',
+ 'Potassium 3-Pyridyltrifluoroborate': 'F[B-](F)(C1=CC=CN=C1)F.[K+]',
+ 'Potassium 4-Pyridyltrifluoroborate': 'F[B-](F)(C1=CC=NC=C1)F.[K+]',
+ 'potassium acetate': 'CC([O-])=O.[K+]',
+ KOAc: 'CC([O-])=O.[K+]',
+ 'Potassium Allyltrifluoroborate': 'F[B-](F)(CC=C)F.[K+]',
+ 'Potassium Bis(1-pyrazolyl)borohydride': 'N1([BH2-]N2N=CC=C2)N=CC=C1.[K+]',
+ 'Potassium Bis(trimethylsilyl)amide': 'C[Si]([N-][Si](C)(C)C)(C)C.[K+]',
+ 'Potassium Borohydride': '[K+].[BH4-]',
+ KBH4: '[K+].[BH4-]',
+ 'Potassium butanolate': 'CC([O-])(C)C.[K+]',
+ 'potassium carbonate': '[O-]C([O-])=O.[K+].[K+]',
+ K2CO3: '[O-]C([O-])=O.[K+].[K+]',
+ 'potassium chloride': '[K+].[Cl-]',
+ KCl: '[K+].[Cl-]',
+ 'Potassium cyanide': '[C-]#N.[K+]',
+ KCN: '[C-]#N.[K+]',
+ 'Potassium Cyclopropyltrifluoroborate': 'F[B-](F)(C1CC1)F.[K+]',
+ 'Potassium dichromate': 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.[K+].[K+]',
+ 'Potassium ethoxide': 'CC[O-].[K+]',
+ 'potassium fluoride': '[K+].[F-]',
+ KF: '[K+].[F-]',
+ 'Potassium Hexafluoroarsenate': 'F[As-](F)(F)(F)(F)F.[K+]',
+ 'Potassium hydroxide': '[K+].[OH-]',
+ 'Potassium hydroxide solution': '[K+].[OH-]',
+ KOH: '[K+].[OH-]',
+ 'potassium iodide': '[K+].[I-]',
+ KI: '[K+].[I-]',
+ 'Potassium methoxide': 'C[O-].[K+]',
+ KOMe: 'C[O-].[K+]',
+ 'Potassium monopersulfate triple salt': 'OS(=O)(=O)[O-].OS(=O)(=O)O[O-].OS(=O)(=O)O[O-].[O-]S(=O)(=O)[O-].[K+].[K+].[K+].[K+].[K+]',
+ 'Potassium nitrate': '[N+](=O)([O-])[O-].[K+]',
+ KNO3: '[N+](=O)([O-])[O-].[K+]',
+ 'Potassium permanganate': 'O=[Mn](=O)(=O)([K])=O',
+ KMnO4: 'O=[Mn](=O)(=O)([K])=O',
+ 'Potassium Perrhenate': 'O=[Re](=O)([O-])=O.[K+]',
+ 'Potassium perruthenate': 'O=[Ru](=O)([O-])=O.[K+]',
+ 'potassium persulfate': '[O-]S(=O)(OOS(=O)([O-])=O)=O.[K+].[K+]',
+ 'Potassium Phenyltrifluoroborate': 'F[B-](F)(C1=CC=CC=C1)F.[K+]',
+ 'Potassium Trifluoro(trifluoromethyl)borate': 'FC([B-](F)(F)F)(F)F.[K+]',
+ 'Potassium Trifluoroacetate': 'O=C([O-])C(F)(F)F.[K+]',
+ 'Potassium Trimethoxy(trifluoromethyl)borate': 'FC([B-](OC)(OC)OC)(F)F.[K+]',
+ 'Potassium trimethylsilanolate': '[O-][Si](C)(C)C.[K+]',
+ 'Potassium Tris(1-pyrazolyl)borohydride': '[BH-](N1N=CC=C1)(N2N=CC=C2)N3N=CC=C3.[K+]',
+ 'Potassium Vinyltrifluoroborate': 'F[B-](F)(C=C)F.[K+]',
+ 'Potassium o-Tolyltrifluoroborate': 'F[B-](F)(C1=CC=CC=C1C)F.[K+]',
+ 'Potassium p-Tolyltrifluoroborate': 'F[B-](F)(C1=CC=C(C)C=C1)F.[K+]',
+ 'Potassium tert-Butoxide': 'CC(C)([O-])C.[K+]',
+ 'Potassium tert-Pentoxide': 'CCC(C)([O-])C.[K+]',
+ 'Propionic Acid': 'CCC(O)=O',
+ 'Propylboronic Acid': 'CCCB(O)O',
+ 'Propylmagnesium Bromide': 'Br[Mg]CCC',
+ 'Propylmagnesium chloride': 'Cl[Mg]CCC',
+ 'p-Toluenesulfonic Acid Monohydrate': 'CC1=CC=C(S(=O)(O)=O)C=C1.[H]O[H]',
+ 'p-Tolylmagnesium Bromide': 'Br[Mg]C1=CC=C(C)C=C1',
+ Pyridine: 'C1=CN=CC=C1',
+ 'Pyridine - Sulfur Trioxide Complex': 'O=S(=O)=O.C1=CC=NC=C1',
+ 'Pyridine Iodine Monochloride': 'IC1=NC=CC=C1Cl',
+ 'Pyridine-2-sulfonyl Fluoride': 'O=S(C1=NC=CC=C1)(F)=O',
+ 'Pyridinium 3-Nitrobenzenesulfonate': 'O=S(C1=CC=CC([N+]([O-])=O)=C1)([O-])=O.C2=CC=CC=[NH+]2',
+ 'Pyridinium Bromide Perbromide': 'BrBr.C1=[NH+]C=CC=C1.[Br-]',
+ 'Pyridinium chlorochromate': '[O-][Cr](=O)(Cl)=O.C1=CC=CC=[NH+]1',
+ 'Pyridinium dichromate': 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.C1=CC=CC=[NH+]1.C2=CC=CC=[NH+]2',
+ 'Pyridinium Fluorochromate': '[O-][Cr](=O)(F)=O.C1=CC=CC=[NH+]1',
+ 'Pyridinium p-Toluenesulfonate': 'CC1=CC=C(S(=O)([O-])=O)C=C1.C2=CC=CC=[NH+]2',
+ 'Pyrimidine-2-sulfonyl Fluoride': 'O=S(C1=NC=CC=N1)(F)=O',
+ Quincoridine: 'OC[C@H]1C[C@@H]2CC[N@]1C[C@@H]2C=C',
+ Quincorine: 'OC[C@@H]1C[C@@H]2CC[N@]1C[C@@H]2C=C',
+ Quinidine: 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34',
+ 'Quinidine Sulfate Dihydrate': 'O[C@H]([C@@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34.O=S(O)(O)=O.[H]O[H].[H]O[H]',
+ Quinine: 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34',
+ 'Quinine Hydrochloride Dihydrate': 'O[C@@H]([C@H]1C[C@H]2[C@H](C[N@@]1CC2)C=C)C3=CC=NC4=CC=C(OC)C=C34.[H]Cl.[H]O[H].[H]O[H]',
+ 'Quinolinium Dichromate': 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.C12=CC=C[NH+]=C1C=CC=C2.C34=CC=C[NH+]=C3C=CC=C4',
+ Quinuclidine: 'N12CCC(CC2)CC1',
+ Rhenium: '[Re]',
+ Rhodium: '[Rh]',
+ 'rhodium trihydroxide': '[Rh+3].[OH-].[OH-].[OH-]',
+ 'Rhodium(II) Acetate': 'CC([O-])=O.CC([O-])=O.[Rh+2]',
+ 'Rhodium(II) Octanoate': 'CCCCCCCC([O-])=O.CCCCCCCC([O-])=O.[Rh+2]',
+ 'RHODIUM(III) OXIDE HYDRATE': '[H]O[H].[Rh+3].[Rh+3].[O-2].[O-2].[O-2]',
+ 'Rubidium hydroxide': '[Rb+].[OH-]',
+ Ruthenium: '[Ru]',
+ 'Ruthenium(III) Chloride': '[Ru+3].[Cl-].[Cl-].[Cl-]',
+ RuCl3: '[Ru+3].[Cl-].[Cl-].[Cl-]',
"Salcomine [=N,N'-Bis(salicylidene)ethylenediiminocobalt(II)]": '[O-]C(C=CC=C1)=C1/C=N/CC/N=C/C2=CC=CC=C2[O-].[Co+2]',
- "Samarium": '[Sm]',
- "Samarium(II) Iodide": '[Sm+2].[I-].[I-]',
- "Scandium": '[Sc]',
- "Scandium(III) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Sc+3]',
- "sec-Butyllithium": '[Li]C(C)CC',
- "sec-Butylmagnesium Bromide": 'Br[Mg]C(C)CC',
- "sec-Butylmagnesium chloride": 'Cl[Mg]C(C)CC',
- "sec-Butylmagnesium Chloride - Lithium Chloride": 'Cl[Mg]C(C)CC.[Li+].[Cl-]',
- "Selenium dioxide": 'O=[Se]=O',
- "SeO2": 'O=[Se]=O',
- "S-Ethyl Trifluorothioacetate": 'O=C(SCC)C(F)(F)F',
- "Silver": '[Ag]',
- "Silver Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.[Ag+]',
- "Silver(I) Trifluoromethanethiolate": '[S-]C(F)(F)F.[Ag+]',
- "Silver(II) picolinate": 'O=C([O-])C1=NC=CC=C1.O=C([O-])C2=NC=CC=C2.[Ag+2]',
- "Silver(II) Pyridine-2-carboxylate": 'O=C(C1=NC=CC=C1)[O-].O=C(C2=NC=CC=C2)[O-].[Ag+2]',
- "Sodium (Trihydroxy)phenylborate": 'O[B-](O)(O)C1=CC=CC=C1.[Na+]',
- "Sodium amide": '[Na+].[NH2-]',
- "NaNH2": '[Na+].[NH2-]',
- "Sodium ascorbate": '[O-]C([C@H](O1)[C@H](CO)O)=C(O)C1=O.[Na+]',
- "sodium azide": '[N-]=[N+]=[N-].[Na+]',
- "NaN3": '[N-]=[N+]=[N-].[Na+]',
- "Sodium Bis(2-methoxyethoxy)aluminum Dihydride": 'COCCO[Al+]OCCOC.[Na+].[H-].[H-]',
- "Sodium Bis(trimethylsilyl)amide": 'C[Si]([N-][Si](C)(C)C)(C)C.[Na+]',
- "Sodium Borohydride": '[Na+].[BH4-]',
- "NaBH4": '[Na+].[BH4-]',
- "sodium bromate": 'O=Br([O-])=O.[Na+]',
- "sodium bromide": '[Na+].[Br-]',
- "NaBr": '[Na+].[Br-]',
- "Sodium Bromodifluoroacetate": 'O=C([O-])C(F)(Br)F.[Na+]',
- "sodium carbonate": '[O-]C([O-])=O.[Na+].[Na+]',
- "Na2CO3": '[O-]C([O-])=O.[Na+].[Na+]',
- "Sodium carbonate decahydrate": '[O-]C([O-])=O.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Na+].[Na+]',
- "sodium chloride": '[Na+].[Cl-]',
- "NaCl": '[Na+].[Cl-]',
- "Sodium Chlorodifluoroacetate": 'O=C([O-])C(F)(Cl)F.[Na+]',
- "Sodium Cyanoborohydride": '[BH3-]C#N.[Na+]',
- "sodium cycanide": '[C-]#N.[Na+]',
- "NaCN": '[C-]#N.[Na+]',
- "sodium D,L lactate": 'OC(C)C([O-])=O.[Na+]',
- "Sodium Dichloroisocyanurate": 'ClN1C([N-]C(N(C1=O)Cl)=O)=O.[Na+]',
- "Sodium dichloroisocyanurate dihydrate": 'O=C1N=C([O-])N(Cl)C(N1Cl)=O.O.O.[Na+]',
- "Sodium dichromate dihydrate": 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.[H]O[H].[H]O[H].[Na+].[Na+]',
- "Sodium Diphenylphosphinobenzene-3-sulfonate": 'O=S(C1=CC(P(C2=CC=CC=C2)C3=CC=CC=C3)=CC=C1)([O-])=O.[Na+]',
- "Sodium Ethoxide": 'CC[O-].[Na+]',
- "NaOEt": 'CC[O-].[Na+]',
- "sodium fluoride": '[Na+].[F-]',
- "NaF": '[Na+].[F-]',
- "Sodium hydride": '[NaH]',
- "NaH": '[NaH]',
- "sodium hydrogen difluoride": '[Na+].[H+].[F-].[F-]',
- "Sodium hydrogen periodate": 'O=I(=O)([O-])=O.O=I(=O)([O-])=O.[Na+].[H+]',
- "Sodium Hydroxide": '[Na+].[OH-]',
- "NaOH": '[Na+].[OH-]',
- "Sodium Hypochlorite Pentahydrate": 'Cl[O-].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Na+]',
- "Sodium iodide": '[Na+].[I-]',
- "NaI": '[Na+].[I-]',
- "sodium L-tartrate": 'O[C@H]([C@H](C([O-])=O)O)C([O-])=O.[Na+].[Na+]',
- "Sodium Methoxide": 'C[O-].[Na+]',
- "NaOMe": 'C[O-].[Na+]',
- "Sodium nitrate": '[N+](=O)([O-])[O-].[Na+]',
- "NaNO3": '[N+](=O)([O-])[O-].[Na+]',
- "Sodium percarbonate": 'O=C(O[O-])[O-].[Na+].[Na+]',
- "sodium perchlorate": 'O=Cl(=O)([O-])=O.[Na+]',
- "Sodium permanganate": 'O=[Mn](=O)([O-])=O.[Na+]',
- "NaMnO4": 'O=[Mn](=O)([O-])=O.[Na+]',
- "Sodium peroxide": '[O-][O-].[Na+].[Na+]',
- "Na2O2": '[O-][O-].[Na+].[Na+]',
- "sodium persulfate": '[O-]S(=O)(OOS(=O)([O-])=O)=O.[Na+].[Na+]',
- "Sodium phosphomolybdate hydrate": 'O=[Mo](OP(O)(O)=O)([O-])=O.[H]O[H].[Na+]',
- "sodium sulfite": 'O=S([O-])[O-].[Na+].[Na+]',
- "Sodium Tellurite Pentahydrate": 'O=[Te]([O-])[O-].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Na+].[Na+]',
- "sodium tetraborate": 'O[B-]12OBO[B-](OBO2)(O)O1.[Na+].[Na+]',
- "Sodium Tetrachloropalladate(II)": 'Cl[Pd-2](Cl)(Cl)Cl.[Na+].[Na+]',
- "Sodium Tetrafluoroborate": 'F[B-](F)(F)F.[Na+]',
- "Sodium Triacetoxyborohydride": 'O=C(O[BH-](OC(C)=O)OC(C)=O)C.[Na+]',
- "Sodium Trifluoroacetate": 'O=C([O-])C(F)(F)F.[Na+]',
- "Sodium Trifluoromethanesulfinate": 'O=S(C(F)(F)F)[O-].[Na+]',
- "Sodium trimethylsilanolate": '[O-][Si](C)(C)C.[Na+]',
- "Sodium Tris(1,1,1,3,3,3-hexafluoroisopropoxy)borohydride": 'FC(F)(C(C(F)(F)F)O[BH-](OC(C(F)(F)F)C(F)(F)F)OC(C(F)(F)F)C(F)(F)F)F.[Na+]',
- "Sodium tert-Butoxide": 'CC(C)([O-])C.[Na+]',
- "Sodium tert-Pentoxide": 'CCC(C)([O-])C.[Na+]',
- "Sorbic Acid": 'C/C=C/C=C/C(O)=O',
- "Strontium hydroxide": '[Sr+2].[OH-].[OH-]',
- "STRONTIUM HYDROXIDE OCTAHYDRATE": '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Sr+2].[OH-].[OH-]',
- "Strontium peroxide": '[O-][O-].[Sr+2]',
- "Succinic Acid": 'O=C(O)CCC(O)=O',
- "Sulfanilic Acid": 'O=S(O)(C1=CC=C(N)C=C1)=O',
- "sulfolane": 'O=S1(CCCC1)=O',
- "Sulfur Trioxide": 'O=S(=O)=O',
- "SO3": 'O=S(=O)=O',
- "Sulfur Trioxide - Triethylamine Complex": 'O=S(=O)=O.CCN(CC)CC',
- "Sulfuric acid": 'O=S(O)(O)=O',
- "H2SO4": 'O=S(O)(O)=O',
- "Sulfuryl chloride": 'O=S(Cl)(Cl)=O',
- "SO2Cl2": 'O=S(Cl)(Cl)=O',
- "Tebbe reagent": 'C[Al-]1(C[Ti+2][Cl+]1)C.[cH-]1cccc1.[cH-]1cccc1',
- "Telluric Acid": 'O=[Te](O)(O)=O',
- "Tellurium(IV) Oxide": '[Te+4].[O-2].[O-2]',
- "Terbium": '[Tb]',
- "tert-Butyl hydroperoxide": 'CC(C)(OO)C',
- "TBHP": 'CC(C)(OO)C',
- "tert-Butyl Hydroperoxide": 'CC(C)(OO)C',
- "tert-Butyldimethylsilane": 'C[SiH](C(C)(C)C)C',
- "tert-Butyldimethylsilanol": 'O[Si](C)(C(C)(C)C)C',
- "tert-Butyldiphenylsilane": 'CC([SiH](C1=CC=CC=C1)C2=CC=CC=C2)(C)C',
- "tert-Butyllithium": '[Li]C(C)(C)C',
- "tBuLi": '[Li]C(C)(C)C',
- "tert-Butylmagnesium Chloride": 'Cl[Mg]C(C)(C)C',
- "tert-Butylmethoxyphenylsilyl Bromide": 'CO[Si](C(C)(C)C)(Br)C1=CC=CC=C1',
- "Tetra(decyl)ammonium Bromide": 'CCCCCCCCCC[N+](CCCCCCCCCC)(CCCCCCCCCC)CCCCCCCCCC.[Br-]',
- "Tetraallyltin": 'C=CC[Sn](CC=C)(CC=C)CC=C',
- "Tetraamylammonium Bromide": 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[Br-]',
- "Tetraamylammonium Chloride": 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[Cl-]',
- "Tetraamylammonium Iodide": 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[I-]',
- "Tetrabromofluorescein": 'O=C1OC2(C3=C(OC4=C2C=CC(O)=C4)C=C(O)C=C3)C5=C1C(Br)=C(Br)C(Br)=C5Br',
- "Tetrabutyl Orthosilicate": 'CCCCO[Si](OCCCC)(OCCCC)OCCCC',
- "Tetrabutyl Orthotitanate": 'CCCCO[Ti](OCCCC)(OCCCC)OCCCC',
- "Tetrabutyl Orthotitanate Tetramer": '[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[Ti+4].[Ti+4].[O-2].[O-2].[Ti+4].[O-2].[Ti+4]',
- "Tetrabutylammonium (meta)periodate": 'CCCC[N+](CCCC)(CCCC)CCCC.O=I(=O)([O-])=O',
- "Tetrabutylammonium Acetate": 'CCCC[N+](CCCC)(CCCC)CCCC.CC([O-])=O',
- "Tetrabutylammonium Bifluoride": 'CCCC[N+](CCCC)(CCCC)CCCC.[H]F.[F-]',
- "Tetrabutylammonium Borohydride": 'CCCC[N+](CCCC)(CCCC)CCCC.[BH4-]',
- "Tetrabutylammonium Bromide": 'CCCC[N+](CCCC)(CCCC)CCCC.[Br-]',
- "Tetrabutylammonium Chloride": 'CCCC[N+](CCCC)(CCCC)CCCC.[Cl-]',
- "Tetrabutylammonium chlorochromate": 'CCCC[N+](CCCC)(CCCC)CCCC.[O-][Cr](=O)(Cl)=O',
- "Tetrabutylammonium Difluorotriphenylstannate": 'CCCC[N+](CCCC)(CCCC)CCCC.F[Sn-](C1=CC=CC=C1)(C2=CC=CC=C2)(F)C3=CC=CC=C3',
- "Tetrabutylammonium Dihydrogen Trifluoride": 'CCCC[N+](CCCC)(CCCC)CCCC.[H+].[H+].[F-].[F-].[F-]',
- "Tetrabutylammonium ethoxide": 'CCCC[N+](CCCC)(CCCC)CCCC.CC[O-]',
- "Tetrabutylammonium Fluoride": 'CCCC[N+](CCCC)(CCCC)CCCC.[F-]',
- "Tetrabutylammonium Fluoride Hydrate": 'CCCC[N+](CCCC)(CCCC)CCCC.[H]O[H].[F-]',
- "Tetrabutylammonium Hexafluorophosphate": 'CCCC[N+](CCCC)(CCCC)CCCC.F[P-](F)(F)(F)(F)F',
- "Tetrabutylammonium Hydrogen Sulfate": 'CCCC[N+](CCCC)(CCCC)CCCC.O=S(O)([O-])=O',
- "Tetrabutylammonium hydroxide": 'CCCC[N+](CCCC)(CCCC)CCCC.[OH-]',
- "Tetrabutylammonium Iodide": 'CCCC[N+](CCCC)(CCCC)CCCC.[I-]',
- "Tetrabutylammonium methoxide": 'CCCC[N+](CCCC)(CCCC)CCCC.C[O-]',
- "Tetrabutylammonium Perchlorate": 'CCCC[N+](CCCC)(CCCC)CCCC.O=Cl(=O)([O-])=O',
- "Tetrabutylammonium Perrhenate": 'CCCC[N+](CCCC)(CCCC)CCCC.O=[Re](=O)([O-])=O',
- "Tetrabutylammonium Tetrafluoroborate": 'CCCC[N+](CCCC)(CCCC)CCCC.F[B-](F)(F)F',
- "Tetrabutylammonium Tetraphenylborate": 'CCCC[N+](CCCC)(CCCC)CCCC.C1([B-](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
- "Tetrabutylammonium Thiocyanate": 'CCCC[N+](CCCC)(CCCC)CCCC.[S-]C#N',
- "Tetrabutylammonium Tribromide": 'CCCC[N+](CCCC)(CCCC)CCCC.[Br-].[Br-].[Br-]',
- "Tetrabutylammonium Trifluoromethanesulfonate": 'CCCC[N+](CCCC)(CCCC)CCCC.O=S(C(F)(F)F)([O-])=O',
- "Tetrabutylammonium Triiodide": 'CCCC[N+](CCCC)(CCCC)CCCC.[I-].[I-].[I-]',
- "Tetrabutylgermane": 'CCCC[Ge](CCCC)(CCCC)CCCC',
- "Tetrabutylphosphonium Bromide": 'CCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
- "Tetrabutylphosphonium Chloride": 'CCCC[P+](CCCC)(CCCC)CCCC.[Cl-]',
- "Tetrabutylphosphonium Hexafluorophosphate": 'CCCC[P+](CCCC)(CCCC)CCCC.F[P-](F)(F)(F)(F)F',
- "Tetrabutylphosphonium Hydroxide": 'CCCC[P+](CCCC)(CCCC)CCCC.[OH-]',
- "Tetrabutylphosphonium malonate": 'CCCC[P+](CCCC)(CCCC)CCCC.CCCC[P+](CCCC)(CCCC)CCCC.O=C([O-])CC([O-])=O',
- "Tetrabutylphosphonium Tetrafluoroborate": 'CCCC[P+](CCCC)(CCCC)CCCC.F[B-](F)(F)F',
- "Tetrabutyltin": 'CCCC[Sn](CCCC)(CCCC)CCCC',
- "Tetracyanoethylene": 'N#CC(C#N)=C(C#N)C#N',
- "Tetradecamethylcycloheptasiloxane": 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
- "Tetradecyltrimethylammonium Bromide": 'C[N+](C)(CCCCCCCCCCCCCC)C.[Br-]',
- "Tetraethyl 1,4,8,11-Tetraazacyclotetradecane-1,4,8,11-tetraacetate": 'O=C(OCC)CN1CCN(CC(OCC)=O)CCCN(CC(OCC)=O)CCN(CC(OCC)=O)CCC1',
- "Tetraethyl Orthosilicate": 'CCO[Si](OCC)(OCC)OCC',
- "Tetraethylammonium Borohydride": 'CC[N+](CC)(CC)CC.[BH4-]',
- "Tetraethylammonium Bromide": 'CC[N+](CC)(CC)CC.[Br-]',
- "Tetraethylammonium Chloride": 'CC[N+](CC)(CC)CC.[Cl-]',
- "Tetraethylammonium Fluoride Tetrahydrofluoride": 'CC[N+](CC)(CC)CC.[H]F.[H]F.[H]F.[H]F.[F-]',
- "Tetraethylammonium Fluoride Trihydrofluoride": 'CC[N+](CC)(CC)CC.[H]F.[H]F.[H]F.[F-]',
- "Tetraethylammonium Hydroxide": 'CC[N+](CC)(CC)CC.[OH-]',
- "Tetraethylammonium Iodide": 'CC[N+](CC)(CC)CC.[I-]',
- "Tetraethylammonium Nitrate": 'CC[N+](CC)(CC)CC.[O-][N+]([O-])=O',
- "Tetraethylammonium Tetrafluoroborate": 'CC[N+](CC)(CC)CC.F[B-](F)(F)F',
- "Tetraethylammonium Trifluoromethanesulfonate": 'CC[N+](CC)(CC)CC.O=S(C(F)(F)F)([O-])=O',
- "Tetraethylammonium p-Toluenesulfonate": 'CC[N+](CC)(CC)CC.CC1=CC=C(S(=O)([O-])=O)C=C1',
- "Tetraethylgermane": 'CC[Ge](CC)(CC)CC',
- "Tetraethylphosphonium Bromide": 'CC[P+](CC)(CC)CC.[Br-]',
- "Tetraethylphosphonium Hexafluorophosphate": 'CC[P+](CC)(CC)CC.F[P-](F)(F)(F)(F)F',
- "Tetraethylphosphonium Tetrafluoroborate": 'CC[P+](CC)(CC)CC.F[B-](F)(F)F',
- "Tetraethylsilane": 'CC[Si](CC)(CC)CC',
- "Tetrafluoroboronic acid diethylether complex": 'F[B-](F)(F)F.CCOCC.[H+]',
- "Tetraheptylammonium Bromide": 'CCCCCCC[N+](CCCCCCC)(CCCCCCC)CCCCCCC.[Br-]',
- "Tetraheptylammonium Iodide": 'CCCCCCC[N+](CCCCCCC)(CCCCCCC)CCCCCCC.[I-]',
- "Tetrahexylammonium Bromide": 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.[Br-]',
- "Tetrahexylammonium Hydrogen Sulfate": 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.O=S(O)([O-])=O',
- "Tetrahexylammonium Hydroxide": 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.[OH-]',
- "Tetrahexylammonium Iodide": 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.[I-]',
- "Tetrahydroxydiboron": 'OB(O)B(O)O',
- "tetrahydroxytitanium": 'O[Ti](O)(O)O',
- "Tetraisobutyl Orthotitanate": 'CC(C)CO[Ti](OCC(C)C)(OCC(C)C)OCC(C)C',
- "Tetraisopropyl Orthosilicate": 'CC(O[Si](OC(C)C)(OC(C)C)OC(C)C)C',
- "Tetraisopropyl Orthotitanate": 'CC(O[Ti](OC(C)C)(OC(C)C)OC(C)C)C',
- "Tetrakis(2,4-pentanedionato)titanium(IV)": '[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[O-]CCC.[O-]CCC.[Ti+4]',
- "Tetrakis(acetonitrile)copper(I) Hexafluorophosphate": 'CC#N.CC#N.CC#N.CC#N.F[P-](F)(F)(F)(F)F.[Cu+]',
- "Tetrakis(acetonitrile)copper(I) Tetrafluoroborate": 'CC#N.CC#N.CC#N.CC#N.F[B-](F)(F)F.[Cu+]',
- "Tetrakis(acetonitrile)palladium(II) Bis(trifluoromethanesulfonate)": 'CC#N.CC#N.CC#N.CC#N.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Pd+2]',
- "Tetrakis(decyl)ammonium hydroxide": 'CCCCCCCCCC[N+](CCCCCCCCCC)(CCCCCCCCCC)CCCCCCCCCC.[OH-]',
- "Tetrakis(dimethylamino)titanium(IV)": 'CN([Ti](N(C)C)(N(C)C)N(C)C)C',
- "Tetrakis(dimethylsilyl)silane": 'C[SiH]([Si]([SiH](C)C)([SiH](C)C)[SiH](C)C)C',
- "Tetrakis(dimethylsilyloxy)silane": 'C[SiH](O[Si](O[SiH](C)C)(O[SiH](C)C)O[SiH](C)C)C',
- "Tetrakis(hydroxymethyl)phosphonium Chloride": 'OC[P+](CO)(CO)CO.[Cl-]',
- "Tetrakis(hydroxymethyl)phosphonium Sulfate": 'OC[P+](CO)(CO)CO.OC[P+](CO)(CO)CO.O=S([O-])([O-])=O',
- "Tetrakis(trimethylsilyl)silane": 'C[Si]([Si]([Si](C)(C)C)([Si](C)(C)C)[Si](C)(C)C)(C)C',
- "Tetrakis(triphenylphosphine)palladium(0)": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.P(C%10=CC=CC=C%10)(C%11=CC=CC=C%11)C%12=CC=CC=C%12.[Pd]',
- "Tetrakis": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.P(C%10=CC=CC=C%10)(C%11=CC=CC=C%11)C%12=CC=CC=C%12.[Pd]',
- "Pd(Ph3)4": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.P(C%10=CC=CC=C%10)(C%11=CC=CC=C%11)C%12=CC=CC=C%12.[Pd]',
- "Tetrakis[dimethyl(vinyl)silyl] Orthosilicate": 'C=C[Si](O[Si](O[Si](C)(C)C=C)(O[Si](C)(C)C=C)O[Si](C)(C)C=C)(C)C',
- "Tetramethylammonium Acetate": 'C[N+](C)(C)C.CC([O-])=O',
- "Tetramethylammonium Borohydride": 'C[N+](C)(C)C.[BH4-]',
- "Tetramethylammonium Bromide": 'C[N+](C)(C)C.[Br-]',
- "Tetramethylammonium Chloride": 'C[N+](C)(C)C.[Cl-]',
- "Tetramethylammonium Dichloroiodate": 'C[N+](C)(C)C.Cl[I-]Cl',
- "Tetramethylammonium Fluoride Tetrahydrate": 'C[N+](C)(C)C.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[F-]',
- "Tetramethylammonium Hexafluorophosphate": 'C[N+](C)(C)C.F[P-](F)(F)(F)(F)F',
- "Tetramethylammonium Hydroxide": 'C[N+](C)(C)C.[OH-]',
- "Tetramethylammonium Iodide": 'C[N+](C)(C)C.[I-]',
- "Tetramethylammonium Sulfate": 'C[N+](C)(C)C.C[N+](C)(C)C.O=S([O-])([O-])=O',
- "Tetramethylammonium Tetrafluoroborate": 'C[N+](C)(C)C.F[B-](F)(F)F',
- "Tetramethylammonium Triacetoxyborohydride": 'C[N+](C)(C)C.O=C(O[BH-](OC(C)=O)OC(C)=O)C',
- "Tetramethylgermane": 'C[Ge](C)(C)C',
- "Tetramethylsilane": 'C[Si](C)(C)C',
- "TMS": 'C[Si](C)(C)C',
- "Tetra-n-octylammonium Bromide": 'CCCCCCCC[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[Br-]',
- "Tetra-n-octylammonium Iodide": 'CCCCCCCC[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[I-]',
- "Tetra-n-octylphosphonium Bromide": 'CCCCCCCC[P+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[Br-]',
- "Tetraoctylammonium hydroxide": 'CCCCCCCC[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[OH-]',
- "Tetrapentylammonium hydroxide": 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[OH-]',
- "Tetraphenyl Lead": 'C1([Pb](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
- "Tetraphenylarsonium Chloride Hydrochloride Hydrate": '[H]O[H].[H]Cl.C1([As+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1.[Cl-]',
- "Tetraphenylcyclopentadienone": 'O=C1C(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C1C5=CC=CC=C5',
- "Tetraphenylgermane": 'C1([Ge](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
- "Tetraphenylphosphonium Bromide": 'C1([P+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1.[Br-]',
- "Tetraphenylphosphonium Chloride": 'C1([P+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1.[Cl-]',
- "Tetraphenylporphyrin": 'C1(C2=CC=CC=C2)=C3C=CC(C(C4=CC=CC=C4)=C5C=CC(N5)=C(C6=CC=CC=C6)C(C=C7)=NC7=C(C8=CC=CC=C8)C9=CC=C1N9)=N3',
- "Tetraphenylsilane": 'C1([Si](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
- "Tetraphenyltin": 'C1([Sn](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
- "Tetrapropyl Orthosilicate": 'CCCO[Si](OCCC)(OCCC)OCCC',
- "Tetrapropylammonium Bromide": 'CCC[N+](CCC)(CCC)CCC.[Br-]',
- "Tetrapropylammonium Chloride": 'CCC[N+](CCC)(CCC)CCC.[Cl-]',
- "Tetrapropylammonium Hydroxide": 'CCC[N+](CCC)(CCC)CCC.[OH-]',
- "Tetrapropylammonium Iodide": 'CCC[N+](CCC)(CCC)CCC.[I-]',
- "Tetrapropylammonium Perruthenate": 'CCC[N+](CCC)(CCC)CCC.O=[Ru](=O)([O-])=O',
- "Thallium(III) Trifluoroacetate": 'O=C([O-])C(F)(F)F.O=C([O-])C(F)(F)F.O=C([O-])C(F)(F)F.[Tl+3]',
- "THF": 'C1CCCO1',
- "Thioacetic Acid": 'CC(O)=S',
- "Thioglycolic Acid": 'SCC(O)=O',
- "Thionyl Chloride": 'O=S(Cl)Cl',
- "Thiophosphoryl Chloride": 'OP(O)(Cl)=S',
- "Thulium": '[Tm]',
- "Thulium(III) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Tm+3]',
- "tin hydroxide": '[Sn+4].[OH-].[OH-].[OH-].[OH-]',
- "Tin(II) 2-Ethylhexanoate": 'CCCCC(CC)C([O-])=O.CCCCC(CC)C([O-])=O.[Sn+2]',
- "Tin(II) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Sn+2]',
- "Tin(IV) Chloride": '[Sn+4].[Cl-].[Cl-].[Cl-].[Cl-]',
- "Titanium": '[Ti]',
- "titanium hydroxide": '[Ti+4].[OH-].[OH-].[OH-].[OH-]',
- "Titanium(IV) Chloride": '[Ti+4].[Cl-].[Cl-].[Cl-].[Cl-]',
- "TMS-Imidazole (=N-Trimethylsilylimidazole)": 'C[Si](N1C=NC=C1)(C)C',
- "toluene": 'CC1=CC=CC=C1',
- "trans,trans-1,5-Bis(4-fluorophenyl)-1,4-pentadien-3-one": 'O=C(/C=C/C1=CC=C(F)C=C1)/C=C/C2=CC=C(F)C=C2',
- "trans,trans-1,5-Bis(4-methoxyphenyl)-1,4-pentadien-3-one": 'O=C(/C=C/C1=CC=C(OC)C=C1)/C=C/C2=CC=C(OC)C=C2',
- "trans,trans-1,5-Bis[4-(trifluoromethyl)phenyl]-1,4-pentadien-3-one": 'O=C(/C=C/C1=CC=C(C(F)(F)F)C=C1)/C=C/C2=CC=C(C(F)(F)F)C=C2',
- "trans,trans-1,5-Diphenyl-1,4-pentadien-3-one": 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2',
- "trans-1,2-Bis(diphenylphosphino)ethylene": 'P(/C=C/P(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
- "trans-2,6-Diisopropyl-N-(2-pyridylmethylene)aniline": 'CC(C1=C(C(C(C)C)=CC=C1)/N=C/C2=NC=CC=C2)C',
- "trans-2-Butene-1,4-bis(triphenylphosphonium Chloride)": 'C1([P+](C/C=C/C[P+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC=C1.[Cl-].[Cl-]',
- "trans-4-(tert-Butyldiphenylsilyloxy)-L-proline": 'O=C(O)[C@H]1NC[C@H](O[Si](C2=CC=CC=C2)(C(C)(C)C)C3=CC=CC=C3)C1',
- "trans-4-Fluoro-L-proline": 'O=C(O)[C@H]1NC[C@H](F)C1',
- "Tri(2-furyl)phosphine": 'P(C1=CC=CO1)(C2=CC=CO2)C3=CC=CO3',
- "Tri(2-thienyl)phosphine": 'P(C1=CC=CS1)(C2=CC=CS2)C3=CC=CS3',
- "Tri(cyclohexa-2,5-dien-1-yl)silane": '[SiH](C1C=CCC=C1)(C2C=CCC=C2)C3C=CCC=C3',
- "Tri(m-tolyl)phosphine": 'CC1=CC(P(C2=CC=CC(C)=C2)C3=CC=CC(C)=C3)=CC=C1',
- "Tri(o-tolyl)phosphine": 'CC1=CC=CC=C1P(C2=CC=CC=C2C)C3=CC=CC=C3C',
- "Tri(p-tolyl)phosphine": 'CC1=CC=C(P(C2=CC=C(C)C=C2)C3=CC=C(C)C=C3)C=C1',
- "Triacetoxyborohydride": 'O=C(O[BH-](OC(C)=O)OC(C)=O)C',
- "Triacetoxyethylsilane": 'CC[Si](OC(C)=O)(OC(C)=O)OC(C)=O',
- "Triallyl(methyl)silane": 'C[Si](CC=C)(CC=C)CC=C',
- "Triallyl(phenyl)silane": 'C=CC[Si](CC=C)(CC=C)C1=CC=CC=C1',
- "Tribenzylsilane": '[SiH](CC1=CC=CC=C1)(CC2=CC=CC=C2)CC3=CC=CC=C3',
- "Tribromoacetic Acid": 'O=C(O)C(Br)(Br)Br',
- "Tributyl borate": 'B(OCCCC)(OCCCC)OCCCC',
- "Tributyl(2-methoxyethyl)phosphonium Bis(trifluoromethanesulfonyl)imide": 'CCCC[P+](CCCC)(CCCC)CCOC.FC(F)(S([N-]S(C(F)(F)F)(=O)=O)(=O)=O)F',
- "Tributyl(cyanomethyl)phosphonium Chloride": 'N#CC[P+](CCCC)(CCCC)CCCC.[Cl-]',
- "Tributyl(ethyl)phosphonium Diethyl Phosphate": 'CC[P+](CCCC)(CCCC)CCCC.O=P(OCC)([O-])OCC',
- "Tributyl(methyl)ammonium Dicyanamide": '[H]C(C([H])([H])C([H])([H])C([H])([H])[H])([H])[N+](C([H])([H])C([H])([H])C([H])([H])C([H])([H])[H])(C([H])([H])[H])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[H].[N-]=C=NC#N',
- "Tributylamine": 'CCCCN(CCCC)CCCC',
- "Tributylchlorosilane": 'Cl[Si](CCCC)(CCCC)CCCC',
- "Tributyldodecylphosphonium Bromide": 'CCCCCCCCCCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
- "Tributylhexadecylphosphonium Bromide": 'CCCCCCCCCCCCCCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
- "Tributylmethylammonium Bis(trifluoromethanesulfonyl)imide": 'FC(F)(S([N-]S(C(F)(F)F)(=O)=O)(=O)=O)F.C[N+](CCCC)(CCCC)CCCC',
- "Tributylmethylammonium Chloride": 'C[N+](CCCC)(CCCC)CCCC.[Cl-]',
- "Tributylmethylphosphonium Bis(trifluoromethanesulfonyl)imide": 'C[P+](CCCC)(CCCC)CCCC.FC(F)(S([N-]S(C(F)(F)F)(=O)=O)(=O)=O)F',
- "Tributylmethylphosphonium Iodide": 'C[P+](CCCC)(CCCC)CCCC.[I-]',
- "Tributyl-n-octylphosphonium Bromide": 'CCCCCCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
- "Tributylphosphine Oxide": 'CCCCP(CCCC)(CCCC)=O',
- "Tributylsilane": 'CCCC[SiH](CCCC)CCCC',
- "Tributylsulfonium Iodide": 'CCCC[S+](CCCC)CCCC.[I-]',
- "Tricarbonyl(cyclooctatetraene)iron": '[C]=O.[C]=O.[C]=O.[Fe].C1=C\\C=C/C=C\\C=C/1',
- "Trichloro(3,3,3-trifluoropropyl)silane": 'FC(F)(F)CC[Si](Cl)(Cl)Cl',
- "Trichloro-2-cyanoethylsilane": 'N#CCC[Si](Cl)(Cl)Cl',
- "Trichloroacetic Acid": 'O=C(O)C(Cl)(Cl)Cl',
- "Trichlorocyclopentylsilane": 'Cl[Si](Cl)(Cl)C1CCCC1',
- "Trichloroisocyanuric Acid": 'O=C(N(Cl)C(N1Cl)=O)N(Cl)C1=O',
- "Trichloromethanesulfonyl Chloride": 'O=S(C(Cl)(Cl)Cl)(Cl)=O',
- "Tricyclohexylphosphine": 'P(C1CCCCC1)(C2CCCCC2)C3CCCCC3',
- "Tricyclohexylphosphonium Tetrafluoroborate": 'F[B-](F)(F)F.[PH+](C1CCCCC1)(C2CCCCC2)C3CCCCC3',
- "Triethoxy(3-glycidyloxypropyl)silane": 'CCO[Si](OCC)(OCC)CCCOCC1CO1',
- "Triethoxy(pentafluorophenyl)silane": 'FC1=C(F)C(F)=C(F)C(F)=C1[Si](OCC)(OCC)OCC',
- "Triethoxy(propyl)silane": 'CCC[Si](OCC)(OCC)OCC',
- "Triethoxy[2-(7-oxabicyclo[4.1.0]heptan-3-yl)ethyl]silane": 'CCO[Si](OCC)(OCC)CCC1CC2OC2CC1',
- "Triethoxy-1H,1H,2H,2H-tridecafluoro-n-octylsilane": 'F[SiH2]C(F)(F)CC(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(OCC)(OCC)OCC',
- "Triethoxyethylsilane": 'CC[Si](OCC)(OCC)OCC',
- "Triethoxyfluorosilane": 'F[Si](OCC)(OCC)OCC',
- "Triethoxymethylsilane": 'C[Si](OCC)(OCC)OCC',
- "Triethoxy-n-octylsilane": 'CCCCCCCC[Si](OCC)(OCC)OCC',
- "Triethoxyphenylsilane": 'CCO[Si](OCC)(OCC)C1=CC=CC=C1',
- "Triethoxyvinylsilane": 'C=C[Si](OCC)(OCC)OCC',
- "Triethyl 2-Fluoro-2-phosphonoacetate": 'O=C(OCC)C(F)P(OCC)(OCC)=O',
- "Triethyl(trifluoromethyl)silane": 'FC([Si](CC)(CC)CC)(F)F',
- "Triethylamine": 'CCN(CC)CC',
- "Triethylamine Borane": 'CCN(CC)CC.B',
- "Triethylamine Trihydrofluoride": 'CCN(CC)CC.[H]F.[H]F.[H]F',
- "Triethylchlorogermane": 'Cl[Ge](CC)(CC)CC',
- "Triethylenetetramine": 'NCCNCCNCCN',
- "Triethylmethylammonium Chloride": 'C[N+](CC)(CC)CC.[Cl-]',
- "Triethylmethylammonium hydroxide": 'C[N+](CC)(CC)CC.[OH-]',
- "Triethylphenylammonium Chloride": 'CC[N+](CC)(CC)C1=CC=CC=C1.[Cl-]',
- "Triethylsilane": 'CC[SiH](CC)CC',
- "TES": 'CC[SiH](CC)CC',
- "Triethylsilanol": 'O[Si](CC)(CC)CC',
- "Triethylsilylacetylene": 'C#C[Si](CC)(CC)CC',
- "Triethylsulfonium Bis(trifluoromethanesulfonyl)imide": 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CC[S+](CC)CC',
- "Triethylvinylsilane": 'C=C[Si](CC)(CC)CC',
- "Trifluoroacetic Acid": 'O=C(O)C(F)(F)F',
- "TFA": 'O=C(O)C(F)(F)F',
- "Trifluoroacetic Anhydride": 'O=C(OC(C(F)(F)F)=O)C(F)(F)F',
- "TFAA": 'O=C(OC(C(F)(F)F)=O)C(F)(F)F',
- "Trifluoroacetyl Triflate": 'O=S(OC(C(F)(F)F)=O)(C(F)(F)F)=O',
- "Trifluoroacetylacetone": 'O=C(CC(C)=O)C(F)(F)F',
- "Trifluoroboronic acid diethyletherate": 'FB(F)F.CCOCC',
- "Trifluoromethanesulfonanilide": 'O=S(C(F)(F)F)(NC1=CC=CC=C1)=O',
- "Trifluoromethanesulfonic Acid": 'O=S(C(F)(F)F)(O)=O',
- "Trifluoromethanesulfonic Anhydride": 'O=S(C(F)(F)F)(OS(C(F)(F)F)(=O)=O)=O',
- "Trifluoromethanesulfonyl Chloride": 'O=S(C(F)(F)F)(Cl)=O',
- "Trihexyl(tetradecyl)phosphonium Chloride": 'CCCCCCCCCCCCCC[P+](CCCCCC)(CCCCCC)CCCCCC.[Cl-]',
- "Trihexyl(tetradecyl)phosphonium Dicyanamide": 'CCCCCC[P+](CCCCCC)(CCCCCC)CCCCCCCCCCCCCC.N#C[N-]C#N',
- "Trihexylphosphine": 'CCCCCCP(CCCCCC)CCCCCC',
- "Trihexylsilane": 'CCCCCC[SiH](CCCCCC)CCCCCC',
- "Triisopropyl[(trimethylsilyl)ethynyl]silane": 'C[Si](C#C[Si](C(C)C)(C(C)C)C(C)C)(C)C',
- "Triisopropylsilane": 'CC([SiH](C(C)C)C(C)C)C',
- "Triisopropylsilylacetylene": 'C#C[Si](C(C)C)(C(C)C)C(C)C',
- "Trimagnesium Dicitrate Nonahydrate": 'OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Mg+2].[Mg+2].[Mg+2]',
- "Trimethoxy(1H,1H,2H,2H-tridecafluoro-n-octyl)silane": 'FC(C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F)(F)CC[Si](OC)(OC)OC',
- "Trimethoxy(2-phenylethyl)silane": 'CO[Si](OC)(OC)CCC1=CC=CC=C1',
- "Trimethoxy(3,3,3-trifluoropropyl)silane": 'FC(F)(F)CC[Si](OC)(OC)OC',
- "Trimethoxy(4-methoxyphenyl)silane": 'COC1=CC=C([Si](OC)(OC)OC)C=C1',
- "Trimethoxy(methyl)silane": 'C[Si](OC)(OC)OC',
- "Trimethoxy(phenylethyl)silane": 'CO[Si](OC)(OC)CCC1=CC=CC=C1',
- "Trimethoxy(propyl)silane": 'CCC[Si](OC)(OC)OC',
- "Trimethoxy[3-(methylamino)propyl]silane": 'CNCCC[Si](OC)(OC)OC',
- "Trimethoxy[3-(phenylamino)propyl]silane": 'CO[Si](OC)(OC)CCCNC1=CC=CC=C1',
- "Trimethoxy-n-octylsilane": 'CCCCCCCC[Si](OC)(OC)OC',
- "Trimethoxyphenylsilane": 'CO[Si](OC)(OC)C1=CC=CC=C1',
+ Samarium: '[Sm]',
+ 'Samarium(II) Iodide': '[Sm+2].[I-].[I-]',
+ Scandium: '[Sc]',
+ 'Scandium(III) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Sc+3]',
+ 'sec-Butyllithium': '[Li]C(C)CC',
+ 'sec-Butylmagnesium Bromide': 'Br[Mg]C(C)CC',
+ 'sec-Butylmagnesium chloride': 'Cl[Mg]C(C)CC',
+ 'sec-Butylmagnesium Chloride - Lithium Chloride': 'Cl[Mg]C(C)CC.[Li+].[Cl-]',
+ 'Selenium dioxide': 'O=[Se]=O',
+ SeO2: 'O=[Se]=O',
+ 'S-Ethyl Trifluorothioacetate': 'O=C(SCC)C(F)(F)F',
+ Silver: '[Ag]',
+ 'Silver Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.[Ag+]',
+ 'Silver(I) Trifluoromethanethiolate': '[S-]C(F)(F)F.[Ag+]',
+ 'Silver(II) picolinate': 'O=C([O-])C1=NC=CC=C1.O=C([O-])C2=NC=CC=C2.[Ag+2]',
+ 'Silver(II) Pyridine-2-carboxylate': 'O=C(C1=NC=CC=C1)[O-].O=C(C2=NC=CC=C2)[O-].[Ag+2]',
+ 'Sodium bicarbonate': 'C(=O)(O)[O-].[Na+]',
+ 'Sodium (Trihydroxy)phenylborate': 'O[B-](O)(O)C1=CC=CC=C1.[Na+]',
+ 'Sodium amide': '[Na+].[NH2-]',
+ NaNH2: '[Na+].[NH2-]',
+ 'Sodium ascorbate': '[O-]C([C@H](O1)[C@H](CO)O)=C(O)C1=O.[Na+]',
+ 'sodium azide': '[N-]=[N+]=[N-].[Na+]',
+ NaN3: '[N-]=[N+]=[N-].[Na+]',
+ 'Sodium Bis(2-methoxyethoxy)aluminum Dihydride': 'COCCO[Al+]OCCOC.[Na+].[H-].[H-]',
+ 'Sodium Bis(trimethylsilyl)amide': 'C[Si]([N-][Si](C)(C)C)(C)C.[Na+]',
+ 'Sodium Borohydride': '[Na+].[BH4-]',
+ NaBH4: '[Na+].[BH4-]',
+ 'sodium bromate': 'O=Br([O-])=O.[Na+]',
+ 'sodium bromide': '[Na+].[Br-]',
+ NaBr: '[Na+].[Br-]',
+ 'Sodium Bromodifluoroacetate': 'O=C([O-])C(F)(Br)F.[Na+]',
+ 'sodium carbonate': '[O-]C([O-])=O.[Na+].[Na+]',
+ Na2CO3: '[O-]C([O-])=O.[Na+].[Na+]',
+ 'Sodium carbonate decahydrate': '[O-]C([O-])=O.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Na+].[Na+]',
+ 'sodium chloride': '[Na+].[Cl-]',
+ NaCl: '[Na+].[Cl-]',
+ 'Sodium Chlorodifluoroacetate': 'O=C([O-])C(F)(Cl)F.[Na+]',
+ 'Sodium Cyanoborohydride': '[BH3-]C#N.[Na+]',
+ 'sodium cycanide': '[C-]#N.[Na+]',
+ NaCN: '[C-]#N.[Na+]',
+ 'sodium D,L lactate': 'OC(C)C([O-])=O.[Na+]',
+ 'Sodium Dichloroisocyanurate': 'ClN1C([N-]C(N(C1=O)Cl)=O)=O.[Na+]',
+ 'Sodium dichloroisocyanurate dihydrate': 'O=C1N=C([O-])N(Cl)C(N1Cl)=O.O.O.[Na+]',
+ 'Sodium dichromate dihydrate': 'O=[Cr]([O-])(O[Cr](=O)([O-])=O)=O.[H]O[H].[H]O[H].[Na+].[Na+]',
+ 'Sodium Diphenylphosphinobenzene-3-sulfonate': 'O=S(C1=CC(P(C2=CC=CC=C2)C3=CC=CC=C3)=CC=C1)([O-])=O.[Na+]',
+ 'Sodium Ethoxide': 'CC[O-].[Na+]',
+ NaOEt: 'CC[O-].[Na+]',
+ 'sodium fluoride': '[Na+].[F-]',
+ NaF: '[Na+].[F-]',
+ 'Sodium hydride': '[NaH]',
+ NaH: '[NaH]',
+ 'sodium hydrogen difluoride': '[Na+].[H+].[F-].[F-]',
+ 'Sodium hydrogen periodate': 'O=I(=O)([O-])=O.O=I(=O)([O-])=O.[Na+].[H+]',
+ 'Sodium Hydroxide': '[Na+].[OH-]',
+ NaOH: '[Na+].[OH-]',
+ 'Sodium Hypochlorite Pentahydrate': 'Cl[O-].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Na+]',
+ 'Sodium iodide': '[Na+].[I-]',
+ NaI: '[Na+].[I-]',
+ 'sodium L-tartrate': 'O[C@H]([C@H](C([O-])=O)O)C([O-])=O.[Na+].[Na+]',
+ 'Sodium Methoxide': 'C[O-].[Na+]',
+ NaOMe: 'C[O-].[Na+]',
+ 'Sodium nitrate': '[N+](=O)([O-])[O-].[Na+]',
+ NaNO3: '[N+](=O)([O-])[O-].[Na+]',
+ 'Sodium percarbonate': 'O=C(O[O-])[O-].[Na+].[Na+]',
+ 'sodium perchlorate': 'O=Cl(=O)([O-])=O.[Na+]',
+ 'Sodium permanganate': 'O=[Mn](=O)([O-])=O.[Na+]',
+ NaMnO4: 'O=[Mn](=O)([O-])=O.[Na+]',
+ 'Sodium peroxide': '[O-][O-].[Na+].[Na+]',
+ Na2O2: '[O-][O-].[Na+].[Na+]',
+ 'sodium persulfate': '[O-]S(=O)(OOS(=O)([O-])=O)=O.[Na+].[Na+]',
+ 'Sodium phosphomolybdate hydrate': 'O=[Mo](OP(O)(O)=O)([O-])=O.[H]O[H].[Na+]',
+ 'sodium sulfite': 'O=S([O-])[O-].[Na+].[Na+]',
+ 'Sodium Tellurite Pentahydrate': 'O=[Te]([O-])[O-].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Na+].[Na+]',
+ 'sodium tetraborate': 'O[B-]12OBO[B-](OBO2)(O)O1.[Na+].[Na+]',
+ 'Sodium Tetrachloropalladate(II)': 'Cl[Pd-2](Cl)(Cl)Cl.[Na+].[Na+]',
+ 'Sodium Tetrafluoroborate': 'F[B-](F)(F)F.[Na+]',
+ 'Sodium Triacetoxyborohydride': 'O=C(O[BH-](OC(C)=O)OC(C)=O)C.[Na+]',
+ 'Sodium Trifluoroacetate': 'O=C([O-])C(F)(F)F.[Na+]',
+ 'Sodium Trifluoromethanesulfinate': 'O=S(C(F)(F)F)[O-].[Na+]',
+ 'Sodium trimethylsilanolate': '[O-][Si](C)(C)C.[Na+]',
+ 'Sodium Tris(1,1,1,3,3,3-hexafluoroisopropoxy)borohydride': 'FC(F)(C(C(F)(F)F)O[BH-](OC(C(F)(F)F)C(F)(F)F)OC(C(F)(F)F)C(F)(F)F)F.[Na+]',
+ 'Sodium tert-Butoxide': 'CC(C)([O-])C.[Na+]',
+ 'Sodium tert-Pentoxide': 'CCC(C)([O-])C.[Na+]',
+ 'Sorbic Acid': 'C/C=C/C=C/C(O)=O',
+ 'Strontium hydroxide': '[Sr+2].[OH-].[OH-]',
+ 'STRONTIUM HYDROXIDE OCTAHYDRATE': '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Sr+2].[OH-].[OH-]',
+ 'Strontium peroxide': '[O-][O-].[Sr+2]',
+ 'Succinic Acid': 'O=C(O)CCC(O)=O',
+ 'Sulfanilic Acid': 'O=S(O)(C1=CC=C(N)C=C1)=O',
+ sulfolane: 'O=S1(CCCC1)=O',
+ 'Sulfur Trioxide': 'O=S(=O)=O',
+ SO3: 'O=S(=O)=O',
+ 'Sulfur Trioxide - Triethylamine Complex': 'O=S(=O)=O.CCN(CC)CC',
+ 'Sulfuric acid': 'O=S(O)(O)=O',
+ H2SO4: 'O=S(O)(O)=O',
+ 'Sulfuryl chloride': 'O=S(Cl)(Cl)=O',
+ SO2Cl2: 'O=S(Cl)(Cl)=O',
+ 'Tebbe reagent': 'C[Al-]1(C[Ti+2][Cl+]1)C.[cH-]1cccc1.[cH-]1cccc1',
+ 'Telluric Acid': 'O=[Te](O)(O)=O',
+ 'Tellurium(IV) Oxide': '[Te+4].[O-2].[O-2]',
+ Terbium: '[Tb]',
+ 'tert-Butyl hydroperoxide': 'CC(C)(OO)C',
+ TBHP: 'CC(C)(OO)C',
+ 'tert-Butyl Hydroperoxide': 'CC(C)(OO)C',
+ 'tert-Butyldimethylsilane': 'C[SiH](C(C)(C)C)C',
+ 'tert-Butyldimethylsilanol': 'O[Si](C)(C(C)(C)C)C',
+ 'tert-Butyldiphenylsilane': 'CC([SiH](C1=CC=CC=C1)C2=CC=CC=C2)(C)C',
+ 'tert-Butyllithium': '[Li]C(C)(C)C',
+ tBuLi: '[Li]C(C)(C)C',
+ 'tert-Butylmagnesium Chloride': 'Cl[Mg]C(C)(C)C',
+ 'tert-Butylmethoxyphenylsilyl Bromide': 'CO[Si](C(C)(C)C)(Br)C1=CC=CC=C1',
+ 'Tetra(decyl)ammonium Bromide': 'CCCCCCCCCC[N+](CCCCCCCCCC)(CCCCCCCCCC)CCCCCCCCCC.[Br-]',
+ Tetraallyltin: 'C=CC[Sn](CC=C)(CC=C)CC=C',
+ 'Tetraamylammonium Bromide': 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[Br-]',
+ 'Tetraamylammonium Chloride': 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[Cl-]',
+ 'Tetraamylammonium Iodide': 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[I-]',
+ Tetrabromofluorescein: 'O=C1OC2(C3=C(OC4=C2C=CC(O)=C4)C=C(O)C=C3)C5=C1C(Br)=C(Br)C(Br)=C5Br',
+ 'Tetrabutyl Orthosilicate': 'CCCCO[Si](OCCCC)(OCCCC)OCCCC',
+ 'Tetrabutyl Orthotitanate': 'CCCCO[Ti](OCCCC)(OCCCC)OCCCC',
+ 'Tetrabutyl Orthotitanate Tetramer': '[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[O-]CCCC.[Ti+4].[Ti+4].[O-2].[O-2].[Ti+4].[O-2].[Ti+4]',
+ 'Tetrabutylammonium (meta)periodate': 'CCCC[N+](CCCC)(CCCC)CCCC.O=I(=O)([O-])=O',
+ 'Tetrabutylammonium Acetate': 'CCCC[N+](CCCC)(CCCC)CCCC.CC([O-])=O',
+ 'Tetrabutylammonium Bifluoride': 'CCCC[N+](CCCC)(CCCC)CCCC.[H]F.[F-]',
+ 'Tetrabutylammonium Borohydride': 'CCCC[N+](CCCC)(CCCC)CCCC.[BH4-]',
+ 'Tetrabutylammonium Bromide': 'CCCC[N+](CCCC)(CCCC)CCCC.[Br-]',
+ 'Tetrabutylammonium Chloride': 'CCCC[N+](CCCC)(CCCC)CCCC.[Cl-]',
+ 'Tetrabutylammonium chlorochromate': 'CCCC[N+](CCCC)(CCCC)CCCC.[O-][Cr](=O)(Cl)=O',
+ 'Tetrabutylammonium Difluorotriphenylstannate': 'CCCC[N+](CCCC)(CCCC)CCCC.F[Sn-](C1=CC=CC=C1)(C2=CC=CC=C2)(F)C3=CC=CC=C3',
+ 'Tetrabutylammonium Dihydrogen Trifluoride': 'CCCC[N+](CCCC)(CCCC)CCCC.[H+].[H+].[F-].[F-].[F-]',
+ 'Tetrabutylammonium ethoxide': 'CCCC[N+](CCCC)(CCCC)CCCC.CC[O-]',
+ 'Tetrabutylammonium Fluoride': 'CCCC[N+](CCCC)(CCCC)CCCC.[F-]',
+ 'Tetrabutylammonium Fluoride Hydrate': 'CCCC[N+](CCCC)(CCCC)CCCC.[H]O[H].[F-]',
+ 'Tetrabutylammonium Hexafluorophosphate': 'CCCC[N+](CCCC)(CCCC)CCCC.F[P-](F)(F)(F)(F)F',
+ 'Tetrabutylammonium Hydrogen Sulfate': 'CCCC[N+](CCCC)(CCCC)CCCC.O=S(O)([O-])=O',
+ 'Tetrabutylammonium hydroxide': 'CCCC[N+](CCCC)(CCCC)CCCC.[OH-]',
+ 'Tetrabutylammonium Iodide': 'CCCC[N+](CCCC)(CCCC)CCCC.[I-]',
+ 'Tetrabutylammonium methoxide': 'CCCC[N+](CCCC)(CCCC)CCCC.C[O-]',
+ 'Tetrabutylammonium Perchlorate': 'CCCC[N+](CCCC)(CCCC)CCCC.O=Cl(=O)([O-])=O',
+ 'Tetrabutylammonium Perrhenate': 'CCCC[N+](CCCC)(CCCC)CCCC.O=[Re](=O)([O-])=O',
+ 'Tetrabutylammonium Tetrafluoroborate': 'CCCC[N+](CCCC)(CCCC)CCCC.F[B-](F)(F)F',
+ 'Tetrabutylammonium Tetraphenylborate': 'CCCC[N+](CCCC)(CCCC)CCCC.C1([B-](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
+ 'Tetrabutylammonium Thiocyanate': 'CCCC[N+](CCCC)(CCCC)CCCC.[S-]C#N',
+ 'Tetrabutylammonium Tribromide': 'CCCC[N+](CCCC)(CCCC)CCCC.[Br-].[Br-].[Br-]',
+ 'Tetrabutylammonium Trifluoromethanesulfonate': 'CCCC[N+](CCCC)(CCCC)CCCC.O=S(C(F)(F)F)([O-])=O',
+ 'Tetrabutylammonium Triiodide': 'CCCC[N+](CCCC)(CCCC)CCCC.[I-].[I-].[I-]',
+ Tetrabutylgermane: 'CCCC[Ge](CCCC)(CCCC)CCCC',
+ 'Tetrabutylphosphonium Bromide': 'CCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
+ 'Tetrabutylphosphonium Chloride': 'CCCC[P+](CCCC)(CCCC)CCCC.[Cl-]',
+ 'Tetrabutylphosphonium Hexafluorophosphate': 'CCCC[P+](CCCC)(CCCC)CCCC.F[P-](F)(F)(F)(F)F',
+ 'Tetrabutylphosphonium Hydroxide': 'CCCC[P+](CCCC)(CCCC)CCCC.[OH-]',
+ 'Tetrabutylphosphonium malonate': 'CCCC[P+](CCCC)(CCCC)CCCC.CCCC[P+](CCCC)(CCCC)CCCC.O=C([O-])CC([O-])=O',
+ 'Tetrabutylphosphonium Tetrafluoroborate': 'CCCC[P+](CCCC)(CCCC)CCCC.F[B-](F)(F)F',
+ Tetrabutyltin: 'CCCC[Sn](CCCC)(CCCC)CCCC',
+ Tetracyanoethylene: 'N#CC(C#N)=C(C#N)C#N',
+ Tetradecamethylcycloheptasiloxane: 'C[Si]1(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O[Si](C)(C)O1',
+ 'Tetradecyltrimethylammonium Bromide': 'C[N+](C)(CCCCCCCCCCCCCC)C.[Br-]',
+ 'Tetraethyl 1,4,8,11-Tetraazacyclotetradecane-1,4,8,11-tetraacetate': 'O=C(OCC)CN1CCN(CC(OCC)=O)CCCN(CC(OCC)=O)CCN(CC(OCC)=O)CCC1',
+ 'Tetraethyl Orthosilicate': 'CCO[Si](OCC)(OCC)OCC',
+ 'Tetraethylammonium Borohydride': 'CC[N+](CC)(CC)CC.[BH4-]',
+ 'Tetraethylammonium Bromide': 'CC[N+](CC)(CC)CC.[Br-]',
+ 'Tetraethylammonium Chloride': 'CC[N+](CC)(CC)CC.[Cl-]',
+ 'Tetraethylammonium Fluoride Tetrahydrofluoride': 'CC[N+](CC)(CC)CC.[H]F.[H]F.[H]F.[H]F.[F-]',
+ 'Tetraethylammonium Fluoride Trihydrofluoride': 'CC[N+](CC)(CC)CC.[H]F.[H]F.[H]F.[F-]',
+ 'Tetraethylammonium Hydroxide': 'CC[N+](CC)(CC)CC.[OH-]',
+ 'Tetraethylammonium Iodide': 'CC[N+](CC)(CC)CC.[I-]',
+ 'Tetraethylammonium Nitrate': 'CC[N+](CC)(CC)CC.[O-][N+]([O-])=O',
+ 'Tetraethylammonium Tetrafluoroborate': 'CC[N+](CC)(CC)CC.F[B-](F)(F)F',
+ 'Tetraethylammonium Trifluoromethanesulfonate': 'CC[N+](CC)(CC)CC.O=S(C(F)(F)F)([O-])=O',
+ 'Tetraethylammonium p-Toluenesulfonate': 'CC[N+](CC)(CC)CC.CC1=CC=C(S(=O)([O-])=O)C=C1',
+ Tetraethylgermane: 'CC[Ge](CC)(CC)CC',
+ 'Tetraethylphosphonium Bromide': 'CC[P+](CC)(CC)CC.[Br-]',
+ 'Tetraethylphosphonium Hexafluorophosphate': 'CC[P+](CC)(CC)CC.F[P-](F)(F)(F)(F)F',
+ 'Tetraethylphosphonium Tetrafluoroborate': 'CC[P+](CC)(CC)CC.F[B-](F)(F)F',
+ Tetraethylsilane: 'CC[Si](CC)(CC)CC',
+ 'Tetrafluoroboronic acid diethylether complex': 'F[B-](F)(F)F.CCOCC.[H+]',
+ 'Tetraheptylammonium Bromide': 'CCCCCCC[N+](CCCCCCC)(CCCCCCC)CCCCCCC.[Br-]',
+ 'Tetraheptylammonium Iodide': 'CCCCCCC[N+](CCCCCCC)(CCCCCCC)CCCCCCC.[I-]',
+ 'Tetrahexylammonium Bromide': 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.[Br-]',
+ 'Tetrahexylammonium Hydrogen Sulfate': 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.O=S(O)([O-])=O',
+ 'Tetrahexylammonium Hydroxide': 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.[OH-]',
+ 'Tetrahexylammonium Iodide': 'CCCCCC[N+](CCCCCC)(CCCCCC)CCCCCC.[I-]',
+ Tetrahydroxydiboron: 'OB(O)B(O)O',
+ tetrahydroxytitanium: 'O[Ti](O)(O)O',
+ 'Tetraisobutyl Orthotitanate': 'CC(C)CO[Ti](OCC(C)C)(OCC(C)C)OCC(C)C',
+ 'Tetraisopropyl Orthosilicate': 'CC(O[Si](OC(C)C)(OC(C)C)OC(C)C)C',
+ 'Tetraisopropyl Orthotitanate': 'CC(O[Ti](OC(C)C)(OC(C)C)OC(C)C)C',
+ 'Tetrakis(2,4-pentanedionato)titanium(IV)': '[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[O-]CCC.[O-]CCC.[Ti+4]',
+ 'Tetrakis(acetonitrile)copper(I) Hexafluorophosphate': 'CC#N.CC#N.CC#N.CC#N.F[P-](F)(F)(F)(F)F.[Cu+]',
+ 'Tetrakis(acetonitrile)copper(I) Tetrafluoroborate': 'CC#N.CC#N.CC#N.CC#N.F[B-](F)(F)F.[Cu+]',
+ 'Tetrakis(acetonitrile)palladium(II) Bis(trifluoromethanesulfonate)': 'CC#N.CC#N.CC#N.CC#N.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Pd+2]',
+ 'Tetrakis(decyl)ammonium hydroxide': 'CCCCCCCCCC[N+](CCCCCCCCCC)(CCCCCCCCCC)CCCCCCCCCC.[OH-]',
+ 'Tetrakis(dimethylamino)titanium(IV)': 'CN([Ti](N(C)C)(N(C)C)N(C)C)C',
+ 'Tetrakis(dimethylsilyl)silane': 'C[SiH]([Si]([SiH](C)C)([SiH](C)C)[SiH](C)C)C',
+ 'Tetrakis(dimethylsilyloxy)silane': 'C[SiH](O[Si](O[SiH](C)C)(O[SiH](C)C)O[SiH](C)C)C',
+ 'Tetrakis(hydroxymethyl)phosphonium Chloride': 'OC[P+](CO)(CO)CO.[Cl-]',
+ 'Tetrakis(hydroxymethyl)phosphonium Sulfate': 'OC[P+](CO)(CO)CO.OC[P+](CO)(CO)CO.O=S([O-])([O-])=O',
+ 'Tetrakis(trimethylsilyl)silane': 'C[Si]([Si]([Si](C)(C)C)([Si](C)(C)C)[Si](C)(C)C)(C)C',
+ 'Tetrakis(triphenylphosphine)palladium(0)': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.P(C%10=CC=CC=C%10)(C%11=CC=CC=C%11)C%12=CC=CC=C%12.[Pd]',
+ Tetrakis: 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.P(C%10=CC=CC=C%10)(C%11=CC=CC=C%11)C%12=CC=CC=C%12.[Pd]',
+ 'Pd(Ph3)4': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.P(C%10=CC=CC=C%10)(C%11=CC=CC=C%11)C%12=CC=CC=C%12.[Pd]',
+ 'Tetrakis[dimethyl(vinyl)silyl] Orthosilicate': 'C=C[Si](O[Si](O[Si](C)(C)C=C)(O[Si](C)(C)C=C)O[Si](C)(C)C=C)(C)C',
+ 'Tetramethylammonium Acetate': 'C[N+](C)(C)C.CC([O-])=O',
+ 'Tetramethylammonium Borohydride': 'C[N+](C)(C)C.[BH4-]',
+ 'Tetramethylammonium Bromide': 'C[N+](C)(C)C.[Br-]',
+ 'Tetramethylammonium Chloride': 'C[N+](C)(C)C.[Cl-]',
+ 'Tetramethylammonium Dichloroiodate': 'C[N+](C)(C)C.Cl[I-]Cl',
+ 'Tetramethylammonium Fluoride Tetrahydrate': 'C[N+](C)(C)C.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[F-]',
+ 'Tetramethylammonium Hexafluorophosphate': 'C[N+](C)(C)C.F[P-](F)(F)(F)(F)F',
+ 'Tetramethylammonium Hydroxide': 'C[N+](C)(C)C.[OH-]',
+ 'Tetramethylammonium Iodide': 'C[N+](C)(C)C.[I-]',
+ 'Tetramethylammonium Sulfate': 'C[N+](C)(C)C.C[N+](C)(C)C.O=S([O-])([O-])=O',
+ 'Tetramethylammonium Tetrafluoroborate': 'C[N+](C)(C)C.F[B-](F)(F)F',
+ 'Tetramethylammonium Triacetoxyborohydride': 'C[N+](C)(C)C.O=C(O[BH-](OC(C)=O)OC(C)=O)C',
+ 'Tetramethylethylenediamine (TMEDA)': 'CN(C)CCN(C)C',
+ Tetramethylgermane: 'C[Ge](C)(C)C',
+ Tetramethylsilane: 'C[Si](C)(C)C',
+ TMS: 'C[Si](C)(C)C',
+ 'Tetra-n-octylammonium Bromide': 'CCCCCCCC[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[Br-]',
+ 'Tetra-n-octylammonium Iodide': 'CCCCCCCC[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[I-]',
+ 'Tetra-n-octylphosphonium Bromide': 'CCCCCCCC[P+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[Br-]',
+ 'Tetraoctylammonium hydroxide': 'CCCCCCCC[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[OH-]',
+ 'Tetrapentylammonium hydroxide': 'CCCCC[N+](CCCCC)(CCCCC)CCCCC.[OH-]',
+ 'Tetraphenyl Lead': 'C1([Pb](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
+ 'Tetraphenylarsonium Chloride Hydrochloride Hydrate': '[H]O[H].[H]Cl.C1([As+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1.[Cl-]',
+ Tetraphenylcyclopentadienone: 'O=C1C(C2=CC=CC=C2)=C(C3=CC=CC=C3)C(C4=CC=CC=C4)=C1C5=CC=CC=C5',
+ Tetraphenylgermane: 'C1([Ge](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
+ 'Tetraphenylphosphonium Bromide': 'C1([P+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1.[Br-]',
+ 'Tetraphenylphosphonium Chloride': 'C1([P+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1.[Cl-]',
+ Tetraphenylporphyrin: 'C1(C2=CC=CC=C2)=C3C=CC(C(C4=CC=CC=C4)=C5C=CC(N5)=C(C6=CC=CC=C6)C(C=C7)=NC7=C(C8=CC=CC=C8)C9=CC=C1N9)=N3',
+ Tetraphenylsilane: 'C1([Si](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
+ Tetraphenyltin: 'C1([Sn](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)=CC=CC=C1',
+ 'Tetrapropyl Orthosilicate': 'CCCO[Si](OCCC)(OCCC)OCCC',
+ 'Tetrapropylammonium Bromide': 'CCC[N+](CCC)(CCC)CCC.[Br-]',
+ 'Tetrapropylammonium Chloride': 'CCC[N+](CCC)(CCC)CCC.[Cl-]',
+ 'Tetrapropylammonium Hydroxide': 'CCC[N+](CCC)(CCC)CCC.[OH-]',
+ 'Tetrapropylammonium Iodide': 'CCC[N+](CCC)(CCC)CCC.[I-]',
+ 'Tetrapropylammonium Perruthenate': 'CCC[N+](CCC)(CCC)CCC.O=[Ru](=O)([O-])=O',
+ 'Thallium(III) Trifluoroacetate': 'O=C([O-])C(F)(F)F.O=C([O-])C(F)(F)F.O=C([O-])C(F)(F)F.[Tl+3]',
+ THF: 'C1CCCO1',
+ 'Thioacetic Acid': 'CC(O)=S',
+ 'Thioglycolic Acid': 'SCC(O)=O',
+ 'Thionyl Chloride': 'O=S(Cl)Cl',
+ 'Thiophosphoryl Chloride': 'OP(O)(Cl)=S',
+ Thulium: '[Tm]',
+ 'Thulium(III) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Tm+3]',
+ 'tin hydroxide': '[Sn+4].[OH-].[OH-].[OH-].[OH-]',
+ 'Tin(II) 2-Ethylhexanoate': 'CCCCC(CC)C([O-])=O.CCCCC(CC)C([O-])=O.[Sn+2]',
+ 'Tin(II) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Sn+2]',
+ 'Tin(IV) Chloride': '[Sn+4].[Cl-].[Cl-].[Cl-].[Cl-]',
+ Titanium: '[Ti]',
+ 'titanium hydroxide': '[Ti+4].[OH-].[OH-].[OH-].[OH-]',
+ 'Titanium(IV) Chloride': '[Ti+4].[Cl-].[Cl-].[Cl-].[Cl-]',
+ 'TMS-Imidazole (=N-Trimethylsilylimidazole)': 'C[Si](N1C=NC=C1)(C)C',
+ toluene: 'CC1=CC=CC=C1',
+ 'trans,trans-1,5-Bis(4-fluorophenyl)-1,4-pentadien-3-one': 'O=C(/C=C/C1=CC=C(F)C=C1)/C=C/C2=CC=C(F)C=C2',
+ 'trans,trans-1,5-Bis(4-methoxyphenyl)-1,4-pentadien-3-one': 'O=C(/C=C/C1=CC=C(OC)C=C1)/C=C/C2=CC=C(OC)C=C2',
+ 'trans,trans-1,5-Bis[4-(trifluoromethyl)phenyl]-1,4-pentadien-3-one': 'O=C(/C=C/C1=CC=C(C(F)(F)F)C=C1)/C=C/C2=CC=C(C(F)(F)F)C=C2',
+ 'trans,trans-1,5-Diphenyl-1,4-pentadien-3-one': 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2',
+ 'trans-1,2-Bis(diphenylphosphino)ethylene': 'P(/C=C/P(C1=CC=CC=C1)C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4',
+ 'trans-2,6-Diisopropyl-N-(2-pyridylmethylene)aniline': 'CC(C1=C(C(C(C)C)=CC=C1)/N=C/C2=NC=CC=C2)C',
+ 'trans-2-Butene-1,4-bis(triphenylphosphonium Chloride)': 'C1([P+](C/C=C/C[P+](C2=CC=CC=C2)(C3=CC=CC=C3)C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6)=CC=CC=C1.[Cl-].[Cl-]',
+ 'trans-4-(tert-Butyldiphenylsilyloxy)-L-proline': 'O=C(O)[C@H]1NC[C@H](O[Si](C2=CC=CC=C2)(C(C)(C)C)C3=CC=CC=C3)C1',
+ 'trans-4-Fluoro-L-proline': 'O=C(O)[C@H]1NC[C@H](F)C1',
+ 'Tri(2-furyl)phosphine': 'P(C1=CC=CO1)(C2=CC=CO2)C3=CC=CO3',
+ 'Tri(2-thienyl)phosphine': 'P(C1=CC=CS1)(C2=CC=CS2)C3=CC=CS3',
+ 'Tri(cyclohexa-2,5-dien-1-yl)silane': '[SiH](C1C=CCC=C1)(C2C=CCC=C2)C3C=CCC=C3',
+ 'Tri(m-tolyl)phosphine': 'CC1=CC(P(C2=CC=CC(C)=C2)C3=CC=CC(C)=C3)=CC=C1',
+ 'Tri(o-tolyl)phosphine': 'CC1=CC=CC=C1P(C2=CC=CC=C2C)C3=CC=CC=C3C',
+ 'Tri(p-tolyl)phosphine': 'CC1=CC=C(P(C2=CC=C(C)C=C2)C3=CC=C(C)C=C3)C=C1',
+ Triacetoxyborohydride: 'O=C(O[BH-](OC(C)=O)OC(C)=O)C',
+ Triacetoxyethylsilane: 'CC[Si](OC(C)=O)(OC(C)=O)OC(C)=O',
+ 'Triallyl(methyl)silane': 'C[Si](CC=C)(CC=C)CC=C',
+ 'Triallyl(phenyl)silane': 'C=CC[Si](CC=C)(CC=C)C1=CC=CC=C1',
+ Tribenzylsilane: '[SiH](CC1=CC=CC=C1)(CC2=CC=CC=C2)CC3=CC=CC=C3',
+ 'Tribromoacetic Acid': 'O=C(O)C(Br)(Br)Br',
+ 'Tributyl borate': 'B(OCCCC)(OCCCC)OCCCC',
+ 'Tributyl(2-methoxyethyl)phosphonium Bis(trifluoromethanesulfonyl)imide': 'CCCC[P+](CCCC)(CCCC)CCOC.FC(F)(S([N-]S(C(F)(F)F)(=O)=O)(=O)=O)F',
+ 'Tributyl(cyanomethyl)phosphonium Chloride': 'N#CC[P+](CCCC)(CCCC)CCCC.[Cl-]',
+ 'Tributyl(ethyl)phosphonium Diethyl Phosphate': 'CC[P+](CCCC)(CCCC)CCCC.O=P(OCC)([O-])OCC',
+ 'Tributyl(methyl)ammonium Dicyanamide': '[H]C(C([H])([H])C([H])([H])C([H])([H])[H])([H])[N+](C([H])([H])C([H])([H])C([H])([H])C([H])([H])[H])(C([H])([H])[H])C([H])([H])C([H])([H])C([H])([H])C([H])([H])[H].[N-]=C=NC#N',
+ Tributylamine: 'CCCCN(CCCC)CCCC',
+ Tributylchlorosilane: 'Cl[Si](CCCC)(CCCC)CCCC',
+ 'Tributyldodecylphosphonium Bromide': 'CCCCCCCCCCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
+ 'Tributylhexadecylphosphonium Bromide': 'CCCCCCCCCCCCCCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
+ 'Tributylmethylammonium Bis(trifluoromethanesulfonyl)imide': 'FC(F)(S([N-]S(C(F)(F)F)(=O)=O)(=O)=O)F.C[N+](CCCC)(CCCC)CCCC',
+ 'Tributylmethylammonium Chloride': 'C[N+](CCCC)(CCCC)CCCC.[Cl-]',
+ 'Tributylmethylphosphonium Bis(trifluoromethanesulfonyl)imide': 'C[P+](CCCC)(CCCC)CCCC.FC(F)(S([N-]S(C(F)(F)F)(=O)=O)(=O)=O)F',
+ 'Tributylmethylphosphonium Iodide': 'C[P+](CCCC)(CCCC)CCCC.[I-]',
+ 'Tributyl-n-octylphosphonium Bromide': 'CCCCCCCC[P+](CCCC)(CCCC)CCCC.[Br-]',
+ 'Tributylphosphine Oxide': 'CCCCP(CCCC)(CCCC)=O',
+ Tributylsilane: 'CCCC[SiH](CCCC)CCCC',
+ 'Tributylsulfonium Iodide': 'CCCC[S+](CCCC)CCCC.[I-]',
+ 'Tricarbonyl(cyclooctatetraene)iron': '[C]=O.[C]=O.[C]=O.[Fe].C1=C\\C=C/C=C\\C=C/1',
+ 'Trichloro(3,3,3-trifluoropropyl)silane': 'FC(F)(F)CC[Si](Cl)(Cl)Cl',
+ 'Trichloro-2-cyanoethylsilane': 'N#CCC[Si](Cl)(Cl)Cl',
+ 'Trichloroacetic Acid': 'O=C(O)C(Cl)(Cl)Cl',
+ Trichlorocyclopentylsilane: 'Cl[Si](Cl)(Cl)C1CCCC1',
+ 'Trichloroisocyanuric Acid': 'O=C(N(Cl)C(N1Cl)=O)N(Cl)C1=O',
+ 'Trichloromethanesulfonyl Chloride': 'O=S(C(Cl)(Cl)Cl)(Cl)=O',
+ Tricyclohexylphosphine: 'P(C1CCCCC1)(C2CCCCC2)C3CCCCC3',
+ 'Tricyclohexylphosphonium Tetrafluoroborate': 'F[B-](F)(F)F.[PH+](C1CCCCC1)(C2CCCCC2)C3CCCCC3',
+ 'Triethoxy(3-glycidyloxypropyl)silane': 'CCO[Si](OCC)(OCC)CCCOCC1CO1',
+ 'Triethoxy(pentafluorophenyl)silane': 'FC1=C(F)C(F)=C(F)C(F)=C1[Si](OCC)(OCC)OCC',
+ 'Triethoxy(propyl)silane': 'CCC[Si](OCC)(OCC)OCC',
+ 'Triethoxy[2-(7-oxabicyclo[4.1.0]heptan-3-yl)ethyl]silane': 'CCO[Si](OCC)(OCC)CCC1CC2OC2CC1',
+ 'Triethoxy-1H,1H,2H,2H-tridecafluoro-n-octylsilane': 'F[SiH2]C(F)(F)CC(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(OCC)(OCC)OCC',
+ Triethoxyethylsilane: 'CC[Si](OCC)(OCC)OCC',
+ Triethoxyfluorosilane: 'F[Si](OCC)(OCC)OCC',
+ Triethoxymethylsilane: 'C[Si](OCC)(OCC)OCC',
+ 'Triethoxy-n-octylsilane': 'CCCCCCCC[Si](OCC)(OCC)OCC',
+ Triethoxyphenylsilane: 'CCO[Si](OCC)(OCC)C1=CC=CC=C1',
+ Triethoxyvinylsilane: 'C=C[Si](OCC)(OCC)OCC',
+ 'Triethyl 2-Fluoro-2-phosphonoacetate': 'O=C(OCC)C(F)P(OCC)(OCC)=O',
+ 'Triethyl(trifluoromethyl)silane': 'FC([Si](CC)(CC)CC)(F)F',
+ Triethylamine: 'CCN(CC)CC',
+ 'Triethylamine Borane': 'CCN(CC)CC.B',
+ 'Triethylamine Trihydrofluoride': 'CCN(CC)CC.[H]F.[H]F.[H]F',
+ Triethylchlorogermane: 'Cl[Ge](CC)(CC)CC',
+ Triethylenetetramine: 'NCCNCCNCCN',
+ 'Triethylmethylammonium Chloride': 'C[N+](CC)(CC)CC.[Cl-]',
+ 'Triethylmethylammonium hydroxide': 'C[N+](CC)(CC)CC.[OH-]',
+ 'Triethylphenylammonium Chloride': 'CC[N+](CC)(CC)C1=CC=CC=C1.[Cl-]',
+ Triethylsilane: 'CC[SiH](CC)CC',
+ TES: 'CC[SiH](CC)CC',
+ Triethylsilanol: 'O[Si](CC)(CC)CC',
+ Triethylsilylacetylene: 'C#C[Si](CC)(CC)CC',
+ 'Triethylsulfonium Bis(trifluoromethanesulfonyl)imide': 'O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O.CC[S+](CC)CC',
+ Triethylvinylsilane: 'C=C[Si](CC)(CC)CC',
+ 'Trifluoroacetic Acid': 'O=C(O)C(F)(F)F',
+ TFA: 'O=C(O)C(F)(F)F',
+ 'Trifluoroacetic Anhydride': 'O=C(OC(C(F)(F)F)=O)C(F)(F)F',
+ TFAA: 'O=C(OC(C(F)(F)F)=O)C(F)(F)F',
+ 'Trifluoroacetyl Triflate': 'O=S(OC(C(F)(F)F)=O)(C(F)(F)F)=O',
+ Trifluoroacetylacetone: 'O=C(CC(C)=O)C(F)(F)F',
+ 'Trifluoroboronic acid diethyletherate': 'FB(F)F.CCOCC',
+ Trifluoromethanesulfonanilide: 'O=S(C(F)(F)F)(NC1=CC=CC=C1)=O',
+ 'Trifluoromethanesulfonic Acid': 'O=S(C(F)(F)F)(O)=O',
+ 'Trifluoromethanesulfonic Anhydride': 'O=S(C(F)(F)F)(OS(C(F)(F)F)(=O)=O)=O',
+ 'Trifluoromethanesulfonyl Chloride': 'O=S(C(F)(F)F)(Cl)=O',
+ 'Trihexyl(tetradecyl)phosphonium Chloride': 'CCCCCCCCCCCCCC[P+](CCCCCC)(CCCCCC)CCCCCC.[Cl-]',
+ 'Trihexyl(tetradecyl)phosphonium Dicyanamide': 'CCCCCC[P+](CCCCCC)(CCCCCC)CCCCCCCCCCCCCC.N#C[N-]C#N',
+ Trihexylphosphine: 'CCCCCCP(CCCCCC)CCCCCC',
+ Trihexylsilane: 'CCCCCC[SiH](CCCCCC)CCCCCC',
+ 'Triisopropyl[(trimethylsilyl)ethynyl]silane': 'C[Si](C#C[Si](C(C)C)(C(C)C)C(C)C)(C)C',
+ Triisopropylsilane: 'CC([SiH](C(C)C)C(C)C)C',
+ Triisopropylsilylacetylene: 'C#C[Si](C(C)C)(C(C)C)C(C)C',
+ 'Trimagnesium Dicitrate Nonahydrate': 'OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.OC(C([O-])=O)(CC([O-])=O)CC([O-])=O.[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[Mg+2].[Mg+2].[Mg+2]',
+ 'Trimethoxy(1H,1H,2H,2H-tridecafluoro-n-octyl)silane': 'FC(C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F)(F)CC[Si](OC)(OC)OC',
+ 'Trimethoxy(2-phenylethyl)silane': 'CO[Si](OC)(OC)CCC1=CC=CC=C1',
+ 'Trimethoxy(3,3,3-trifluoropropyl)silane': 'FC(F)(F)CC[Si](OC)(OC)OC',
+ 'Trimethoxy(4-methoxyphenyl)silane': 'COC1=CC=C([Si](OC)(OC)OC)C=C1',
+ 'Trimethoxy(methyl)silane': 'C[Si](OC)(OC)OC',
+ 'Trimethoxy(phenylethyl)silane': 'CO[Si](OC)(OC)CCC1=CC=CC=C1',
+ 'Trimethoxy(propyl)silane': 'CCC[Si](OC)(OC)OC',
+ 'Trimethoxy[3-(methylamino)propyl]silane': 'CNCCC[Si](OC)(OC)OC',
+ 'Trimethoxy[3-(phenylamino)propyl]silane': 'CO[Si](OC)(OC)CCCNC1=CC=CC=C1',
+ 'Trimethoxy-n-octylsilane': 'CCCCCCCC[Si](OC)(OC)OC',
+ Trimethoxyphenylsilane: 'CO[Si](OC)(OC)C1=CC=CC=C1',
"Trimethyl 2,2':6',2''-Terpyridine-4,4',4''-tricarboxylate": 'O=C(C1=CC(C2=NC(C3=NC=CC(C(OC)=O)=C3)=CC(C(OC)=O)=C2)=NC=C1)OC',
- "Trimethyl(2-pyridyl)tin": 'C[Sn](C)(C)C1=NC=CC=C1',
- "Trimethyl(4-pyridyl)tin": 'C[Sn](C)(C)C1=CC=NC=C1',
- "Trimethyl(heptafluoropropyl)silane": 'FC([Si](C)(C)C)(F)C(F)(F)C(F)(F)F',
- "Trimethyl(nonafluorobutyl)silane": 'FC([Si](C)(C)C)(F)C(F)(F)C(F)(F)C(F)(F)F',
- "Trimethyl(pentafluoroethyl)silane": 'FC([Si](C)(C)C)(F)C(F)(F)F',
- "Trimethyl(pentafluorophenyl)silane": 'FC1=C(F)C(F)=C(F)C(F)=C1[Si](C)(C)C',
- "Trimethyl(tridecafluorohexyl)silane": 'FC([Si](C)(C)C)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F',
- "Trimethyl[2-[(trimethylsilyl)methyl]benzyl]ammonium Iodide": 'C[Si](CC1=CC=CC=C1C[N+](C)(C)C)(C)C.[I-]',
- "Trimethyl[3-(trimethoxysilyl)propyl]ammonium Chloride": 'CO[Si](CCC[N+](C)(C)C)(OC)OC.[Cl-]',
- "Trimethylamine Borane": 'CN(C)C.B',
- "Trimethylamine N-Oxide": 'C[N+](C)([O-])C',
- "Trimethylamine N-Oxide Dihydrate": 'C[N+](C)([O-])C.[H]O[H].[H]O[H]',
- "Trimethylchlorogermane": 'Cl[Ge](C)(C)C',
- "Trimethylethoxysilane": 'CCO[Si](C)(C)C',
- "Trimethylnonylammonium Bromide": 'CCCCCCCCC[N+](C)(C)C.[Br-]',
- "Trimethylphenylammonium Bromide": 'C[N+](C)(C)C1=CC=CC=C1.[Br-]',
- "Trimethylphenylammonium Chloride": 'C[N+](C)(C)C1=CC=CC=C1.[Cl-]',
- "Trimethylphenylammonium Hydroxide": 'C[N+](C)(C)C1=CC=CC=C1.[OH-]',
- "Trimethylphenylammonium Tribromide": 'C[N+](C)(C)C1=CC=CC=C1.[Br-].[Br-].[Br-]',
- "Trimethylphenylsilane": 'C[Si](C)(C)C1=CC=CC=C1',
- "Trimethylphosphine": 'CP(C)C',
- "Trimethylpropylammonium Bis(trifluoromethanesulfonyl)imide": 'CCC[N+](C)(C)C.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
- "Trimethylpropylammonium Bromide": 'CCC[N+](C)(C)C.[Br-]',
- "Trimethylsilyl Chloride": 'C[Si](C)(Cl)C',
- "TMSCl": 'C[Si](C)(Cl)C',
- "TMS-chloride": 'C[Si](C)(Cl)C',
- "Trimethylsilyl Azide": 'C[Si](C)(N=[N+]=[N-])C',
- "TMS-Azide": 'C[Si](C)(N=[N+]=[N-])C',
- "TMSA": 'C[Si](C)(N=[N+]=[N-])C',
- "TMSN3": 'C[Si](C)(N=[N+]=[N-])C',
- "Trimethylsilyl Acetate": 'CC(O[Si](C)(C)C)=O',
- "Trimethylsilyl Difluoro(fluorosulfonyl)acetate": 'O=C(O[Si](C)(C)C)C(F)(F)S(=O)(F)=O',
- "Trimethylsilyl Propionate": 'CCC(O[Si](C)(C)C)=O',
- "Trimethylsilyl Trifluoroacetate": 'O=C(O[Si](C)(C)C)C(F)(F)F',
- "Trimethylsilylacetylene": 'C#C[Si](C)(C)C',
- "Trimethylsilylcyclopentadiene": 'C[Si](C1=CC=CC1)(C)C',
- "Trimethylsilylketene Ethyl Trimethylsilyl Acetal": 'C[Si](/C=C(OCC)/O[Si](C)(C)C)(C)C',
- "Trimethylsilylmethylmagnesium Chloride": 'Cl[Mg]C[Si](C)(C)C',
- "Trimethylstearylammonium Bromide": 'CCCCCCCCCCCCCCCCCC[N+](C)(C)C.[Br-]',
- "Trimethylsulfonium Iodide": 'C[S+](C)C.[I-]',
- "Trimethyltetradecylammonium Chloride": 'CCCCCCCCCCCCCC[N+](C)(C)C.[Cl-]',
- "Trimethyltin Chloride": 'C[Sn](C)(Cl)C',
- "Tri-n-octylphosphine": 'CCCCCCCCP(CCCCCCCC)CCCCCCCC',
- "Tri-n-octylphosphine Oxide": 'CCCCCCCCP(CCCCCCCC)(CCCCCCCC)=O',
- "Trioctylmethylammonium Chloride": 'C[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[Cl-]',
- "Triphenyl Phosphite": 'P(OC1=CC=CC=C1)(OC2=CC=CC=C2)OC3=CC=CC=C3',
- "Triphenylantimony": '[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylantimony Diacetate": 'CC(O)=O.CC(O)=O.[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylantimony Dichloride": 'Cl[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)(Cl)C3=CC=CC=C3',
- "Triphenylantimony Oxide": 'O=[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylarsine": '[As](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylchlorogermane": 'Cl[Ge](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylphosphine": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylphosphine Borane": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.B',
- "Triphenylphosphine Oxide": 'O=P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylphosphine Selenide": '[Se]=P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylsilane": '[SiH](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylsilanol": 'O[Si](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphenylvinylsilane": 'C=C[Si](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
- "Triphosgene": 'ClC(Cl)(OC(OC(Cl)(Cl)Cl)=O)Cl',
- "Tris(1-pyrazolyl)methane": 'C(N1N=CC=C1)(N2N=CC=C2)N3N=CC=C3',
+ 'Trimethyl(2-pyridyl)tin': 'C[Sn](C)(C)C1=NC=CC=C1',
+ 'Trimethyl(4-pyridyl)tin': 'C[Sn](C)(C)C1=CC=NC=C1',
+ 'Trimethyl(heptafluoropropyl)silane': 'FC([Si](C)(C)C)(F)C(F)(F)C(F)(F)F',
+ 'Trimethyl(nonafluorobutyl)silane': 'FC([Si](C)(C)C)(F)C(F)(F)C(F)(F)C(F)(F)F',
+ 'Trimethyl(pentafluoroethyl)silane': 'FC([Si](C)(C)C)(F)C(F)(F)F',
+ 'Trimethyl(pentafluorophenyl)silane': 'FC1=C(F)C(F)=C(F)C(F)=C1[Si](C)(C)C',
+ 'Trimethyl(tridecafluorohexyl)silane': 'FC([Si](C)(C)C)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F',
+ 'Trimethyl[2-[(trimethylsilyl)methyl]benzyl]ammonium Iodide': 'C[Si](CC1=CC=CC=C1C[N+](C)(C)C)(C)C.[I-]',
+ 'Trimethyl[3-(trimethoxysilyl)propyl]ammonium Chloride': 'CO[Si](CCC[N+](C)(C)C)(OC)OC.[Cl-]',
+ 'Trimethylamine Borane': 'CN(C)C.B',
+ 'Trimethylamine N-Oxide': 'C[N+](C)([O-])C',
+ 'Trimethylamine N-Oxide Dihydrate': 'C[N+](C)([O-])C.[H]O[H].[H]O[H]',
+ Trimethylchlorogermane: 'Cl[Ge](C)(C)C',
+ Trimethylethoxysilane: 'CCO[Si](C)(C)C',
+ 'Trimethylnonylammonium Bromide': 'CCCCCCCCC[N+](C)(C)C.[Br-]',
+ 'Trimethylphenylammonium Bromide': 'C[N+](C)(C)C1=CC=CC=C1.[Br-]',
+ 'Trimethylphenylammonium Chloride': 'C[N+](C)(C)C1=CC=CC=C1.[Cl-]',
+ 'Trimethylphenylammonium Hydroxide': 'C[N+](C)(C)C1=CC=CC=C1.[OH-]',
+ 'Trimethylphenylammonium Tribromide': 'C[N+](C)(C)C1=CC=CC=C1.[Br-].[Br-].[Br-]',
+ Trimethylphenylsilane: 'C[Si](C)(C)C1=CC=CC=C1',
+ Trimethylphosphine: 'CP(C)C',
+ 'Trimethylpropylammonium Bis(trifluoromethanesulfonyl)imide': 'CCC[N+](C)(C)C.O=S([N-]S(C(F)(F)F)(=O)=O)(C(F)(F)F)=O',
+ 'Trimethylpropylammonium Bromide': 'CCC[N+](C)(C)C.[Br-]',
+ 'Trimethylsilyl Chloride': 'C[Si](C)(Cl)C',
+ TMSCl: 'C[Si](C)(Cl)C',
+ 'TMS-chloride': 'C[Si](C)(Cl)C',
+ 'Trimethylsilyl Azide': 'C[Si](C)(N=[N+]=[N-])C',
+ 'TMS-Azide': 'C[Si](C)(N=[N+]=[N-])C',
+ TMSA: 'C[Si](C)(N=[N+]=[N-])C',
+ TMSN3: 'C[Si](C)(N=[N+]=[N-])C',
+ 'Trimethylsilyl Acetate': 'CC(O[Si](C)(C)C)=O',
+ 'Trimethylsilyl Difluoro(fluorosulfonyl)acetate': 'O=C(O[Si](C)(C)C)C(F)(F)S(=O)(F)=O',
+ 'Trimethylsilyl Propionate': 'CCC(O[Si](C)(C)C)=O',
+ 'Trimethylsilyl Trifluoroacetate': 'O=C(O[Si](C)(C)C)C(F)(F)F',
+ Trimethylsilylacetylene: 'C#C[Si](C)(C)C',
+ Trimethylsilylcyclopentadiene: 'C[Si](C1=CC=CC1)(C)C',
+ 'Trimethylsilylketene Ethyl Trimethylsilyl Acetal': 'C[Si](/C=C(OCC)/O[Si](C)(C)C)(C)C',
+ 'Trimethylsilylmethylmagnesium Chloride': 'Cl[Mg]C[Si](C)(C)C',
+ 'Trimethylstearylammonium Bromide': 'CCCCCCCCCCCCCCCCCC[N+](C)(C)C.[Br-]',
+ 'Trimethylsulfonium Iodide': 'C[S+](C)C.[I-]',
+ 'Trimethyltetradecylammonium Chloride': 'CCCCCCCCCCCCCC[N+](C)(C)C.[Cl-]',
+ 'Trimethyltin Chloride': 'C[Sn](C)(Cl)C',
+ 'Tri-n-octylphosphine': 'CCCCCCCCP(CCCCCCCC)CCCCCCCC',
+ 'Tri-n-octylphosphine Oxide': 'CCCCCCCCP(CCCCCCCC)(CCCCCCCC)=O',
+ 'Trioctylmethylammonium Chloride': 'C[N+](CCCCCCCC)(CCCCCCCC)CCCCCCCC.[Cl-]',
+ 'Triphenyl Phosphite': 'P(OC1=CC=CC=C1)(OC2=CC=CC=C2)OC3=CC=CC=C3',
+ Triphenylantimony: '[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ 'Triphenylantimony Diacetate': 'CC(O)=O.CC(O)=O.[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ 'Triphenylantimony Dichloride': 'Cl[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)(Cl)C3=CC=CC=C3',
+ 'Triphenylantimony Oxide': 'O=[Sb](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphenylarsine: '[As](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphenylchlorogermane: 'Cl[Ge](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphenylphosphine: 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ 'Triphenylphosphine Borane': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.B',
+ 'Triphenylphosphine Oxide': 'O=P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ 'Triphenylphosphine Selenide': '[Se]=P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphenylsilane: '[SiH](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphenylsilanol: 'O[Si](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphenylvinylsilane: 'C=C[Si](C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3',
+ Triphosgene: 'ClC(Cl)(OC(OC(Cl)(Cl)Cl)=O)Cl',
+ 'Tris(1-pyrazolyl)methane': 'C(N1N=CC=C1)(N2N=CC=C2)N3N=CC=C3',
"Tris(2,2'-bipyridyl)ruthenium(II) Chloride Hexahydrate": '[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].[H]O[H].C1(C2=NC=CC=C2)=NC=CC=C1.C3(C4=NC=CC=C4)=NC=CC=C3.C5(C6=NC=CC=C6)=NC=CC=C5.[Ru+2].[Cl-].[Cl-]',
- "Tris(2,4-di-tert-butylphenyl) Phosphite": 'CC(C1=CC=C(OP(OC2=CC=C(C(C)(C)C)C=C2C(C)(C)C)OC3=CC=C(C(C)(C)C)C=C3C(C)(C)C)C(C(C)(C)C)=C1)(C)C',
- "Tris(2,4-pentanedionato)cobalt(III)": 'CC(/C=C(C)\\[O-])=O.[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[Co+3]',
- "Tris(2,4-pentanedionato)iron(III)": '[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[Fe+3]',
- "Tris(2,4-pentanedionato)manganese(III)": 'CC(/C=C(C)\\[O-])=O.[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[Mn+3]',
- "Tris(2,6-dimethoxyphenyl)phosphine": 'COC1=C(P(C2=C(OC)C=CC=C2OC)C3=C(OC)C=CC=C3OC)C(OC)=CC=C1',
- "Tris(2-aminoethyl)amine": 'NCCN(CCN)CCN',
- "Tris(2-benzimidazolylmethyl)amine": 'N(CC1=NC2=CC=CC=C2N1)(CC3=NC4=CC=CC=C4N3)CC5=NC6=CC=CC=C6N5',
- "Tris(2-carboxyethyl)phosphine Hydrochloride": 'O=C(CCP(CCC(O)=O)CCC(O)=O)O.[H]Cl',
- "Tris(2-methoxyphenyl)phosphine": 'COC1=CC=CC=C1P(C2=CC=CC=C2OC)C3=CC=CC=C3OC',
- "Tris(2-phenylpyridinato)iridium(III)": 'C1(C2=CC=CC=C2)=NC=CC=C1.C3(C4=CC=CC=C4)=NC=CC=C3.C5(C6=CC=CC=C6)=NC=CC=C5.[Ir]',
- "Tris(2-pyridylmethyl)amine": 'N(CC1=NC=CC=C1)(CC2=NC=CC=C2)CC3=NC=CC=C3',
- "Tris(3,5-dimethyl-1-pyrazolyl)methane": 'CC1=CC(C)=NN1C(N2N=C(C)C=C2C)N3N=C(C)C=C3C',
- "Tris(3-hydroxypropyltriazolylmethyl)amine": 'OCCCC(N(C(CCCO)C1=CNN=N1)C(CCCO)C2=CNN=N2)C3=CNN=N3',
- "Tris(4-fluorophenyl)phosphine": 'FC1=CC=C(P(C2=CC=C(F)C=C2)C3=CC=C(F)C=C3)C=C1',
- "Tris(4-methoxyphenyl)phosphine": 'COC1=CC=C(P(C2=CC=C(OC)C=C2)C3=CC=C(OC)C=C3)C=C1',
- "Tris(dibenzoylmethanato) Iron": '[O-]/C(C1=CC=CC=C1)=C\\C(C2=CC=CC=C2)=O.[O-]/C(C3=CC=CC=C3)=C\\C(C4=CC=CC=C4)=O.[O-]/C(C5=CC=CC=C5)=C\\C(C6=CC=CC=C6)=O.[Fe+3]',
- "Tris(dibenzylideneacetone)dipalladium(0)": 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.O=C(/C=C/C5=CC=CC=C5)/C=C/C6=CC=CC=C6.[Pd].[Pd]',
- "Pd2(dba)3": 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.O=C(/C=C/C5=CC=CC=C5)/C=C/C6=CC=CC=C6.[Pd].[Pd]',
- "Tris(diethylamino)phosphine": 'CCN(P(N(CC)CC)N(CC)CC)CC',
- "Tris(hydroxymethyl)aminomethane": 'NC(CO)(CO)CO',
- "Tris(pentafluorophenyl)phosphine": 'FC1=C(F)C(F)=C(F)C(F)=C1P(C2=C(F)C(F)=C(F)C(F)=C2F)C3=C(F)C(F)=C(F)C(F)=C3F',
- "Tris(trimethylsilyloxy)silane": 'C[Si](O[SiH](O[Si](C)(C)C)O[Si](C)(C)C)(C)C',
- "Tris(triphenylphosphine)rhodium(I) Chloride": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.[Rh+].[Cl-]',
- "Tris(triphenylphosphine)ruthenium(II) Dichloride": 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.[Ru+2].[Cl-].[Cl-]',
- "Tris[(1-benzyl-1H-1,2,3-triazol-4-yl)methyl]amine": 'N(CC1=CN(CC2=CC=CC=C2)N=N1)(CC3=CN(CC4=CC=CC=C4)N=N3)CC5=CN(CC6=CC=CC=C6)N=N5',
- "Tris[2-(dimethylamino)ethyl]amine": 'CN(CCN(CCN(C)C)CCN(C)C)C',
- "Tris[3,5-bis(trifluoromethyl)phenyl]phosphine": 'FC(C1=CC(C(F)(F)F)=CC(P(C2=CC(C(F)(F)F)=CC(C(F)(F)F)=C2)C3=CC(C(F)(F)F)=CC(C(F)(F)F)=C3)=C1)(F)F',
- "Trisodium Paraperiodate": 'O=I([O-])([O-])(O)(O)[O-].[Na+].[Na+].[Na+]',
- "Tri-tert-butyl 1,4,7,10-Tetraazacyclododecane-1,4,7,10-tetraacetate": 'O=C(OC(C)(C)C)CN1CCN(CC(OC(C)(C)C)=O)CCN(CC(OC(C)(C)C)=O)CCN(CC([O-])=O)CC1',
- "Tri-tert-butyl 1,4,7,10-Tetraazacyclododecane-1,4,7-triacetate": 'O=C(OC(C)(C)C)CN1CCN(CC(OC(C)(C)C)=O)CCN(CC(OC(C)(C)C)=O)CCNCC1',
- "Tri-tert-butylphosphonium Tetrafluoroborate": 'CC([PH+](C(C)(C)C)C(C)(C)C)(C)C.F[B-](F)(F)F',
- "Tungsten": '[W]',
- "Urea hydrogen peroxide": 'NC(N)=O.OO',
- "Vanadium": '[V]',
- "Vinylmagnesium Bromide": 'Br[Mg]C=C',
- "Vinyltrimethoxysilane": 'CO[Si](OC)(C=C)OC',
- "Vinyltrimethylsilane": 'C[Si](C)(C=C)C',
- "Vinyltris(2-methoxyethoxy)silane": 'COCCO[Si](OCCOC)(C=C)OCCOC',
- "water": '[H]O[H]',
- "Ytterbium": '[Yb]',
- "Ytterbium(III) Trifluoromethanesulfonate Hydrate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[H]O[H].[Yb+3]',
- "Yttrium": '[Y]',
- "Zinc Bromide": '[Zn+2].[Br-].[Br-]',
- "Zinc Chloride": '[Zn+2].[Cl-].[Cl-]',
- "Zinc peroxide": '[O-][O-].[Zn+2]',
- "Zinc(II) Bis(trifluoromethanesulfinate) Dihydrate": 'O=S(C(F)(F)F)[O-].O=S(C(F)(F)F)[O-].[H]O[H].[H]O[H].[Zn+2]',
- "Zinc(II) Trifluoromethanesulfonate": 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Zn+2]',
- "zink hydroxide": '[Zn+2].[OH-].[OH-]',
- "zink stannate": 'O=[Sn]([O-])[O-].[Zn+2]',
- "Zirconium": '[Zr]',
- "Zirconium hydroxide": '[Zr+4].[OH-].[OH-].[OH-].[OH-]',
- "α-Methyl-L-proline": 'O=C(O)[C@@]1(C)NCCC1',
- "β-Isocupreidine": '[H][C@@](C1([H])[H])(C([H])([H])C2([H])[H])[C@@]3(C([H])([H])C([H])([H])[H])O[C@](C4=C(C([H])=C5O[H])C(C([H])=C5[H])=NC([H])=C4[H])([H])[C@]1([H])[N@@]2C3([H])[H]',
- "Di-tert-butyl dicarbonate": 'O=C(OC(OC(C)(C)C)=O)OC(C)(C)C',
- "Boc2O": 'O=C(OC(OC(C)(C)C)=O)OC(C)(C)C',
- "N-(9H-Fluoren-9-ylmethoxycarbonyloxy)succinimide": 'O=C(ON(C1=O)C(CC1)=O)OCC2C(C=CC=C3)=C3C4=C2C=CC=C4',
- "Fmoc-Osu": 'O=C(ON(C1=O)C(CC1)=O)OCC2C(C=CC=C3)=C3C4=C2C=CC=C4',
+ 'Tris(2,4-di-tert-butylphenyl) Phosphite': 'CC(C1=CC=C(OP(OC2=CC=C(C(C)(C)C)C=C2C(C)(C)C)OC3=CC=C(C(C)(C)C)C=C3C(C)(C)C)C(C(C)(C)C)=C1)(C)C',
+ 'Tris(2,4-pentanedionato)cobalt(III)': 'CC(/C=C(C)\\[O-])=O.[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[Co+3]',
+ 'Tris(2,4-pentanedionato)iron(III)': '[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[Fe+3]',
+ 'Tris(2,4-pentanedionato)manganese(III)': 'CC(/C=C(C)\\[O-])=O.[O-]/C(C)=C\\C(C)=O.[O-]/C(C)=C\\C(C)=O.[Mn+3]',
+ 'Tris(2,6-dimethoxyphenyl)phosphine': 'COC1=C(P(C2=C(OC)C=CC=C2OC)C3=C(OC)C=CC=C3OC)C(OC)=CC=C1',
+ 'Tris(2-aminoethyl)amine': 'NCCN(CCN)CCN',
+ 'Tris(2-benzimidazolylmethyl)amine': 'N(CC1=NC2=CC=CC=C2N1)(CC3=NC4=CC=CC=C4N3)CC5=NC6=CC=CC=C6N5',
+ 'Tris(2-carboxyethyl)phosphine Hydrochloride': 'O=C(CCP(CCC(O)=O)CCC(O)=O)O.[H]Cl',
+ 'Tris(2-methoxyphenyl)phosphine': 'COC1=CC=CC=C1P(C2=CC=CC=C2OC)C3=CC=CC=C3OC',
+ 'Tris(2-phenylpyridinato)iridium(III)': 'C1(C2=CC=CC=C2)=NC=CC=C1.C3(C4=CC=CC=C4)=NC=CC=C3.C5(C6=CC=CC=C6)=NC=CC=C5.[Ir]',
+ 'Tris(2-pyridylmethyl)amine': 'N(CC1=NC=CC=C1)(CC2=NC=CC=C2)CC3=NC=CC=C3',
+ 'Tris(3,5-dimethyl-1-pyrazolyl)methane': 'CC1=CC(C)=NN1C(N2N=C(C)C=C2C)N3N=C(C)C=C3C',
+ 'Tris(3-hydroxypropyltriazolylmethyl)amine': 'OCCCC(N(C(CCCO)C1=CNN=N1)C(CCCO)C2=CNN=N2)C3=CNN=N3',
+ 'Tris(4-fluorophenyl)phosphine': 'FC1=CC=C(P(C2=CC=C(F)C=C2)C3=CC=C(F)C=C3)C=C1',
+ 'Tris(4-methoxyphenyl)phosphine': 'COC1=CC=C(P(C2=CC=C(OC)C=C2)C3=CC=C(OC)C=C3)C=C1',
+ 'Tris(dibenzoylmethanato) Iron': '[O-]/C(C1=CC=CC=C1)=C\\C(C2=CC=CC=C2)=O.[O-]/C(C3=CC=CC=C3)=C\\C(C4=CC=CC=C4)=O.[O-]/C(C5=CC=CC=C5)=C\\C(C6=CC=CC=C6)=O.[Fe+3]',
+ 'Tris(dibenzylideneacetone)dipalladium(0)': 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.O=C(/C=C/C5=CC=CC=C5)/C=C/C6=CC=CC=C6.[Pd].[Pd]',
+ 'Pd2(dba)3': 'O=C(/C=C/C1=CC=CC=C1)/C=C/C2=CC=CC=C2.O=C(/C=C/C3=CC=CC=C3)/C=C/C4=CC=CC=C4.O=C(/C=C/C5=CC=CC=C5)/C=C/C6=CC=CC=C6.[Pd].[Pd]',
+ 'Tris(diethylamino)phosphine': 'CCN(P(N(CC)CC)N(CC)CC)CC',
+ 'Tris(hydroxymethyl)aminomethane': 'NC(CO)(CO)CO',
+ 'Tris(pentafluorophenyl)phosphine': 'FC1=C(F)C(F)=C(F)C(F)=C1P(C2=C(F)C(F)=C(F)C(F)=C2F)C3=C(F)C(F)=C(F)C(F)=C3F',
+ 'Tris(trimethylsilyloxy)silane': 'C[Si](O[SiH](O[Si](C)(C)C)O[Si](C)(C)C)(C)C',
+ 'Tris(triphenylphosphine)rhodium(I) Chloride': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.[Rh+].[Cl-]',
+ 'Tris(triphenylphosphine)ruthenium(II) Dichloride': 'P(C1=CC=CC=C1)(C2=CC=CC=C2)C3=CC=CC=C3.P(C4=CC=CC=C4)(C5=CC=CC=C5)C6=CC=CC=C6.P(C7=CC=CC=C7)(C8=CC=CC=C8)C9=CC=CC=C9.[Ru+2].[Cl-].[Cl-]',
+ 'Tris[(1-benzyl-1H-1,2,3-triazol-4-yl)methyl]amine': 'N(CC1=CN(CC2=CC=CC=C2)N=N1)(CC3=CN(CC4=CC=CC=C4)N=N3)CC5=CN(CC6=CC=CC=C6)N=N5',
+ 'Tris[2-(dimethylamino)ethyl]amine': 'CN(CCN(CCN(C)C)CCN(C)C)C',
+ 'Tris[3,5-bis(trifluoromethyl)phenyl]phosphine': 'FC(C1=CC(C(F)(F)F)=CC(P(C2=CC(C(F)(F)F)=CC(C(F)(F)F)=C2)C3=CC(C(F)(F)F)=CC(C(F)(F)F)=C3)=C1)(F)F',
+ 'Trisodium Paraperiodate': 'O=I([O-])([O-])(O)(O)[O-].[Na+].[Na+].[Na+]',
+ 'Tri-tert-butyl 1,4,7,10-Tetraazacyclododecane-1,4,7,10-tetraacetate': 'O=C(OC(C)(C)C)CN1CCN(CC(OC(C)(C)C)=O)CCN(CC(OC(C)(C)C)=O)CCN(CC([O-])=O)CC1',
+ 'Tri-tert-butyl 1,4,7,10-Tetraazacyclododecane-1,4,7-triacetate': 'O=C(OC(C)(C)C)CN1CCN(CC(OC(C)(C)C)=O)CCN(CC(OC(C)(C)C)=O)CCNCC1',
+ 'Tri-tert-butylphosphonium Tetrafluoroborate': 'CC([PH+](C(C)(C)C)C(C)(C)C)(C)C.F[B-](F)(F)F',
+ Tungsten: '[W]',
+ 'Urea hydrogen peroxide': 'NC(N)=O.OO',
+ Vanadium: '[V]',
+ 'Vinylmagnesium Bromide': 'Br[Mg]C=C',
+ Vinyltrimethoxysilane: 'CO[Si](OC)(C=C)OC',
+ Vinyltrimethylsilane: 'C[Si](C)(C=C)C',
+ 'Vinyltris(2-methoxyethoxy)silane': 'COCCO[Si](OCCOC)(C=C)OCCOC',
+ water: '[H]O[H]',
+ Ytterbium: '[Yb]',
+ 'Ytterbium(III) Trifluoromethanesulfonate Hydrate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[H]O[H].[Yb+3]',
+ Yttrium: '[Y]',
+ 'Zinc Bromide': '[Zn+2].[Br-].[Br-]',
+ 'Zinc Chloride': '[Zn+2].[Cl-].[Cl-]',
+ 'Zinc peroxide': '[O-][O-].[Zn+2]',
+ 'Zinc(II) Bis(trifluoromethanesulfinate) Dihydrate': 'O=S(C(F)(F)F)[O-].O=S(C(F)(F)F)[O-].[H]O[H].[H]O[H].[Zn+2]',
+ 'Zinc(II) Trifluoromethanesulfonate': 'O=S(C(F)(F)F)([O-])=O.O=S(C(F)(F)F)([O-])=O.[Zn+2]',
+ 'zink hydroxide': '[Zn+2].[OH-].[OH-]',
+ 'zink stannate': 'O=[Sn]([O-])[O-].[Zn+2]',
+ Zirconium: '[Zr]',
+ 'Zirconium hydroxide': '[Zr+4].[OH-].[OH-].[OH-].[OH-]',
+ 'α-Methyl-L-proline': 'O=C(O)[C@@]1(C)NCCC1',
+ 'β-Isocupreidine': '[H][C@@](C1([H])[H])(C([H])([H])C2([H])[H])[C@@]3(C([H])([H])C([H])([H])[H])O[C@](C4=C(C([H])=C5O[H])C(C([H])=C5[H])=NC([H])=C4[H])([H])[C@]1([H])[N@@]2C3([H])[H]',
+ 'Di-tert-butyl dicarbonate': 'O=C(OC(OC(C)(C)C)=O)OC(C)(C)C',
+ Boc2O: 'O=C(OC(OC(C)(C)C)=O)OC(C)(C)C',
+ 'N-(9H-Fluoren-9-ylmethoxycarbonyloxy)succinimide': 'O=C(ON(C1=O)C(CC1)=O)OCC2C(C=CC=C3)=C3C4=C2C=CC=C4',
+ 'Fmoc-Osu': 'O=C(ON(C1=O)C(CC1)=O)OCC2C(C=CC=C3)=C3C4=C2C=CC=C4',
};
diff --git a/app/packs/src/components/structureEditor/StructureEditorModal.js b/app/packs/src/components/structureEditor/StructureEditorModal.js
index 75fca68614..306055d252 100644
--- a/app/packs/src/components/structureEditor/StructureEditorModal.js
+++ b/app/packs/src/components/structureEditor/StructureEditorModal.js
@@ -9,6 +9,7 @@ import {
ControlLabel
} from 'react-bootstrap';
import Select from 'react-select';
+import NotificationActions from 'src/stores/alt/actions/NotificationActions';
import UserStore from 'src/stores/alt/stores/UserStore';
import UIStore from 'src/stores/alt/stores/UIStore';
import StructureEditor from 'src/models/StructureEditor';
@@ -178,13 +179,20 @@ export default class StructureEditorModal extends React.Component {
});
});
} else {
- const { molfile, info } = structure;
- structure.fetchSVG().then((svg) => {
- this.setState({
- showModal: false,
- showWarning: this.props.hasChildren || this.props.hasParent
- }, () => { if (this.props.onSave) { this.props.onSave(molfile, svg, info, editor.id); } });
- });
+ try {
+ const { molfile, info } = structure;
+ if (!molfile) throw new Error('No molfile');
+ structure.fetchSVG().then((svg) => {
+ this.setState({
+ showModal: false,
+ showWarning: this.props.hasChildren || this.props.hasParent
+ }, () => { if (this.props.onSave) { this.props.onSave(molfile, svg, info, editor.id); } });
+ });
+ } catch (e) {
+ NotificationActions.add({
+ title: 'Editor error', message: `The drawing is not supported! ${e}`, level: 'error', position: 'tc'
+ });
+ }
}
}
@@ -235,7 +243,7 @@ export default class StructureEditorModal extends React.Component {
;
citeMarvin = (
-
+
);
}
diff --git a/app/packs/src/endpoints/ApiServices.js b/app/packs/src/endpoints/ApiServices.js
new file mode 100644
index 0000000000..01c44af62d
--- /dev/null
+++ b/app/packs/src/endpoints/ApiServices.js
@@ -0,0 +1,15 @@
+const CommentManagementServices = {
+ COMMENT_BY_ID: (commentId) => `/api/v1/comments/${commentId}.json`,
+ COMMENT_BY_COMMENTABLE: (commentableId, commentableType) => `/api/v1/comments?commentable_id=${commentableId}&commentable_type=${commentableType}`,
+ CREATE_COMMENT: '/api/v1/comments',
+ UPDATE_COMMENT: (comment) => `/api/v1/comments/${comment.id}`,
+ DELETE_COMMENT: (comment) => `/api/v1/comments/${comment.id}`,
+};
+
+// path of the chemspectra data type file
+const SPECTRA_DATA_TYPE = '/data_type.json';
+
+export {
+ CommentManagementServices,
+ SPECTRA_DATA_TYPE,
+};
diff --git a/app/packs/src/fetchers/AdminFetcher.js b/app/packs/src/fetchers/AdminFetcher.js
index 0cb47a21f4..280c731c96 100644
--- a/app/packs/src/fetchers/AdminFetcher.js
+++ b/app/packs/src/fetchers/AdminFetcher.js
@@ -2,52 +2,59 @@ import 'whatwg-fetch';
import BaseFetcher from 'src/fetchers/BaseFetcher';
export default class AdminFetcher {
- static fetchUnitsSystem() {
- return fetch('/units_system/units_system.json', {
- credentials: 'same-origin', cache: 'no-store', headers: { 'cache-control': 'no-cache' }
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
- }
-
static fetchLocalCollector() {
return fetch('/api/v1/admin/listLocalCollector/all.json', {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static checkDiskSpace() {
return fetch('/api/v1/admin/disk.json', {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchDevices() {
return fetch('/api/v1/admin/listDevices/all.json', {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchDeviceById(deviceId) {
return fetch(`/api/v1/admin/device/${deviceId}`, {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchDeviceMetadataByDeviceId(deviceId) {
return fetch(`/api/v1/admin/deviceMetadata/${deviceId}`, {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static postDeviceMetadata(params) {
@@ -56,26 +63,35 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static syncDeviceMetadataToDataCite(params) {
- return fetch(`/api/v1/admin/deviceMetadata/${params.device_id}/sync_to_data_cite`, {
- credentials: 'same-origin',
- method: 'PUT',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(params)
- }).then(response => response.json())
+ return fetch(
+ `/api/v1/admin/deviceMetadata/${params.device_id}/sync_to_data_cite`,
+ {
+ credentials: 'same-origin',
+ method: 'PUT',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(params),
+ }
+ )
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static testSFTP(params) {
@@ -84,12 +100,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static removeDeviceMethod(params) {
@@ -98,12 +117,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static updateDeviceMethod(params) {
@@ -112,12 +134,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static editNovncSettings(params) {
@@ -126,11 +151,13 @@ export default class AdminFetcher {
method: 'PUT',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then((response) => {
- if (response.status === 204) { return ''; }
+ body: JSON.stringify(params),
+ }).then(response => {
+ if (response.status === 204) {
+ return '';
+ }
return 'error';
});
}
@@ -141,12 +168,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static createUserAccount(params) {
@@ -155,12 +185,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static updateUser(params) {
@@ -169,20 +202,45 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchUsers() {
return fetch('/api/v1/admin_user/listUsers/all.json', {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
+ }
+
+ static fetchUsersByNameType(name, type, limit = 5) {
+ return fetch(
+ `/api/v1/admin_user/listUsers/byname.json?${new URLSearchParams({
+ name,
+ type,
+ limit,
+ })}`,
+ {
+ credentials: 'same-origin',
+ method: 'GET',
+ }
+ )
+ .then(response => response.json())
+ .then(json => json)
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static updateAccount(params) {
@@ -191,12 +249,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static olsTermDisableEnable(params) {
@@ -205,10 +266,10 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then((response) => {
+ body: JSON.stringify(params),
+ }).then(response => {
if (response.status === 204) {
return true;
}
@@ -222,18 +283,24 @@ export default class AdminFetcher {
return fetch('/api/v1/admin/importOlsTerms/', {
credentials: 'same-origin',
method: 'POST',
- body: data
- }).then(response => response.json())
+ body: data,
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchGroupsDevices(type) {
return fetch(`/api/v1/admin/group_device/list?type=${type}`, {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static updateGroup(params = {}) {
@@ -242,20 +309,15 @@ export default class AdminFetcher {
method: 'PUT',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
- }
-
- static fetchUsersByNameType(name, type) {
- return fetch(`/api/v1/admin/group_device/name.json?type=${type}&name=${name}`, {
- credentials: 'same-origin'
- }).then(response => response.json())
- .then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static createGroupDevice(params = {}) {
@@ -264,28 +326,26 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
- .then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
- }
-
- static fetchUserGroupByName(name) {
- return fetch(`/api/v1/matrix/find_user.json?name=${name}`, {
- credentials: 'same-origin'
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchMatrices() {
return fetch('/api/v1/matrix/list.json', {
- credentials: 'same-origin'
- }).then(response => response.json())
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static updateMatrice(params) {
@@ -294,12 +354,15 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static updateMatriceJson(params) {
@@ -308,99 +371,27 @@ export default class AdminFetcher {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(params)
- }).then(response => response.json())
+ body: JSON.stringify(params),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
- }
-
- static exec(path, method) {
- return BaseFetcher.withoutBodyData({
- apiEndpoint: path, requestMethod: method, jsonTranformation: json => json
- });
- }
-
- static genericKlass(params, path) {
- return BaseFetcher.withBodyData({
- apiEndpoint: `/api/v1/admin_generic/${path}/`, requestMethod: 'POST', bodyData: params, jsonTranformation: json => json
- });
- }
-
- static fetchElementKlasses() {
- return this.exec('/api/v1/generic_elements/klasses_all.json', 'GET');
- }
-
- static updateGElTemplates(params) {
- return this.genericKlass(params, 'update_element_template');
- }
-
- static createElementKlass(params) {
- return this.genericKlass(params, 'create_element_klass');
- }
-
- static updateElementKlass(params) {
- return this.genericKlass(params, 'update_element_klass');
- }
-
- static activeInActiveElementKlass(params) {
- return this.genericKlass(params, 'de_active_element_klass');
- }
-
- static deleteElementKlass(params) {
- return this.genericKlass(params, 'delete_element_klass');
- }
-
- static createSegmentKlass(params) {
- return this.genericKlass(params, 'create_segment_klass');
- }
-
- static updateSegmentKlass(params) {
- return this.genericKlass(params, 'update_segment_klass');
- }
-
- static deActiveSegmentKlass(params) {
- return this.genericKlass(params, 'de_active_segment_klass');
- }
-
- static updateSegmentTemplate(params) {
- return this.genericKlass(params, 'update_segment_template');
- }
-
- static deleteKlassRevision(params) {
- return this.genericKlass(params, 'delete_klass_revision');
- }
-
- static deleteGenericRevision(id) {
- return this.exec(`/api/v1/admin_generic/delete_generic_revision/${id}`, 'DELETE');
- }
-
- static listSegmentKlass(params = {}) {
- const api = params.is_active === undefined ? '/api/v1/admin_generic/list_segment_klass.json' : `/api/v1/admin/list_segment_klass.json?is_active=${params.is_active}`;
- return this.exec(api, 'GET');
- }
-
- static listDatasetKlass(params = {}) {
- const api = params.is_active === undefined ? '/api/v1/admin_generic/list_dataset_klass.json' : `/api/v1/admin/list_dataset_klass.json?is_active=${params.is_active}`;
- return this.exec(api, 'GET');
- }
-
- static deActiveDatasetKlass(params) {
- return this.genericKlass(params, 'de_active_dataset_klass');
- }
-
- static updateDatasetTemplate(params) {
- return this.genericKlass(params, 'update_dataset_template');
+ .catch(errorMessage => {
+ console.log(errorMessage);
+ });
}
static fetchJobs() {
return fetch('/api/v1/admin/jobs', {
credentials: 'same-origin',
method: 'GET',
- }).then(response => response.json())
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.error(errorMessage); });
+ .catch(errorMessage => {
+ console.error(errorMessage);
+ });
}
static restartJob(id) {
@@ -409,15 +400,14 @@ export default class AdminFetcher {
method: 'PUT',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify(id)
- }).then(response => response.json())
+ body: JSON.stringify(id),
+ })
+ .then(response => response.json())
.then(json => json)
- .catch((errorMessage) => { console.error(errorMessage); });
- }
-
- static fetchKlassRevisions(id, klass) {
- return this.exec(`/api/v1/admin/klass_revisions.json?id=${id}&klass=${klass}`, 'GET');
+ .catch(errorMessage => {
+ console.error(errorMessage);
+ });
}
}
diff --git a/app/packs/src/fetchers/AttachmentFetcher.js b/app/packs/src/fetchers/AttachmentFetcher.js
index 48fc3bb9ca..2858fb0028 100644
--- a/app/packs/src/fetchers/AttachmentFetcher.js
+++ b/app/packs/src/fetchers/AttachmentFetcher.js
@@ -1,3 +1,4 @@
+/* eslint-disable camelcase */
import 'whatwg-fetch';
import { decamelizeKeys } from 'humps';
@@ -15,80 +16,83 @@ const fileFromAttachment = (attachment, containerId) => {
};
export default class AttachmentFetcher {
-
static fetchImageAttachment(params) {
return fetch(`/api/v1/attachments/image/${params.id}`, {
credentials: 'same-origin',
- method: 'GET'
- }).then(response => response.blob())
- .then(blob => ({ type: blob.type, data: URL.createObjectURL(blob) }))
- .catch((errorMessage) => { console.log(errorMessage); });
+ method: 'GET',
+ })
+ .then((response) => response.blob())
+ .then((blob) => ({ type: blob.type, data: URL.createObjectURL(blob) }))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
- static fetchImageAttachmentByIdentifier(params) {
- const urlParams=new URLSearchParams({
+ static fetchImageAttachmentByIdentifier(params) {
+ const urlParams = new URLSearchParams({
identifier: params.identifier,
- annotated: params.annotated})
-
- return fetch('/api/v1/attachments/image/-1?'+urlParams, {
+ annotated: params.annotated,
+ });
+
+ return fetch(`/api/v1/attachments/image/-1?${urlParams}`, {
credentials: 'same-origin',
- method: 'GET'
- }).then(response => response.blob())
- .then(blob => ({ type: blob.type, data: URL.createObjectURL(blob) }))
- .catch((errorMessage) => { console.log(errorMessage); });
+ method: 'GET',
+ })
+ .then((response) => response.blob())
+ .then((blob) => ({ type: blob.type, data: URL.createObjectURL(blob) }))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static fetchThumbnail(params) {
- let promise = fetch(`/api/v1/attachments/thumbnail/${params.id}`, {
+ const promise = fetch(`/api/v1/attachments/thumbnail/${params.id}`, {
credentials: 'same-origin',
- method: 'GET'
- }).then((response) => {
- return response.json()
- }).then((json) => {
- return json
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ method: 'GET',
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
static fetchThumbnails(ids) {
- let promise = fetch('/api/v1/attachments/thumbnails/', {
+ const promise = fetch('/api/v1/attachments/thumbnails/', {
credentials: 'same-origin',
method: 'POST',
headers: {
- 'Accept': 'application/json',
+ Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ ids }),
- }).then((response) => {
- return response.json();
- }).then((json) => {
- return json;
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
static fetchFiles(ids) {
- let promise = fetch('/api/v1/attachments/files/', {
+ const promise = fetch('/api/v1/attachments/files/', {
credentials: 'same-origin',
method: 'POST',
headers: {
- 'Accept': 'application/json',
+ Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ ids }),
- }).then((response) => {
- return response.json();
- }).then((json) => {
- return json;
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
@@ -100,17 +104,16 @@ export default class AttachmentFetcher {
data.append('molfile', mol);
data.append('mass', mass);
- let promise = fetch('/api/v1/chemspectra/file/convert', {
+ const promise = fetch('/api/v1/chemspectra/file/convert', {
credentials: 'same-origin',
method: 'POST',
body: data,
- }).then((response) => {
- return response.json();
- }).then((json) => {
- return json;
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
@@ -119,14 +122,15 @@ export default class AttachmentFetcher {
if (container == null) return [];
const allFiles = [];
this.filterAllAttachments(allFiles, container.children);
- return allFiles
+ return allFiles;
}
static filterAllAttachments(files, containers) {
containers.forEach((container) => {
- const tmpArray = (container.attachments || []).filter(a => a.is_new)
- .map(a => fileFromAttachment(a, container.id));
- files.push.apply(files, tmpArray);
+ const tmpArray = (container.attachments || [])
+ .filter((a) => a.is_new)
+ .map((a) => fileFromAttachment(a, container.id));
+ files.push(...tmpArray);
if (container.children && container.children.length > 0) {
this.filterAllAttachments(files, container.children);
@@ -137,17 +141,19 @@ export default class AttachmentFetcher {
static updateAttachables(files, attachableType, attachableId, dels) {
const data = new FormData();
files.forEach((file) => {
+ data.append('attfilesIdentifier[]', file.id);
data.append('files[]', file.file, file.name);
});
data.append('attachable_type', attachableType);
data.append('attachable_id', attachableId);
+
dels.forEach((f) => {
data.append('del_files[]', f.id);
});
return () => fetch('/api/v1/attachable/update_attachments_attachable', {
credentials: 'same-origin',
method: 'post',
- body: data
+ body: data,
}).then((response) => {
if (response.ok === false) {
let msg = 'Files uploading failed: ';
@@ -156,22 +162,27 @@ export default class AttachmentFetcher {
} else {
msg += response.statusText;
}
- NotificationActions.add({ message: msg, level: 'error', position: 'tc' });
+ NotificationActions.add({
+ message: msg,
+ level: 'error',
+ position: 'tc',
+ });
}
});
}
static uploadToInbox(attachments) {
const data = new FormData();
- const files = (attachments).filter(f => f.is_new)
- .map(f => fileFromAttachment(f, null));
+ const files = attachments
+ .filter((f) => f.is_new)
+ .map((f) => fileFromAttachment(f, null));
files.forEach((file) => {
data.append(file.id || file.name, file);
});
return () => fetch('/api/v1/attachments/upload_to_inbox', {
credentials: 'same-origin',
method: 'post',
- body: data
+ body: data,
}).then((response) => {
if (response.ok === false) {
let msg = 'Files uploading to Inbox failed: ';
@@ -182,7 +193,7 @@ export default class AttachmentFetcher {
}
NotificationActions.add({
message: msg,
- level: 'error'
+ level: 'error',
});
}
});
@@ -197,17 +208,17 @@ export default class AttachmentFetcher {
credentials: 'same-origin',
contentType: 'application/json',
method: 'post',
- body: data
- }).then((response) => {
- return response.json();
- }).then((json) => {
- for (let i = 0; i < json.error_messages.length; i++) {
- NotificationActions.add({
- message: json.error_messages[i],
- level: 'error'
- });
- }
- });
+ body: data,
+ })
+ .then((response) => response.json())
+ .then((json) => {
+ for (let i = 0; i < json.error_messages.length; i += 1) {
+ NotificationActions.add({
+ message: json.error_messages[i],
+ level: 'error',
+ });
+ }
+ });
}
static uploadCompleted(filename, key, checksum) {
@@ -216,90 +227,95 @@ export default class AttachmentFetcher {
method: 'post',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
- body: JSON.stringify({ filename: filename, key: key, checksum: checksum }),
- }).then(response => response.json())
+ body: JSON.stringify({
+ filename,
+ key,
+ checksum,
+ }),
+ })
+ .then((response) => response.json())
.then((response) => {
LoadingActions.stopLoadingWithProgress(filename);
- if (response.ok == false) {
+ if (response.ok === false) {
let msg = 'Files uploading failed: ';
- if (response.status == 413) {
+ if (response.status === 413) {
msg += 'File size limit exceeded.';
} else {
msg += response.statusText;
}
- NotificationActions.add({
- message: msg,
- level: 'error'
- });
- } else if(response.error_messages) {
- for (let i = 0; i < response.error_messages.length; i++) {
NotificationActions.add({
- message: response.error_messages[i],
- level: 'error'
+ message: msg,
+ level: 'error',
});
+ } else if (response.error_messages) {
+ for (let i = 0; i < response.error_messages.length; i += 1) {
+ NotificationActions.add({
+ message: response.error_messages[i],
+ level: 'error',
+ });
+ }
}
- }
- })
- };
+ });
+ }
static uploadChunk(chunk, counter, key, progress, filename) {
- let body = { file: chunk, counter: counter, key: key };
+ const body = { file: chunk, counter, key };
const formData = new FormData();
- for (const name in body) {
+ Object.keys(body).forEach((name) => {
formData.append(name, body[name]);
- }
+ });
return () => fetch('/api/v1/attachments/upload_chunk', {
credentials: 'same-origin',
method: 'post',
- body: formData
+ body: formData,
})
- .then(response => response.json())
+ .then((response) => response.json())
.then((response) => {
LoadingActions.updateLoadingProgress(filename, progress);
- if (response.ok == false) {
+ if (response.ok === false) {
const msg = `Chunk uploading failed: ${response.statusText}`;
NotificationActions.add({
message: msg,
- level: 'error'
+ level: 'error',
});
}
});
- };
+ }
static async uploadFile(file) {
LoadingActions.startLoadingWithProgress(file.name);
const chunkSize = 100 * 1024 * 1024;
- const chunksCount = file.size % chunkSize == 0
+ const chunksCount = file.size % chunkSize === 0
? file.size / chunkSize
: Math.floor(file.size / chunkSize) + 1;
let beginingOfTheChunk = 0;
let endOfTheChunk = chunkSize;
- let tasks = [];
+ const tasks = [];
const key = file.id;
- let spark = new SparkMD5.ArrayBuffer();
- let totalStep = chunksCount + 1;
- for (let counter = 1; counter <= chunksCount; counter++) {
- let chunk = file.slice(beginingOfTheChunk, endOfTheChunk);
- tasks.push(this.uploadChunk(chunk, counter, key, counter / totalStep, file.name)());
+ const spark = new SparkMD5.ArrayBuffer();
+ const totalStep = chunksCount + 1;
+ for (let counter = 1; counter <= chunksCount; counter += 1) {
+ const chunk = file.slice(beginingOfTheChunk, endOfTheChunk);
+ tasks.push(
+ this.uploadChunk(chunk, counter, key, counter / totalStep, file.name)()
+ );
spark.append(await this.getFileContent(chunk));
beginingOfTheChunk = endOfTheChunk;
endOfTheChunk += chunkSize;
}
- let checksum = spark.end();
- return Promise.all(tasks).then(() => {
- return this.uploadCompleted(file.name, key, checksum)();
- });
+ const checksum = spark.end();
+ return Promise.all(tasks).then(() => this.uploadCompleted(file.name, key, checksum)());
}
static getFileContent(file) {
- let promise = new Promise(function (resolve, reject) {
- var reader = new FileReader();
+ const promise = new Promise((resolve) => {
+ const reader = new FileReader();
reader.onload = function (event) {
- let buffer = new Uint8Array(event.target.result);
+ const buffer = new Uint8Array(event.target.result);
resolve(buffer);
};
@@ -310,109 +326,163 @@ export default class AttachmentFetcher {
}
static deleteAttachment(params) {
- let promise = fetch(`/api/v1/attachments/${params.id}`, {
+ const promise = fetch(`/api/v1/attachments/${params.id}`, {
credentials: 'same-origin',
method: 'DELETE',
headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json'
- }
- }).then((response) => {
- return response.json();
- }).then((json) => {
- return new Attachment(json.attachment);
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ })
+ .then((response) => response.json())
+ .then((json) => new Attachment(json.attachment))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
static deleteContainerLink(params) {
- let promise = fetch(`/api/v1/attachments/link/${params.id}`, {
+ const promise = fetch(`/api/v1/attachments/link/${params.id}`, {
credentials: 'same-origin',
method: 'DELETE',
headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json'
- }
- }).then((response) => {
- return response.json();
- }).then((json) => {
- return new Attachment(json.attachment);
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ })
+ .then((response) => response.json())
+ .then((json) => new Attachment(json.attachment))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
- static downloadZip(id) {
- let file_name = 'dataset.zip'
- return fetch(`/api/v1/attachments/zip/${id}`, {
+ static downloadDataset(id) {
+ let file_name = 'dataset.xlsx';
+ return fetch(`/api/v1/export_ds/dataset/${id}`, {
credentials: 'same-origin',
method: 'GET',
- }).then((response) => {
- const disposition = response.headers.get('Content-Disposition')
- if (disposition && disposition.indexOf('attachment') !== -1) {
- let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
- let matches = filenameRegex.exec(disposition);
- if (matches != null && matches[1]) {
- file_name = matches[1].replace(/['"]/g, '');
+ })
+ .then((response) => {
+ const disposition = response.headers.get('Content-Disposition');
+ if (disposition && disposition.indexOf('attachment') !== -1) {
+ const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
+ const matches = filenameRegex.exec(disposition);
+ if (matches != null && matches[1]) {
+ file_name = matches[1].replace(/['"]/g, '');
+ }
}
- }
- return response.blob()
- }).then((blob) => {
- const a = document.createElement("a");
- a.style = "display: none";
- document.body.appendChild(a);
- let url = window.URL.createObjectURL(blob);
- a.href = url;
- a.download = file_name
- a.click();
- window.URL.revokeObjectURL(url);
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ return response.blob();
+ })
+ .then((blob) => {
+ const a = document.createElement('a');
+ a.style = 'display: none';
+ document.body.appendChild(a);
+ const url = window.URL.createObjectURL(blob);
+ a.href = url;
+ a.download = file_name;
+ a.click();
+ window.URL.revokeObjectURL(url);
+ })
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
- static downloadZipBySample(sampleId) {
- let fileName = 'dataset.zip';
- return fetch(`/api/v1/attachments/sample_analyses/${sampleId}`, {
+ static downloadZip(id) {
+ let file_name = 'dataset.zip';
+ return fetch(`/api/v1/attachments/zip/${id}`, {
credentials: 'same-origin',
method: 'GET',
- }).then((response) => {
- const disposition = response.headers.get('Content-Disposition');
- if (disposition != null) {
+ })
+ .then((response) => {
+ const disposition = response.headers.get('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
- fileName = matches[1].replace(/['"]/g, '');
+ file_name = matches[1].replace(/['"]/g, '');
}
}
-
return response.blob();
- }
- else {
- NotificationActions.notifyExImportStatus('Analysis download', 204);
- return null;
- }
- }).then((blob) => {
- if (blob && blob.type != null) {
+ })
+ .then((blob) => {
const a = document.createElement('a');
a.style = 'display: none';
document.body.appendChild(a);
const url = window.URL.createObjectURL(blob);
a.href = url;
- a.download = fileName;
+ a.download = file_name;
a.click();
window.URL.revokeObjectURL(url);
- }
- }).catch((errorMessage) => { console.log(errorMessage); });
+ })
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ }
+
+ static downloadZipBySample(sampleId) {
+ let fileName = 'dataset.zip';
+ return fetch(`/api/v1/attachments/sample_analyses/${sampleId}`, {
+ credentials: 'same-origin',
+ method: 'GET',
+ })
+ .then((response) => {
+ const disposition = response.headers.get('Content-Disposition');
+ if (disposition != null) {
+ if (disposition && disposition.indexOf('attachment') !== -1) {
+ const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
+ const matches = filenameRegex.exec(disposition);
+ if (matches != null && matches[1]) {
+ fileName = matches[1].replace(/['"]/g, '');
+ }
+ }
+
+ return response.blob();
+ }
+ NotificationActions.notifyExImportStatus('Analysis download', 204);
+ return null;
+ })
+ .then((blob) => {
+ if (blob && blob.type != null) {
+ const a = document.createElement('a');
+ a.style = 'display: none';
+ document.body.appendChild(a);
+ const url = window.URL.createObjectURL(blob);
+ a.href = url;
+ a.download = fileName;
+ a.click();
+ window.URL.revokeObjectURL(url);
+ }
+ })
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
- static saveSpectrum(attId, peaksStr, shift, scan, thres, integration, multiplicity, predict, keepPred, waveLengthStr, cyclicvolta, curveIdx, simulatenmr) {
+ static saveSpectrum(
+ attId,
+ peaksStr,
+ shift,
+ scan,
+ thres,
+ integration,
+ multiplicity,
+ predict,
+ keepPred,
+ waveLengthStr,
+ cyclicvolta,
+ curveIdx,
+ simulatenmr,
+ previousSpcInfos,
+ isSaveCombined,
+ axesUnitsStr,
+ detector,
+ ) {
const params = {
attachmentId: attId,
peaksStr,
@@ -429,23 +499,37 @@ export default class AttachmentFetcher {
cyclicvolta: cyclicvolta,
curveIdx: curveIdx,
simulatenmr: simulatenmr,
+ axesUnits: axesUnitsStr,
+ detector
};
- const promise = fetch(
- '/api/v1/attachments/save_spectrum/',
- {
- credentials: 'same-origin',
- method: 'POST',
- headers:
- {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(decamelizeKeys(params)),
+ const promise = fetch('/api/v1/attachments/save_spectrum/', {
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
},
- )
- .then(response => response.json())
- .then(json => json)
+ body: JSON.stringify(decamelizeKeys(params)),
+ })
+ .then((response) => response.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);
});
@@ -453,7 +537,19 @@ export default class AttachmentFetcher {
return promise;
}
- static inferSpectrum(attId, peaksStr, shift, scan, thres, integration, multiplicity, predict, peaks, layout, keepPred) {
+ static inferSpectrum(
+ attId,
+ peaksStr,
+ shift,
+ scan,
+ thres,
+ integration,
+ multiplicity,
+ predict,
+ peaks,
+ layout,
+ keepPred
+ ) {
const params = {
attachmentId: attId,
peaksStr,
@@ -471,21 +567,17 @@ export default class AttachmentFetcher {
layout,
};
- const promise = fetch(
- '/api/v1/attachments/infer/',
- {
- credentials: 'same-origin',
- method: 'POST',
- headers:
- {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(decamelizeKeys(params)),
+ const promise = fetch('/api/v1/attachments/infer/', {
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
},
- )
- .then(response => response.json())
- .then(json => json)
+ body: JSON.stringify(decamelizeKeys(params)),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
.catch((errorMessage) => {
console.log(errorMessage);
});
@@ -494,24 +586,20 @@ export default class AttachmentFetcher {
}
static regenerateSpectrum(jcampIds) {
- const promise = fetch(
- '/api/v1/attachments/regenerate_spectrum/',
- {
- credentials: 'same-origin',
- method: 'POST',
- headers:
- {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- original: jcampIds.orig,
- generated: jcampIds.gene,
- }),
+ const promise = fetch('/api/v1/attachments/regenerate_spectrum/', {
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
},
- )
- .then(response => response.json())
- .then(json => json)
+ body: JSON.stringify({
+ original: jcampIds.orig,
+ generated: jcampIds.gene,
+ }),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
.catch((errorMessage) => {
console.log(errorMessage);
});
@@ -520,8 +608,30 @@ export default class AttachmentFetcher {
}
static regenerateEditedSpectrum(jcampIds, molfile) {
+ const promise = fetch('/api/v1/attachments/regenerate_edited_spectrum/', {
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ edited: jcampIds.edited,
+ molfile: molfile,
+ }),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+
+ return promise;
+ }
+
+ static combineSpectra(jcampIds, curveIdx) {
const promise = fetch(
- '/api/v1/attachments/regenerate_edited_spectrum/',
+ '/api/v1/chemspectra/file/combine_spectra',
{
credentials: 'same-origin',
method: 'POST',
@@ -531,13 +641,17 @@ export default class AttachmentFetcher {
'Content-Type': 'application/json',
},
body: JSON.stringify({
- edited: jcampIds.edited,
- molfile: molfile
+ spectra_ids: jcampIds,
+ front_spectra_idx: curveIdx,
}),
},
)
- .then(response => response.json())
- .then(json => json)
+ .then((response) => {
+ return response.json();
+ })
+ .then((json) => {
+ return json;
+ })
.catch((errorMessage) => {
console.log(errorMessage);
});
diff --git a/app/packs/src/fetchers/BaseFetcher.js b/app/packs/src/fetchers/BaseFetcher.js
index c77cc0a2bd..1af1b5c5f5 100644
--- a/app/packs/src/fetchers/BaseFetcher.js
+++ b/app/packs/src/fetchers/BaseFetcher.js
@@ -1,6 +1,8 @@
import 'whatwg-fetch';
import UIStore from 'src/stores/alt/stores/UIStore';
+import CellLine from 'src/models/cellLine/CellLine'
+import UserStore from 'src/stores/alt/stores/UserStore';
export default class BaseFetcher {
/**
@@ -18,9 +20,11 @@ export default class BaseFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(bodyData)
- }).then((response) => response.json()).then((json) => jsonTranformation(json)).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ }).then((response) => response.json())
+ .then((json) => jsonTranformation(json))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
@@ -34,9 +38,11 @@ export default class BaseFetcher {
const promise = fetch(apiEndpoint, {
credentials: 'same-origin',
method: requestMethod
- }).then((response) => response.json()).then((json) => jsonTranformation(json)).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ }).then((response) => response.json())
+ .then((json) => jsonTranformation(json))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
@@ -44,22 +50,71 @@ export default class BaseFetcher {
static fetchByCollectionId(id, queryParams = {}, isSync = false, type = 'samples', ElKlass) {
const page = queryParams.page || 1;
const perPage = queryParams.per_page || UIStore.getState().number_of_results;
- const filterCreatedAt = queryParams.filterCreatedAt === true ? '&filter_created_at=true' : '&filter_created_at=false';
+ const filterCreatedAt = queryParams.filterCreatedAt === true
+ ? '&filter_created_at=true' : '&filter_created_at=false';
const fromDate = queryParams.fromDate ? `&from_date=${queryParams.fromDate.unix()}` : '';
const toDate = queryParams.toDate ? `&to_date=${queryParams.toDate.unix()}` : '';
- const product_only = queryParams.productOnly === true ? '&product_only=true' : '&product_only=false';
+ const productOnly = queryParams.productOnly === true ? '&product_only=true' : '&product_only=false';
const api = `/api/v1/${type}.json?${isSync ? 'sync_' : ''}`
- + `collection_id=${id}&page=${page}&per_page=${perPage}&`
- + `${fromDate}${toDate}${filterCreatedAt}${product_only}`;
- let addQuery = type === 'samples'
- ? `&product_only=${queryParams.productOnly || false}&molecule_sort=${queryParams.moleculeSort ? 1 : 0}`
- : '';
- addQuery = type === 'generic_elements' ? `&el_type=${queryParams.name}` : '';
+ + `collection_id=${id}&page=${page}&per_page=${perPage}&`
+ + `${fromDate}${toDate}${filterCreatedAt}${productOnly}`;
+ let addQuery = '';
+ let userState;
+ let group;
+ let sort;
+ let direction;
+ let filters;
+ let reaction;
+ let sortColumn;
+
+ switch (type) {
+ case 'samples':
+ addQuery = `&product_only=${queryParams.productOnly || false}`
+ + `&molecule_sort=${queryParams.moleculeSort ? 1 : 0}`;
+ break;
+ case 'reactions':
+ userState = UserStore.getState();
+ filters = userState?.profile?.data?.filters || {};
+ reaction = userState?.profile?.data?.filters?.reaction || {};
+ group = filters.reaction?.group || 'created_at';
+ sort = filters.reaction?.sort || false;
+ direction = filters.reaction?.direction || 'DESC';
+
+ if (group === 'none') {
+ sortColumn = sort ? 'created_at' : 'updated_at';
+ } else if (sort && group) {
+ sortColumn = group;
+ } else {
+ sortColumn = 'updated_at';
+ }
+
+ addQuery = `&sort_column=${sortColumn}&sort_direction=${direction}`;
+
+ // if the user has not updated its profile yet, we set the default sort to created_at
+ if (!filters.reaction) {
+ addQuery = '&sort_column=created_at&sort_direction=DESC';
+ }
+ break;
+ case 'generic_elements':
+ userState = UserStore.getState();
+ filters = userState?.profile?.data?.filters || {};
+ group = filters[queryParams.name]?.group || 'none';
+ sort = filters[queryParams.name]?.sort || false;
+ addQuery = `&el_type=${queryParams.name}&sort_column=${(sort && group) || 'updated_at'}`;
+ break;
+ default:
+ }
+
return fetch(api.concat(addQuery), {
credentials: 'same-origin'
}).then((response) => (
response.json().then((json) => ({
- elements: json[type].map((r) => (new ElKlass(r))),
+ elements: json[type].map((r) => {
+ if (type === 'cell_lines') {
+ return CellLine.createFromRestResponse(id, r);
+ }
+ return (new ElKlass(r));
+ }),
totalElements: parseInt(response.headers.get('X-Total'), 10),
page: parseInt(response.headers.get('X-Page'), 10),
pages: parseInt(response.headers.get('X-Total-Pages'), 10),
@@ -99,4 +154,33 @@ export default class BaseFetcher {
return Promise.all(updateTasks);
}
+
+ static updateAnnotationsOfAttachments(element) {
+ const updateTasks = [];
+ element.attachments
+ .filter(((attach) => attach.hasOwnProperty('updatedAnnotation')))
+ .forEach((attach) => {
+ const data = new FormData();
+ data.append('updated_svg_string', attach.updatedAnnotation);
+ updateTasks.push(fetch(`/api/v1/attachments/${attach.id}/annotation`, {
+ credentials: 'same-origin',
+ method: 'post',
+ body: data
+ })
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ }));
+ });
+
+ return Promise.all(updateTasks);
+ }
+
+ static updateAnnotations(element) {
+ return Promise.all(
+ [
+ BaseFetcher.updateAnnotationsOfAttachments(element),
+ BaseFetcher.updateAnnotationsInContainer(element, [])
+ ]
+ );
+ }
}
diff --git a/app/packs/src/fetchers/CellLinesFetcher.js b/app/packs/src/fetchers/CellLinesFetcher.js
new file mode 100644
index 0000000000..1d3079f223
--- /dev/null
+++ b/app/packs/src/fetchers/CellLinesFetcher.js
@@ -0,0 +1,154 @@
+import CellLine from 'src/models/cellLine/CellLine';
+import BaseFetcher from 'src/fetchers/BaseFetcher';
+import AttachmentFetcher from 'src/fetchers/AttachmentFetcher';
+import GenericElsFetcher from 'src/fetchers/GenericElsFetcher';
+import NotificationActions from 'src/stores/alt/actions/NotificationActions';
+
+import {
+ extractApiParameter
+
+} from 'src/utilities/CellLineUtils';
+
+const successfullyCreatedParameter = {
+ title: 'Element created',
+ message: 'Cell line sample successfully added',
+ level: 'info',
+ dismissible: 'button',
+ autoDismiss: 10,
+ position: 'tr'
+};
+
+const successfullyUpdatedParameter = {
+ title: 'Element updated',
+ message: 'Cell line sample successfully updated',
+ level: 'info',
+ dismissible: 'button',
+ autoDismiss: 10,
+ position: 'tr'
+};
+
+const errorMessageParameter = {
+ title: 'Error',
+ message: 'Unfortunately, the last action failed. Please try again or contact your admin.',
+ level: 'error',
+ dismissible: 'button',
+ autoDismiss: 30,
+ position: 'tr'
+};
+
+export default class CellLinesFetcher {
+
+ static fetchByCollectionId(id, queryParams = {}, isSync = false) {
+ return BaseFetcher.fetchByCollectionId(id, queryParams, isSync, 'cell_lines', CellLine);
+ }
+
+ static fetchById(id) {
+ const promise = fetch(`/api/v1/cell_lines/${id}`, {
+ credentials: 'same-origin',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ method: 'GET'
+ })
+ .then((response) => response.json())
+ .then((json) => CellLine.createFromRestResponse(0, json))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ return promise;
+ }
+
+ static create(cellLine,user) {
+ const params = extractApiParameter(cellLine);
+
+ const promise = CellLinesFetcher.uploadAttachments(cellLine)
+ .then(() => fetch('/api/v1/cell_lines', {
+ credentials: 'same-origin',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ method: 'POST',
+ body: JSON.stringify(params)
+ }))
+
+ .then((response) => response.json())
+ .then((json) => { GenericElsFetcher.uploadGenericFiles(cellLine, json.id, 'CellLineSample'); return json; })
+ .then((json) => CellLine.createFromRestResponse(params.collection_id, json))
+ .then((cellLineItem) => {
+ NotificationActions.add(successfullyCreatedParameter);
+ user.cell_lines_count = user.cell_lines_count +1;
+ return cellLineItem;
+ })
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ NotificationActions.add(errorMessageParameter);
+ return cellLine;
+ });
+
+ return promise;
+ }
+
+ static uploadAttachments(cellLine) {
+ const files = AttachmentFetcher.getFileListfrom(cellLine.container);
+
+ if (files.length > 0) {
+ const tasks = [];
+ files.forEach((file) => tasks.push(AttachmentFetcher.uploadFile(file).then()));
+ return Promise.all(tasks).then(() => {
+ Promise.resolve(1);
+ });
+ }
+ return Promise.resolve(1);
+ }
+
+ static getAllCellLineNames() {
+ return fetch('/api/v1/cell_lines/names/all', {
+ credentials: 'same-origin',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ method: 'GET'
+ }).then((response) => response.json());
+ }
+
+ static getCellLineMaterialById(id) {
+ return fetch(`/api/v1/cell_lines/material/${id}`, {
+ credentials: 'same-origin',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ method: 'GET'
+ }).then((response) => response.json());
+ }
+
+ static update(cellLineItem) {
+ const params = extractApiParameter(cellLineItem);
+ const promise = CellLinesFetcher.uploadAttachments(cellLineItem)
+ .then(() => fetch('/api/v1/cell_lines', {
+ credentials: 'same-origin',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ method: 'PUT',
+ body: JSON.stringify(params)
+ }))
+ .then((response) => response.json())
+ .then(() => {BaseFetcher.updateAnnotationsInContainer(cellLineItem)})
+ .then(()=> CellLinesFetcher.fetchById(cellLineItem.id))
+ .then((loadedCellLineSample) => {
+ NotificationActions.add(successfullyUpdatedParameter);
+ return loadedCellLineSample;
+ })
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ NotificationActions.add(errorMessageParameter);
+ return cellLineItem;
+ });
+ return promise;
+ }
+}
diff --git a/app/packs/src/fetchers/ChemSpectraFetcher.js b/app/packs/src/fetchers/ChemSpectraFetcher.js
new file mode 100644
index 0000000000..e348a1a378
--- /dev/null
+++ b/app/packs/src/fetchers/ChemSpectraFetcher.js
@@ -0,0 +1,45 @@
+import { SPECTRA_DATA_TYPE } from 'src/endpoints/ApiServices';
+import 'whatwg-fetch';
+
+export default class ChemSpectraFetcher {
+ static fetchSpectraLayouts() {
+ return fetch('/api/v1/chemspectra/spectra_layouts', {
+ method: 'GET',
+ credentials: 'same-origin',
+ }).then((response) => {
+ if (response.ok) {
+ return response.json();
+ }
+ return null;
+ })
+ .then((data) => data)
+ .catch((errorMessage) => { console.error(errorMessage); });
+ }
+
+ static updateDataTypes(newDataTypes) {
+ const requestData = { datatypes: newDataTypes };
+
+ return fetch('/api/v1/admin/data_types.json', {
+ credentials: 'same-origin',
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(requestData)
+ }).then((response) => {
+ if (!response.ok) { throw response; }
+ return response.json();
+ });
+ }
+
+ static fetchUpdatedSpectraLayouts() {
+ return fetch(SPECTRA_DATA_TYPE)
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error('Failed to fetch JSON');
+ }
+ return response.json();
+ })
+ .then((data) => Object.entries(data.datatypes));
+ }
+}
diff --git a/app/packs/src/fetchers/ChemicalFetcher.js b/app/packs/src/fetchers/ChemicalFetcher.js
index fea51082d4..1ed7eab985 100644
--- a/app/packs/src/fetchers/ChemicalFetcher.js
+++ b/app/packs/src/fetchers/ChemicalFetcher.js
@@ -40,7 +40,9 @@ export default class ChemicalFetcher {
}
static fetchSafetySheets(queryParams) {
- return fetch(`/api/v1/chemicals/fetch_safetysheet/${queryParams.id}?data[vendor]=${queryParams.vendor}&data[option]=${queryParams.queryOption}&data[language]=${queryParams.language}&data[searchStr]=${queryParams.string}`, {
+ return fetch(`/api/v1/chemicals/fetch_safetysheet/${queryParams.id}`
+ + `?data[vendor]=${queryParams.vendor}&data[option]=${queryParams.queryOption}`
+ + `&data[language]=${queryParams.language}&data[searchStr]=${queryParams.string}`, {
credentials: 'same-origin',
method: 'GET',
headers: {
@@ -51,8 +53,10 @@ export default class ChemicalFetcher {
if (response.ok) {
return response.text();
}
+ return null;
}).catch((errorMessage) => {
console.log(errorMessage);
+ return null;
});
}
diff --git a/app/packs/src/fetchers/CollectionsFetcher.js b/app/packs/src/fetchers/CollectionsFetcher.js
index 3f6d2867b8..6c54a61f79 100644
--- a/app/packs/src/fetchers/CollectionsFetcher.js
+++ b/app/packs/src/fetchers/CollectionsFetcher.js
@@ -14,18 +14,6 @@ export default class CollectionsFetcher {
return promise;
}
- static fetchGenericEls() {
- const promise = fetch('/api/v1/collections/locked.json', {
- credentials: 'same-origin'
- })
- .then(response => response.json()).then((json) => {
- return json;
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
- return promise;
- }
-
static fetchLockedRoots() {
return BaseFetcher.withoutBodyData({
apiEndpoint: '/api/v1/collections/locked.json',
@@ -319,4 +307,51 @@ export default class CollectionsFetcher {
throw new Error(response.status);
}).catch((errorMessage) => { console.log(errorMessage); });
}
+
+ static fetchTabsLayout(params) {
+ let promise = fetch('/api/v1/collections/tab_segments/' + params.id, {
+ credentials: 'same-origin'
+ })
+ .then((response) => {
+ return response.json()
+ }).then((json) => {
+ return json;
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+
+ return promise;
+ }
+
+ static createTabsSegment(params) {
+ return fetch('/api/v1/collections/tabs/', {
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ id: params.currentCollectionId,
+ segments: params.layoutSegments
+ })
+ }).then(response => response)
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
+
+ static updateTabsLayout(params) {
+ return fetch('/api/v1/collections/tabs/', {
+ credentials: 'same-origin',
+ method: 'PATCH',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ id: params.cId,
+ segment: params.segment
+ })
+ }).then(response => response)
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
}
diff --git a/app/packs/src/fetchers/CommentFetcher.js b/app/packs/src/fetchers/CommentFetcher.js
new file mode 100644
index 0000000000..6bf2b3f957
--- /dev/null
+++ b/app/packs/src/fetchers/CommentFetcher.js
@@ -0,0 +1,72 @@
+import 'whatwg-fetch';
+
+import Comment from 'src/models/Comment';
+import { CommentManagementServices } from 'src/endpoints/ApiServices';
+
+const classify = (string) => {
+ const elementType = string.replace(/([-_]\w)/g, (g) => g[1].toUpperCase());
+ return elementType.charAt(0).toUpperCase() + elementType.slice(1);
+};
+const headers = {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+};
+
+export default class CommentFetcher {
+ static fetchById(commentId) {
+ return fetch(CommentManagementServices.COMMENT_BY_ID(commentId), {
+ credentials: 'same-origin'
+ }).then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
+
+ static fetchByCommentableId(commentableId, commentableType) {
+ return fetch(
+ CommentManagementServices.COMMENT_BY_COMMENTABLE(
+ commentableId,
+ classify(commentableType)
+ ),
+ {
+ credentials: 'same-origin',
+ }
+ ).then((response) => response.json())
+ .then((json) => json.comments.map((comment) => new Comment(comment)))
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
+
+ static create(prms) {
+ const params = { ...prms };
+ if (prms.commentable_type) {
+ params.commentable_type = classify(prms.commentable_type);
+ }
+ return fetch(CommentManagementServices.CREATE_COMMENT, {
+ credentials: 'same-origin',
+ method: 'post',
+ headers,
+ body: JSON.stringify(params)
+ }).then((response) => response.json())
+ .then((json) => new Comment(json.comment))
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
+
+ static updateComment(comment, params) {
+ return fetch(CommentManagementServices.UPDATE_COMMENT(comment), {
+ credentials: 'same-origin',
+ method: 'put',
+ headers,
+ body: JSON.stringify(params)
+ }).then((response) => response.json())
+ .then((json) => new Comment(json.comment))
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
+
+ static delete(comment) {
+ return fetch(CommentManagementServices.DELETE_COMMENT(comment), {
+ credentials: 'same-origin',
+ method: 'delete',
+ headers
+ }).then((response) => response.json())
+ .catch((errorMessage) => { console.log(errorMessage); });
+ }
+}
diff --git a/app/packs/src/fetchers/GenericBaseFetcher.js b/app/packs/src/fetchers/GenericBaseFetcher.js
index 8d07f4ae4b..aab9f665b0 100644
--- a/app/packs/src/fetchers/GenericBaseFetcher.js
+++ b/app/packs/src/fetchers/GenericBaseFetcher.js
@@ -3,63 +3,120 @@ import 'whatwg-fetch';
export default class GenericBaseFetcher {
static exec(path, method) {
return fetch(`/api/v1/${path}`, { credentials: 'same-origin', method })
- .then(response => response.json()).then(json => json).catch((errorMessage) => {
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
console.log(errorMessage);
});
}
static execData(params, path, method = 'POST') {
- console.log(`/api/v1/${path}`);
return fetch(`/api/v1/${path}`, {
- credentials: 'same-origin', method, headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(params)
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ credentials: 'same-origin',
+ method,
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(params),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static deActivateKlass(params) {
return fetch('/api/v1/generic_elements/de_activate_klass', {
- credentials: 'same-origin', method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(params)
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(params),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static deleteKlass(params) {
return fetch(`/api/v1/generic_elements/delete_klass/${params.id}`, {
- credentials: 'same-origin', method: 'DELETE', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(params)
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ credentials: 'same-origin',
+ method: 'DELETE',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(params),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static deleteKlassRevision(params) {
return fetch('/api/v1/generic_elements/delete_klass_revision', {
- credentials: 'same-origin', method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(params)
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(params),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static fetchKlassRevisions(id, klass) {
- return fetch(`/api/v1/generic_elements/klass_revisions.json?id=${id}&klass=${klass}`, { credentials: 'same-origin' })
- .then(response => response.json()).then(json => json).catch((errorMessage) => {
+ return fetch(
+ `/api/v1/generic_elements/klass_revisions.json?id=${id}&klass=${klass}`,
+ { credentials: 'same-origin' }
+ )
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
console.log(errorMessage);
});
}
static fetchUnitsSystem() {
- return fetch('/units_system/units_system.json', { credentials: 'same-origin', cache: 'no-store', headers: { 'cache-control': 'no-cache' } })
- .then(response => response.json()).then(json => json).catch((errorMessage) => {
+ return fetch('/units_system/units_system.json', {
+ credentials: 'same-origin',
+ cache: 'no-store',
+ headers: { 'cache-control': 'no-cache' },
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
console.log(errorMessage);
});
}
static updateTemplate(params) {
return fetch('/api/v1/generic_elements/update_template', {
- credentials: 'same-origin', method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(params)
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(params),
+ })
+ .then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
}
diff --git a/app/packs/src/fetchers/GenericDSsFetcher.js b/app/packs/src/fetchers/GenericDSsFetcher.js
index a86962ed8b..8521651226 100644
--- a/app/packs/src/fetchers/GenericDSsFetcher.js
+++ b/app/packs/src/fetchers/GenericDSsFetcher.js
@@ -1,20 +1,38 @@
import GenericBaseFetcher from 'src/fetchers/GenericBaseFetcher';
export default class GenericDSsFetcher extends GenericBaseFetcher {
- static exec(path, method) { return super.exec(`generic_dataset/${path}`, method); }
+ static exec(path, method) {
+ return super.exec(`generic_dataset/${path}`, method);
+ }
+
+ static execData(params, path) {
+ return super.execData(params, `generic_dataset/${path}`);
+ }
- static execData(params, path) { return super.execData(params, `generic_dataset/${path}`); }
+ static fetchRepo() {
+ return this.exec('fetch_repo', 'GET');
+ }
+
+ static createRepo(params) {
+ return this.execData(params, 'create_repo_klass');
+ }
static fetchKlass() {
return this.exec('klasses.json', 'GET');
}
static listDatasetKlass(params = {}) {
- const api = params.is_active === undefined ? 'list_dataset_klass.json' : `list_dataset_klass.json?is_active=${params.is_active}`;
+ const api =
+ params.is_active === undefined
+ ? 'list_dataset_klass.json'
+ : `list_dataset_klass.json?is_active=${params.is_active}`;
return this.exec(api, 'GET');
}
static updateDatasetTemplate(params) {
- return super.updateTemplate({ ...params, klass: 'DatasetKlass' }, 'update_dataset_template');
+ return super.updateTemplate(
+ { ...params, klass: 'DatasetKlass' },
+ 'update_dataset_template'
+ );
}
}
diff --git a/app/packs/src/fetchers/GenericElsFetcher.js b/app/packs/src/fetchers/GenericElsFetcher.js
index 2934a0264b..6c8b92b3ee 100644
--- a/app/packs/src/fetchers/GenericElsFetcher.js
+++ b/app/packs/src/fetchers/GenericElsFetcher.js
@@ -2,43 +2,77 @@ import 'whatwg-fetch';
import GenericEl from 'src/models/GenericEl';
import AttachmentFetcher from 'src/fetchers/AttachmentFetcher';
import BaseFetcher from 'src/fetchers/BaseFetcher';
+import GenericBaseFetcher from 'src/fetchers/GenericBaseFetcher';
-export default class GenericElsFetcher {
- static fetchElementKlass(klassName) {
- return fetch(`/api/v1/generic_elements/klass.json?name=${klassName}`, {
- credentials: 'same-origin'
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
+export default class GenericElsFetcher extends GenericBaseFetcher {
+ static exec(path, method) {
+ return super.exec(`generic_elements/${path}`, method);
+ }
+
+ static execData(params, path) {
+ return super.execData(params, `generic_elements/${path}`);
}
static fetchByCollectionId(id, queryParams = {}, isSync = false) {
- return BaseFetcher.fetchByCollectionId(id, queryParams, isSync, 'generic_elements', GenericEl);
+ return BaseFetcher.fetchByCollectionId(
+ id,
+ queryParams,
+ isSync,
+ 'generic_elements',
+ GenericEl
+ );
}
static fetchById(id) {
const promise = fetch(`/api/v1/generic_elements/${id}.json`, {
- credentials: 'same-origin'
+ credentials: 'same-origin',
})
- .then(response => response.json()).then((json) => {
+ .then((response) => response.json())
+ .then((json) => {
const genericEl = new GenericEl(json.element);
genericEl.attachments = json.attachments;
if (json.error) {
- genericEl.type = null; // `${id}:error:GenericEl ${id} is not accessible!`;
+ genericEl.type = null;
}
return genericEl;
- }).catch((errorMessage) => {
+ })
+ .catch((errorMessage) => {
console.log(errorMessage);
});
return promise;
}
- static uploadGenericFiles(element, id, type, hasAttach = false, isElement = false) {
- const segFiles = (element.segments || []).filter(seg => seg.files && seg.files.length > 0).length === 0;
- if (!isElement && !hasAttach && segFiles === true) return Promise.resolve(true);
- if (isElement && segFiles === true && (typeof element.files === 'undefined' || (element.files || []).length === 0)
- && (typeof element.attachments === 'undefined' || (element.attachments || []).length === 0)) return Promise.resolve(true);
- if (!isElement && hasAttach && segFiles === true && (element.attachments || []).length === 0) return Promise.resolve(true);
+ static uploadGenericFiles(
+ element,
+ id,
+ type,
+ hasAttach = false,
+ isElement = false
+ ) {
+ const segFiles = (element.segments || []).filter(
+ (seg) => seg.files && seg.files.length > 0
+ ).length === 0;
+ if (!isElement && !hasAttach && segFiles === true) {
+ return Promise.resolve(true);
+ }
+ if (
+ isElement
+ && segFiles === true
+ && (typeof element.files === 'undefined'
+ || (element.files || []).length === 0)
+ && (typeof element.attachments === 'undefined'
+ || (element.attachments || []).length === 0)
+ ) {
+ return Promise.resolve(true);
+ }
+ if (
+ !isElement
+ && hasAttach
+ && segFiles === true
+ && (element.attachments || []).length === 0
+ ) {
+ return Promise.resolve(true);
+ }
const data = new FormData();
data.append('att_id', id);
@@ -54,56 +88,68 @@ export default class GenericElsFetcher {
});
data.append('elInfo', JSON.stringify(elMap));
}
- if (hasAttach === true && element.attachments && element.attachments.length > 0) {
- const newFiles = (element.attachments || []).filter(a => a.is_new && !a.is_deleted);
- const delFiles = (element.attachments || []).filter(a => !a.is_new && a.is_deleted);
- (newFiles || []).forEach((file) => {
- data.append('attfiles[]', file.file, file.name);
- data.append('attfilesIdentifier[]', file.id);
- });
- (delFiles || []).forEach((f) => {
- data.append('delfiles[]', f.id);
- });
+
+ if (GenericElsFetcher.shouldUploadAttachments(hasAttach, element)) {
+ GenericElsFetcher.prepareAttachmentParam(element, data);
}
+
(element.segments || []).forEach((segment) => {
- segMap[segment.segment_klass_id] = { type: 'SegmentProps', id, files: [] };
+ segMap[segment.segment_klass_id] = {
+ type: 'SegmentProps',
+ id,
+ files: [],
+ };
(segment.files || []).forEach((file) => {
data.append('sefiles[]', file.file.file, file.uid);
- segMap[segment.segment_klass_id].files.push({ uid: file.uid, filename: file.file.name });
+ segMap[segment.segment_klass_id].files.push({
+ uid: file.uid,
+ filename: file.file.name,
+ });
});
});
data.append('seInfo', JSON.stringify(segMap));
return fetch('/api/v1/generic_elements/upload_generics_files', {
credentials: 'same-origin',
method: 'post',
- body: data
- }).then(response => response).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ body: data,
+ })
+ .then((response) => response)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static updateOrCreate(genericEl, action = 'create') {
const files = AttachmentFetcher.getFileListfrom(genericEl.container);
const method = action === 'create' ? 'post' : 'put';
- const api = action === 'create' ? '/api/v1/generic_elements/' : `/api/v1/generic_elements/${genericEl.id}`;
+ const api = action === 'create'
+ ? '/api/v1/generic_elements/'
+ : `/api/v1/generic_elements/${genericEl.id}`;
const promise = () => fetch(api, {
credentials: 'same-origin',
method,
- headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
- body: JSON.stringify(genericEl.serialize())
- }).then(response => response.json())
- .then(json => GenericElsFetcher.uploadGenericFiles(genericEl, json.element.id, 'Element', true, true)
- .then(() => this.fetchById(json.element.id)))
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(genericEl.serialize()),
+ })
+ .then((response) => response.json())
+ .then((json) => GenericElsFetcher.uploadGenericFiles(
+ genericEl,
+ json.element.id,
+ 'Element',
+ true,
+ true
+ ).then(() => this.fetchById(json.element.id)))
.catch((errorMessage) => {
console.log(errorMessage);
});
if (files.length > 0) {
- let tasks = [];
- files.forEach(file => tasks.push(AttachmentFetcher.uploadFile(file).then()));
- return Promise.all(tasks).then(() => {
- return promise();
- });
+ const tasks = [];
+ files.forEach((file) => tasks.push(AttachmentFetcher.uploadFile(file).then()));
+ return Promise.all(tasks).then(() => promise());
}
return promise();
}
@@ -116,21 +162,69 @@ export default class GenericElsFetcher {
return this.updateOrCreate(genericEl, 'create');
}
+ static createElementKlass(params) {
+ return this.execData(params, 'create_element_klass');
+ }
+
static fetchElementRevisions(id) {
- return BaseFetcher.withoutBodyData({
- apiEndpoint: `/api/v1/generic_elements/element_revisions.json?id=${id}`, requestMethod: 'GET', jsonTranformation: json => json
- });
+ return this.exec(`element_revisions.json?id=${id}`, 'GET');
+ }
+
+ static fetchSegmentRevisions(id) {
+ return this.exec(`segment_revisions.json?id=${id}`, 'GET');
+ }
+
+ static fetchElementKlasses() {
+ return this.exec('klasses_all.json', 'GET');
+ }
+
+ static fetchElementKlass(klassName) {
+ return this.exec(`klass.json?name=${klassName}`, 'GET');
}
static deleteRevisions(params) {
- return BaseFetcher.withBodyData({
- apiEndpoint: '/api/v1/generic_elements/delete_revision', requestMethod: 'POST', bodyData: params, jsonTranformation: json => json
- });
+ return this.execData(params, 'delete_revision');
}
- static fetchSegmentRevisions(id) {
- return BaseFetcher.withoutBodyData({
- apiEndpoint: `/api/v1/generic_elements/segment_revisions.json?id=${id}`, requestMethod: 'GET', jsonTranformation: json => json
+ static updateElementKlass(params) {
+ return this.execData(params, 'update_element_klass');
+ }
+
+ static updateElementTemplate(params) {
+ return super.updateTemplate(
+ { ...params, klass: 'ElementKlass' },
+ 'update_element_template'
+ );
+ }
+
+ static fetchRepo() {
+ return this.exec('fetch_repo', 'GET');
+ }
+
+ static createRepo(params) {
+ return this.execData(params, 'create_repo_klass');
+ }
+
+ static prepareAttachmentParam(element, data) {
+ const newFiles = (element.attachments || []).filter(
+ (a) => a.is_new && !a.is_deleted
+ );
+ const delFiles = (element.attachments || []).filter(
+ (a) => !a.is_new && a.is_deleted
+ );
+ (newFiles || []).forEach((file) => {
+ data.append('attfiles[]', file.file, file.name);
+ data.append('attfilesIdentifier[]', file.id);
+ });
+ (delFiles || []).forEach((f) => {
+ data.append('delfiles[]', f.id);
});
}
+
+ static shouldUploadAttachments(hasAttach, element) {
+ return hasAttach === true
+ && element.attachments
+ && element.attachments.length > 0
+ && element.type !== 'research_plan';
+ }
}
diff --git a/app/packs/src/fetchers/GenericSgsFetcher.js b/app/packs/src/fetchers/GenericSgsFetcher.js
new file mode 100644
index 0000000000..a331afa992
--- /dev/null
+++ b/app/packs/src/fetchers/GenericSgsFetcher.js
@@ -0,0 +1,56 @@
+import GenericBaseFetcher from 'src/fetchers/GenericBaseFetcher';
+
+export default class GenericSgsFetcher extends GenericBaseFetcher {
+ static exec(path, method) {
+ return super.exec(`segments/${path}`, method);
+ }
+
+ static execData(params, path) {
+ return super.execData(params, `segments/${path}`);
+ }
+
+ static fetchRepo() {
+ return this.exec('fetch_repo', 'GET');
+ }
+
+ static createRepo(params) {
+ return this.execData(params, 'create_repo_klass');
+ }
+
+ static createKlass(params) {
+ return this.execData(params, 'create_segment_klass');
+ }
+
+ static fetchKlass(elementName = null) {
+ const api = elementName == null
+ ? 'klasses.json'
+ : `klasses.json?element=${elementName}`;
+ return this.exec(api, 'GET');
+ }
+
+ static fetchRepoKlassList() {
+ return this.exec('fetch_repo_generic_template_list', 'GET');
+ }
+
+ static listSegmentKlass(params = {}) {
+ const api = params.is_active === undefined
+ ? 'list_segment_klass.json'
+ : `list_segment_klass.json?is_active=${params.is_active}`;
+ return this.exec(api, 'GET');
+ }
+
+ static syncTemplate(params) {
+ return this.execData(params, 'fetch_repo_generic_template');
+ }
+
+ static updateSegmentKlass(params) {
+ return this.execData(params, 'update_segment_klass');
+ }
+
+ static updateSegmentTemplate(params) {
+ return super.updateTemplate(
+ { ...params, klass: 'SegmentKlass' },
+ 'update_segment_template'
+ );
+ }
+}
diff --git a/app/packs/src/fetchers/InboxFetcher.js b/app/packs/src/fetchers/InboxFetcher.js
index 5f0022c25c..eb5959ede0 100644
--- a/app/packs/src/fetchers/InboxFetcher.js
+++ b/app/packs/src/fetchers/InboxFetcher.js
@@ -1,6 +1,15 @@
+import UserStore from 'src/stores/alt/stores/UserStore';
+
export default class InboxFetcher {
static fetchInbox(isCntOnly = false, queryParams = {}) {
- const promise = fetch(`/api/v1/inbox?cnt_only=${isCntOnly}&page=${queryParams.currentPage || 1}&per_page=${queryParams.itemsPerPage || 20}`, {
+ const userState = UserStore.getState();
+ const filters = userState?.profile?.data?.filters || {};
+ const sortColumn = filters.inbox?.sort || 'name';
+
+ // if the user has not updated its profile yet, we set the default sort to name
+ const addQuery = `&sort_column=${filters.inbox ? sortColumn : 'name'}`;
+
+ const promise = fetch(`/api/v1/inbox?cnt_only=${isCntOnly}&page=${queryParams.currentPage || 1}&per_page=${queryParams.itemsPerPage || 20}${addQuery}`, {
credentials: 'same-origin'
})
.then(response => response.json())
@@ -13,7 +22,27 @@ export default class InboxFetcher {
}
static fetchInboxByContainer(containerId, currentContainerPage) {
- const promise = fetch(`/api/v1/inbox/containers/${containerId}?dataset_page=${currentContainerPage || 1}`, {
+ const userState = UserStore.getState();
+ const filters = userState?.profile?.data?.filters || {};
+ const sortColumn = filters.inbox?.sort || 'name';
+
+ // if the user has not updated its profile yet, we set the default sort to name
+ const addQuery = `&sort_column=${filters.inbox ? sortColumn : 'name'}`;
+
+ const promise = fetch(`/api/v1/inbox/containers/${containerId}?dataset_page=${currentContainerPage || 1}${addQuery}`, {
+ credentials: 'same-origin'
+ })
+ .then(response => response.json())
+ .then(json => json)
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+
+ return promise;
+ }
+
+ static fetchInboxUnsorted() {
+ const promise = fetch('/api/v1/inbox/unlinked_attachments', {
credentials: 'same-origin'
})
.then(response => response.json())
diff --git a/app/packs/src/fetchers/InventoryFetcher.js b/app/packs/src/fetchers/InventoryFetcher.js
new file mode 100644
index 0000000000..a4f4d8a951
--- /dev/null
+++ b/app/packs/src/fetchers/InventoryFetcher.js
@@ -0,0 +1,32 @@
+import 'whatwg-fetch';
+
+export default class InventoryFetcher {
+ static updateInventoryLabel(params) {
+ const promise = fetch('/api/v1/inventory/update_inventory_label', {
+ credentials: 'same-origin',
+ method: 'PUT',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(params)
+ }).then((response) => response.json()).then((json) => json).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ return promise;
+ }
+
+ static fetchLabelsAndCollections() {
+ const promise = fetch('/api/v1/inventory/user_inventory_collections', {
+ credentials: 'same-origin',
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ }).then((response) => response.json()).then((json) => json).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ return promise;
+ }
+}
diff --git a/app/packs/src/fetchers/LiteraturesFetcher.js b/app/packs/src/fetchers/LiteraturesFetcher.js
index d4a4f0b002..722139739a 100644
--- a/app/packs/src/fetchers/LiteraturesFetcher.js
+++ b/app/packs/src/fetchers/LiteraturesFetcher.js
@@ -5,15 +5,15 @@ import Literature from 'src/models/Literature';
export default class LiteraturesFetcher {
static fetchElementReferences(element) {
if (!element || element.isNew) {
- return Promise.resolve(Immutable.List())
+ return Promise.resolve(Immutable.List());
}
const { type, id } = element;
return fetch(`/api/v1/literatures?element_type=${type}&element_id=${id}`, {
credentials: 'same-origin'
- }).then(response => response.json())
- .then(json => json.literatures)
- .then(literatures => literatures.map(literature => new Literature(literature)))
- .then(lits => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
+ }).then((response) => response.json())
+ .then((json) => json.literatures)
+ .then((literatures) => literatures.map((literature) => new Literature(literature)))
+ .then((lits) => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
.catch((errorMessage) => { console.log(errorMessage); });
}
@@ -21,7 +21,7 @@ export default class LiteraturesFetcher {
const { element, literature } = params;
const { type, id } = element;
if (!element || element.isNew) {
- return Promise.resolve(Immutable.List())
+ return Promise.resolve(Immutable.List());
}
return fetch('/api/v1/literatures', {
credentials: 'same-origin',
@@ -31,10 +31,10 @@ export default class LiteraturesFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify({ element_type: type, element_id: id, ref: literature })
- }).then(response => response.json())
+ }).then((response) => response.json())
.then((json) => { if (json.error) { throw json; } return json.literatures; })
- .then(literatures => literatures.map(lits => new Literature(lits)))
- .then(lits => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
+ .then((literatures) => literatures.map((lits) => new Literature(lits)))
+ .then((lits) => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
.catch((errorMessage) => { console.log(errorMessage); throw errorMessage; });
}
@@ -42,13 +42,23 @@ export default class LiteraturesFetcher {
const { element, literature } = params;
const { type, id } = element;
const refId = literature.literal_id;
- return fetch(`/api/v1/literatures?id=${refId}&element_type=${type}&element_id=${id}`, {
+
+ const urlParams = new URLSearchParams({
+ id: refId,
+ element_type: type,
+ element_id: id
+ });
+
+ const requestParams = {
credentials: 'same-origin',
method: 'delete',
headers: {
Accept: 'application/json',
},
- }).then(response => response.json())
+ };
+
+ return fetch(`/api/v1/literatures?${urlParams}`, requestParams)
+ .then((response) => (response.status === 200 ? {} : response.json()))
.then((json) => { if (json.error) { throw json; } })
.catch((errorMessage) => { throw errorMessage; });
}
@@ -62,24 +72,24 @@ export default class LiteraturesFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
- }).then(response => response.json())
+ }).then((response) => response.json())
.then((json) => { if (json.error) { throw json; } return json.literatures; })
- .then(literatures => literatures.map(lits => new Literature(lits)))
- .then(lits => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
+ .then((literatures) => literatures.map((lits) => new Literature(lits)))
+ .then((lits) => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
.catch((errorMessage) => { console.log(errorMessage); throw errorMessage; });
}
static fetchDOIMetadata(doi) {
return fetch(`/api/v1/literatures/doi/metadata?doi=${encodeURIComponent(doi)}`, {
credentials: 'same-origin',
- }).then(response => response.json())
+ }).then((response) => response.json())
.catch((errorMessage) => { console.log(errorMessage); });
}
static fetchReferencesByCollection(params) {
return fetch(`/api/v1/literatures/collection?id=${params.id}&is_sync_to_me=${params.is_sync_to_me || false}`, {
credentials: 'same-origin',
- }).then(response => response.json())
+ }).then((response) => response.json())
.then((json) => {
const {
collectionRefs,
@@ -88,27 +98,27 @@ export default class LiteraturesFetcher {
researchPlanRefs,
} = json;
return {
- collectionRefs: Immutable.List(collectionRefs.map(lit => new Literature(lit))),
- sampleRefs: Immutable.List(sampleRefs.map(lit => new Literature(lit))),
- reactionRefs: Immutable.List(reactionRefs.map(lit => new Literature(lit))),
- researchPlanRefs: Immutable.List(researchPlanRefs.map(lit => new Literature(lit))),
+ collectionRefs: Immutable.List(collectionRefs.map((lit) => new Literature(lit))),
+ sampleRefs: Immutable.List(sampleRefs.map((lit) => new Literature(lit))),
+ reactionRefs: Immutable.List(reactionRefs.map((lit) => new Literature(lit))),
+ researchPlanRefs: Immutable.List(researchPlanRefs.map((lit) => new Literature(lit))),
};
})
.catch((errorMessage) => { console.log(errorMessage); });
}
static postReferencesByUIState(params, method = 'post') {
- return fetch(`/api/v1/literatures/ui_state`, {
+ return fetch('/api/v1/literatures/ui_state', {
credentials: 'same-origin',
method,
headers: {
- 'Accept': 'application/json',
+ Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
- }).then(response => response.json())
- .then(json => json.selectedRefs.map(lit => new Literature(lit)))
- .then(lits => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
+ }).then((response) => response.json())
+ .then((json) => json.selectedRefs.map((lit) => new Literature(lit)))
+ .then((lits) => lits.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map()))
.catch((errorMessage) => { console.log(errorMessage); });
}
}
diff --git a/app/packs/src/fetchers/PrivateNoteFetcher.js b/app/packs/src/fetchers/PrivateNoteFetcher.js
index 37a8cd7511..41e618ff5b 100644
--- a/app/packs/src/fetchers/PrivateNoteFetcher.js
+++ b/app/packs/src/fetchers/PrivateNoteFetcher.js
@@ -39,7 +39,7 @@ export default class PrivateNoteFetcher {
if (prms.noteable_type) {
params.noteable_type = classify(prms.noteable_type);
}
- return fetch('/api/v1/private_notes/create', {
+ return fetch('/api/v1/private_notes', {
credentials: 'same-origin',
method: 'post',
headers: {
diff --git a/app/packs/src/fetchers/ReactionsFetcher.js b/app/packs/src/fetchers/ReactionsFetcher.js
index ac1fb5455f..4d5ed60e7a 100644
--- a/app/packs/src/fetchers/ReactionsFetcher.js
+++ b/app/packs/src/fetchers/ReactionsFetcher.js
@@ -6,32 +6,43 @@ import Reaction from 'src/models/Reaction';
import AttachmentFetcher from 'src/fetchers/AttachmentFetcher';
import Literature from 'src/models/Literature';
import GenericElsFetcher from 'src/fetchers/GenericElsFetcher';
+import ResearchPlansFetcher from 'src/fetchers/ResearchPlansFetcher';
// TODO: Extract common base functionality into BaseFetcher
export default class ReactionsFetcher {
- static fetchById(id) {
- return fetch(`/api/v1/reactions/${id}.json`, {
- credentials: 'same-origin'
- }).then(response => response.json())
- .then((json) => {
- if (json.hasOwnProperty("reaction")) {
- const reaction = new Reaction(json.reaction);
- if (json.literatures && json.literatures.length > 0) {
- const tliteratures = json.literatures.map(literature => new Literature(literature));
- const lits = tliteratures.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map());
- reaction.literatures = lits;
+ static async fetchById(id) {
+ try {
+ const response = await fetch(`/api/v1/reactions/${id}.json`, {
+ credentials: 'same-origin'
+ }).then((response) => response.json())
+ .then((json) => {
+ if (json.hasOwnProperty('reaction')) {
+ const reaction = new Reaction(json.reaction);
+ if (json.literatures && json.literatures.length > 0) {
+ const tliteratures = json.literatures.map((literature) => new Literature(literature));
+ const lits = tliteratures.reduce((acc, l) => acc.set(l.literal_id, l), new Immutable.Map());
+ reaction.literatures = lits;
+ }
+ if (json.research_plans && json.research_plans.length > 0) {
+ reaction.research_plans = json.research_plans;
+ }
+ reaction.updateMaxAmountOfProducts();
+ return reaction;
}
- reaction.updateMaxAmountOfProducts();
- return reaction;
- }
- const rReaction = new Reaction(json.reaction);
- if (json.error) {
- rReaction.id = `${id}:error:Reaction ${id} is not accessible!`;
- }
- return rReaction;
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ const rReaction = new Reaction(json.reaction);
+ if (json.error) {
+ rReaction.id = `${id}:error:Reaction ${id} is not accessible!`;
+ }
+ return rReaction;
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ const researchPlans = await ResearchPlansFetcher.fetchResearchPlansForElements(id, response.type);
+ response.research_plans = researchPlans;
+ return response;
+ } catch (error) {
+ console.error(error);
+ }
}
static fetchByCollectionId(id, queryParams = {}, isSync = false) {
@@ -45,7 +56,7 @@ export default class ReactionsFetcher {
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' }
}
- ).then((response) => response.json()).catch(errorMessage => console.log(errorMessage))
+ ).then((response) => response.json()).catch((errorMessage) => console.log(errorMessage));
}
static create(reaction, method = 'post') {
@@ -65,31 +76,29 @@ export default class ReactionsFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(reaction.serialize())
- }).then(response => response.json())
- .then(json => GenericElsFetcher.uploadGenericFiles(reaction, json.reaction.id, 'Reaction')
- .then(()=> ReactionsFetcher.updateAnnotationsInReaction(reaction))
+ }).then((response) => response.json())
+ .then((json) => GenericElsFetcher.uploadGenericFiles(reaction, json.reaction.id, 'Reaction')
+ .then(() => ReactionsFetcher.updateAnnotationsInReaction(reaction))
.then(() => this.fetchById(json.reaction.id))).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ console.log(errorMessage);
+ });
if (allFiles.length > 0) {
- let tasks = [];
- allFiles.forEach(file => tasks.push(AttachmentFetcher.uploadFile(file).then()));
- return Promise.all(tasks).then(() => {
- return promise();
- });
- }
-
+ const tasks = [];
+ allFiles.forEach((file) => tasks.push(AttachmentFetcher.uploadFile(file).then()));
+ return Promise.all(tasks).then(() => promise());
+ }
+
return promise();
- }
+ }
- static updateAnnotationsInReaction(reaction){
- const tasks=[];
- reaction.products.forEach( e => tasks.push(BaseFetcher.updateAnnotationsInContainer(e)));
- return Promise.all(tasks);
+ static updateAnnotationsInReaction(reaction) {
+ const tasks = [];
+ reaction.products.forEach((e) => tasks.push(BaseFetcher.updateAnnotationsInContainer(e)));
+ return Promise.all(tasks);
}
- static update(reaction) {
+ static update(reaction) {
return ReactionsFetcher.create(reaction, 'put');
}
}
diff --git a/app/packs/src/fetchers/ResearchPlansFetcher.js b/app/packs/src/fetchers/ResearchPlansFetcher.js
index f0e8dc21fd..e012633b73 100644
--- a/app/packs/src/fetchers/ResearchPlansFetcher.js
+++ b/app/packs/src/fetchers/ResearchPlansFetcher.js
@@ -32,6 +32,7 @@ export default class ResearchPlansFetcher {
static create(researchPlan) {
researchPlan.convertTemporaryImageFieldsInBody();
+
const promise = fetch('/api/v1/research_plans/', {
credentials: 'same-origin',
method: 'post',
@@ -40,10 +41,18 @@ export default class ResearchPlansFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(researchPlan.serialize())
- }).then((response) => response.json()).then((json) => GenericElsFetcher.uploadGenericFiles(researchPlan, json.research_plan.id, 'ResearchPlan', true)
- .then(() => this.fetchById(json.research_plan.id))).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ })
+ .then((response) => response.json())
+ .then((json) => AttachmentFetcher.updateAttachables(
+ researchPlan.getNewAttachments(),
+ 'ResearchPlan',
+ json.research_plan.id,
+ researchPlan.getMarkedAsDeletedAttachments()
+ )().then(() => GenericElsFetcher.uploadGenericFiles(researchPlan, json.research_plan.id, 'ResearchPlan', true)
+ .then(() => this.fetchById(json.research_plan.id))))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
@@ -59,13 +68,16 @@ export default class ResearchPlansFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(researchPlan.serialize())
- }).then( response => response.json())
- .then((json) =>{ return GenericElsFetcher.uploadGenericFiles(researchPlan, json.research_plan.id, 'ResearchPlan', true)})
- .then(() => {
- return ResearchPlansFetcher.updateAnnotations(researchPlan) })
- .then(() =>{
- return this.fetchById(researchPlan.id)} )
- .catch((errorMessage) => {console.log(errorMessage);});
+ }).then((response) => response.json())
+ .then((json) => AttachmentFetcher.updateAttachables(
+ researchPlan.getNewAttachments(),
+ 'ResearchPlan',
+ json.research_plan.id,
+ researchPlan.getMarkedAsDeletedAttachments()
+ )().then(() => GenericElsFetcher.uploadGenericFiles(researchPlan, json.research_plan.id, 'ResearchPlan', true)
+ .then(() => BaseFetcher.updateAnnotations(researchPlan))
+ .then(() => this.fetchById(researchPlan.id))))
+ .catch((errorMessage) => { console.log(errorMessage); });
if (containerFiles.length > 0) {
const tasks = [];
@@ -255,32 +267,16 @@ export default class ResearchPlansFetcher {
}).catch((errorMessage) => { console.log(errorMessage); });
}
- static updateAnnotations(researchPlan) {
- return Promise.all(
- [
- ResearchPlansFetcher.updateAnnotationsOfAttachments(researchPlan),
- BaseFetcher.updateAnnotationsInContainer(researchPlan,[])
- ]);
- }
-
- static updateAnnotationsOfAttachments(researchPlan){
-
- const updateTasks=[];
- researchPlan.attachments
- .filter((attach => attach.hasOwnProperty('updatedAnnotation')))
- .forEach(attach => {
- let data = new FormData();
- data.append('updated_svg_string', attach.updatedAnnotation);
- updateTasks.push(fetch('/api/v1/attachments/' + attach.id + '/annotation', {
- credentials: 'same-origin',
- method: 'post',
- body: data
- })
- .catch((errorMessage) => {
- console.log(errorMessage);
- }));
- })
-
- return Promise.all(updateTasks);
+ static fetchResearchPlansForElements(id, element) {
+ return fetch(`/api/v1/research_plans/linked?id=${id}&element=${element}`, {
+ credentials: 'same-origin',
+ method: 'get',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
+ }
+ }).then((response) => response.json())
+ .then((json) => json)
+ .catch((errorMessage) => { console.log(errorMessage); });
}
}
diff --git a/app/packs/src/fetchers/SampleTasksFetcher.js b/app/packs/src/fetchers/SampleTasksFetcher.js
index 63a4a9eda4..3dd9d1e7d9 100644
--- a/app/packs/src/fetchers/SampleTasksFetcher.js
+++ b/app/packs/src/fetchers/SampleTasksFetcher.js
@@ -32,6 +32,14 @@ export default class SampleTaskFetcher {
.catch(errorMessage => console.log(errorMessage));
}
+ static deleteSampleTask(sample_task_id) {
+ return fetch(
+ `/api/v1/sample_tasks/${sample_task_id}`,
+ { ...this._httpOptions('DELETE') }
+ ).then(response => response.json())
+ .catch(errorMessage => console.log(errorMessage));
+ }
+
static _fetchSampleTasks(status) {
return fetch(
`/api/v1/sample_tasks?status=${status}`,
diff --git a/app/packs/src/fetchers/SamplesFetcher.js b/app/packs/src/fetchers/SamplesFetcher.js
index a677dba661..a94a9cb1f5 100644
--- a/app/packs/src/fetchers/SamplesFetcher.js
+++ b/app/packs/src/fetchers/SamplesFetcher.js
@@ -6,7 +6,6 @@ import AttachmentFetcher from 'src/fetchers/AttachmentFetcher';
import BaseFetcher from 'src/fetchers/BaseFetcher';
import GenericElsFetcher from 'src/fetchers/GenericElsFetcher';
-
export default class SamplesFetcher {
static fetchSamplesByUIStateAndLimit(params) {
const limit = params.limit ? limit : null;
@@ -15,7 +14,7 @@ export default class SamplesFetcher {
credentials: 'same-origin',
method: 'POST',
headers: {
- 'Accept': 'application/json',
+ Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
@@ -27,22 +26,18 @@ export default class SamplesFetcher {
},
limit: params.limit
})
- }).then((response) => {
- return response.json()
- }).then((json) => {
- return json.samples.map((s) => new Sample(s));
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ }).then((response) => response.json())
+ .then((json) => json.samples.map((s) => new Sample(s)))
+ .catch((errorMessage) => {
+ console.log(errorMessage);
+ });
}
static fetchById(id) {
- let promise = fetch('/api/v1/samples/' + id + '.json', {
+ const promise = fetch(`/api/v1/samples/${id}.json`, {
credentials: 'same-origin'
})
- .then((response) => {
- return response.json()
- }).then((json) => {
+ .then((response) => response.json()).then((json) => {
const rSample = new Sample(json.sample);
if (json.error) {
rSample.id = `${id}:error:Sample ${id} is not accessible!`;
@@ -55,8 +50,8 @@ export default class SamplesFetcher {
}
static fetchByCollectionId(id, queryParams = {}, isSync = false, moleculeSort = false) {
- queryParams.moleculeSort = moleculeSort;
- return BaseFetcher.fetchByCollectionId(id, queryParams, isSync, 'samples', Sample);
+ const updatedQueryParams = { ...queryParams, moleculeSort };
+ return BaseFetcher.fetchByCollectionId(id, updatedQueryParams, isSync, 'samples', Sample);
}
static findByShortLabel(shortLabel) {
@@ -66,7 +61,7 @@ export default class SamplesFetcher {
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' }
}
- ).then((response) => response.json()).catch(errorMessage => console.log(errorMessage))
+ ).then((response) => response.json()).catch((errorMessage) => console.log(errorMessage));
}
static update(sample) {
@@ -79,19 +74,17 @@ export default class SamplesFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(sample.serialize())
- }).then(response => response.json())
- .then(json => GenericElsFetcher.uploadGenericFiles(sample, json.sample.id, 'Sample')
- .then(() => BaseFetcher.updateAnnotationsInContainer(sample))
- .then(() => this.fetchById(json.sample.id))).catch((errorMessage) => {
- console.log(errorMessage);
+ }).then((response) => response.json())
+ .then((json) => GenericElsFetcher.uploadGenericFiles(sample, json.sample.id, 'Sample')
+ .then(() => BaseFetcher.updateAnnotationsInContainer(sample))
+ .then(() => this.fetchById(json.sample.id))).catch((errorMessage) => {
+ console.log(errorMessage);
});
if (files.length > 0) {
- let tasks = [];
- files.forEach(file => tasks.push(AttachmentFetcher.uploadFile(file).then()));
- return Promise.all(tasks).then(() => {
- return promise();
- });
+ const tasks = [];
+ files.forEach((file) => tasks.push(AttachmentFetcher.uploadFile(file).then()));
+ return Promise.all(tasks).then(() => promise());
}
return promise();
@@ -107,24 +100,22 @@ export default class SamplesFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(sample.serialize())
- }).then(response => response.json())
- .then(json => GenericElsFetcher.uploadGenericFiles(sample, json.sample.id, 'Sample')
+ }).then((response) => response.json())
+ .then((json) => GenericElsFetcher.uploadGenericFiles(sample, json.sample.id, 'Sample')
.then(() => this.fetchById(json.sample.id))).catch((errorMessage) => {
- console.log(errorMessage);
- });
- if (files.length > 0) {
- let tasks = [];
- files.forEach(file => tasks.push(AttachmentFetcher.uploadFile(file)));
- return Promise.all(tasks).then(() => {
- return promise();
+ console.log(errorMessage);
});
+ if (files.length > 0) {
+ const tasks = [];
+ files.forEach((file) => tasks.push(AttachmentFetcher.uploadFile(file)));
+ return Promise.all(tasks).then(() => promise());
}
return promise();
}
static splitAsSubsamples(params) {
- let promise = fetch('/api/v1/samples/subsamples/', {
+ const promise = fetch('/api/v1/samples/subsamples/', {
credentials: 'same-origin',
method: 'POST',
headers: {
@@ -141,11 +132,7 @@ export default class SamplesFetcher {
currentCollectionId: params.currentCollection.id
}
})
- }).then((response) => {
- return response.json()
- }).then((json) => {
- return json;
- }).catch((errorMessage) => {
+ }).then((response) => response.json()).then((json) => json).catch((errorMessage) => {
console.log(errorMessage);
});
@@ -153,32 +140,28 @@ export default class SamplesFetcher {
}
static importSamplesFromFile(params) {
+ const data = new FormData();
+ data.append('file', params.file);
+ data.append('currentCollectionId', params.currentCollectionId);
+ data.append('import_type', params.type);
- var data = new FormData();
- data.append("file", params.file);
- data.append("currentCollectionId", params.currentCollectionId);
-
- let promise = fetch('/api/v1/samples/import/', {
+ const promise = fetch('/api/v1/samples/import/', {
credentials: 'same-origin',
method: 'post',
body: data
- }).then((response) => {
- return response.json()
- }).then((json) => {
- return json;
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
-
+ }).then((response) => response.json())
+ .then((json) => json).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
return promise;
}
static importSamplesFromFileConfirm(params) {
- let promise = fetch('/api/v1/samples/confirm_import/', {
+ const promise = fetch('/api/v1/samples/confirm_import/', {
credentials: 'same-origin',
method: 'post',
headers: {
- 'Accept': 'application/json',
+ Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
@@ -187,16 +170,23 @@ export default class SamplesFetcher {
mapped_keys: params.mapped_keys,
})
}).then((response) => {
- return response.json();
+ response.json();
}).then((json) => {
- for (let i = 0; i < json.error_messages.length; i++) {
+ if (Array.isArray(json.error_messages)) {
+ json.error_messages.forEach((message) => {
+ NotificationActions.add({
+ message,
+ level: 'error',
+ autoDismiss: 10
+ });
+ });
+ } else {
NotificationActions.add({
- message: json.error_messages[i],
- level: 'error',
+ message: json.error_messages || json.message,
+ level: json.message ? 'success' : 'error',
autoDismiss: 10
});
- };
-
+ }
return json;
}).catch((errorMessage) => {
console.log(errorMessage);
diff --git a/app/packs/src/fetchers/SearchFetcher.js b/app/packs/src/fetchers/SearchFetcher.js
index b91de9d265..797d493ef9 100644
--- a/app/packs/src/fetchers/SearchFetcher.js
+++ b/app/packs/src/fetchers/SearchFetcher.js
@@ -2,6 +2,7 @@ import 'whatwg-fetch';
import Sample from 'src/models/Sample';
import Reaction from 'src/models/Reaction';
import Wellplate from 'src/models/Wellplate';
+import CellLine from 'src/models/cellLine/CellLine';
import Screen from 'src/models/Screen';
import GenericEl from 'src/models/GenericEl';
import ResearchPlan from 'src/models/ResearchPlan';
@@ -27,7 +28,7 @@ export default class SearchFetcher {
})
}).then(response => response.json())
.then((json) => {
- const { samples, reactions, wellplates, screens, research_plans } = json;
+ const { samples, reactions, wellplates, screens, research_plans, cell_lines } = json;
const result = { ...json };
Object.keys(json).forEach((key) => {
@@ -35,27 +36,32 @@ export default class SearchFetcher {
case 'samples':
if (samples && samples.totalElements && samples.totalElements > 0) {
result.samples.elements = samples.elements.map(s => (new Sample(s)));
- } else { result.samples = { elements: [], totalElements: 0, ids: [] }; }
+ } else { result.samples = { elements: [], totalElements: 0, ids: [], error: result.samples.error }; }
break;
case 'reactions':
if (reactions && reactions.totalElements && reactions.totalElements > 0) {
result.reactions.elements = reactions.elements.map(r => (new Reaction(r)));
- } else { result.reactions = { elements: [], totalElements: 0, ids: [] }; }
+ } else { result.reactions = { elements: [], totalElements: 0, ids: [], error: result.reactions.error }; }
break;
case 'wellplates':
if (wellplates && wellplates.totalElements && wellplates.totalElements > 0) {
result.wellplates.elements = wellplates.elements.map(s => (new Wellplate(s)));
- } else { result.wellplates = { elements: [], totalElements: 0, ids: [] }; }
+ } else { result.wellplates = { elements: [], totalElements: 0, ids: [], error: result.wellplates.error }; }
break;
case 'screens':
if (screens && screens.totalElements && screens.totalElements > 0) {
result.screens.elements = screens.elements.map(s => (new Screen(s)));
- } else { result.screens = { elements: [], totalElements: 0, ids: [] }; }
+ } else { result.screens = { elements: [], totalElements: 0, ids: [], error: result.screens.error }; }
break;
case 'research_plans':
if (research_plans && research_plans.totalElements && research_plans.totalElements > 0) {
result.research_plans.elements = research_plans.elements.map(s => (new ResearchPlan(s)));
- } else { result.research_plans = { elements: [], totalElements: 0, ids: [] }; }
+ } else { result.research_plans = { elements: [], totalElements: 0, ids: [], error: result.research_plans.error }; }
+ break;
+ case 'cell_lines':
+ if (cell_lines && cell_lines.totalElements && cell_lines.totalElements > 0) {
+ result.cell_lines.elements = cell_lines.elements.map(s => (CellLine.createFromRestResponse(0, s)));
+ } else { result.cell_lines = { elements: [], totalElements: 0, ids: [] }; }
break;
default:
result[`${key}`].elements = json[`${key}`].elements.map(s => (new GenericEl(s)));
@@ -65,4 +71,67 @@ export default class SearchFetcher {
return result;
}).catch((errorMessage) => { console.log(errorMessage); });
}
+
+ static fetchBasedOnSearchResultIds(params) {
+ const { selection, collectionId, page, isSync, moleculeSort, isPublic } = params;
+ return fetch(`/api/v1/search/${selection.elementType.toLowerCase()}`, {
+ credentials: 'same-origin',
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ selection,
+ collection_id: collectionId,
+ page: page || 1,
+ page_size: selection.page_size,
+ per_page: selection.page_size,
+ is_sync: isSync || false,
+ molecule_sort: moleculeSort || false,
+ is_public: isPublic || false,
+ })
+ }).then(response => response.json())
+ .then((json) => {
+ const { samples, reactions, wellplates, screens, research_plans } = json;
+ const result = { ...json };
+
+ Object.keys(json).forEach((key) => {
+ switch (key) {
+ case 'samples':
+ if (samples && samples.elements.length > 0) {
+ result.samples.elements = samples.elements.map(s => (new Sample(s)));
+ } else { result.samples = { elements: [], ids: [], totalElements: 0 }; }
+ break;
+ case 'reactions':
+ if (reactions && reactions.elements.length > 0) {
+ result.reactions.elements = reactions.elements.map(r => (new Reaction(r)));
+ } else { result.reactions = { elements: [], totalElements: 0, ids: [] }; }
+ break;
+ case 'wellplates':
+ if (wellplates && wellplates.elements.length > 0) {
+ result.wellplates.elements = wellplates.elements.map(s => (new Wellplate(s)));
+ } else { result.wellplates = { elements: [], totalElements: 0, ids: [] }; }
+ break;
+ case 'screens':
+ if (screens && screens.elements.length > 0) {
+ result.screens.elements = screens.elements.map(s => (new Screen(s)));
+ } else { result.screens = { elements: [], totalElements: 0, ids: [] }; }
+ break;
+ case 'research_plans':
+ if (research_plans && research_plans.elements.length > 0) {
+ result.research_plans.elements = research_plans.elements.map(s => (new ResearchPlan(s)));
+ } else { result.research_plans = { elements: [], totalElements: 0, ids: [] }; }
+ break;
+ default:
+ if (json[`${key}`] && json[`${key}`].elements !== undefined && json[`${key}`].elements.length > 0) {
+ result[`${key}`].elements = json[`${key}`].elements.map(s => (new GenericEl(s)));
+ } else { result[`${key}`] = { elements: [], totalElements: 0, ids: [] }; }
+ break;
+ }
+ });
+
+ return result;
+ }).catch((errorMessage) => { console.log(errorMessage); });
+ }
}
diff --git a/app/packs/src/fetchers/SegmentsFetcher.js b/app/packs/src/fetchers/SegmentsFetcher.js
deleted file mode 100644
index b0f8158d3c..0000000000
--- a/app/packs/src/fetchers/SegmentsFetcher.js
+++ /dev/null
@@ -1,15 +0,0 @@
-export default class SegmentsFetcher {
- static fetchKlass(elementName = null) {
- let api = '';
- if (elementName == null) {
- api = '/api/v1/segments/klasses.json';
- } else {
- api = `/api/v1/segments/klasses.json?element=${elementName}`;
- }
- return fetch(api, {
- credentials: 'same-origin'
- }).then(response => response.json()).then(json => json).catch((errorMessage) => {
- console.log(errorMessage);
- });
- }
-}
diff --git a/app/packs/src/fetchers/SuggestionsFetcher.js b/app/packs/src/fetchers/SuggestionsFetcher.js
index 3c735a81a0..15780fa297 100644
--- a/app/packs/src/fetchers/SuggestionsFetcher.js
+++ b/app/packs/src/fetchers/SuggestionsFetcher.js
@@ -1,9 +1,14 @@
-import 'whatwg-fetch';
-
export default class SuggestionsFetcher {
static fetchSuggestionsForCurrentUser(elementType, query, collectId, isSync = false) {
+ const urlParams=new URLSearchParams({
+ query: encodeURIComponent(query),
+ collection_id: collectId,
+ is_sync: isSync})
+
+ elementType=elementType.replaceAll(" ", "_");
+
return fetch(
- `/api/v1/suggestions/${elementType}?query=${encodeURIComponent(query)}&collection_id=${collectId}&is_sync=${isSync}`,
+ `/api/v1/suggestions/${elementType}?`+urlParams,
{ credentials: 'same-origin' }
).then(response => response.json())
.then(json => json.suggestions)
diff --git a/app/packs/src/fetchers/ThirdPartyAppFetcher.js b/app/packs/src/fetchers/ThirdPartyAppFetcher.js
index 6a65663e9f..8dee31af24 100644
--- a/app/packs/src/fetchers/ThirdPartyAppFetcher.js
+++ b/app/packs/src/fetchers/ThirdPartyAppFetcher.js
@@ -10,27 +10,10 @@ export default class ThirdPartyAppFetcher {
.catch((errorMessage) => { console.log(errorMessage); });
}
- static isNameUnique(name) {
- const obj = {
- name
- };
- return fetch('/api/v1/third_party_apps_administration/name_unique', {
- credentials: 'same-origin',
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(obj)
- }).then(response => response.json())
- .then(json => json)
- .catch((errorMessage) => { console.log(errorMessage); });
- }
-
- static newThirdPartyApp(name, IPAddress) {
+ static newThirdPartyApp(name, url) {
const obj = {
name,
- IPAddress
+ url
};
return fetch('/api/v1/third_party_apps_administration/new_third_party_app', {
credentials: 'same-origin',
@@ -45,10 +28,10 @@ export default class ThirdPartyAppFetcher {
.catch((errorMessage) => { console.log(errorMessage); });
}
- static editThirdPartyApp(id, name, IPAddress) {
+ static editThirdPartyApp(id, name, url) {
const obj = {
id: id,
- IPAddress: IPAddress,
+ url: url,
name: name
};
return fetch('/api/v1/third_party_apps_administration/update_third_party_app', {
@@ -124,7 +107,7 @@ export default class ThirdPartyAppFetcher {
.catch((errorMessage) => { console.log(errorMessage); });
}
- static fetchAttachmentToken(attID, userID, nameThirdPartyApp) {
+ static fetchAttachmentToken(attID, nameThirdPartyApp, userID) {
const obj = { attID, userID, nameThirdPartyApp };
const queryParams = new URLSearchParams(obj).toString();
const url = `/api/v1/third_party_apps/Token.json?${queryParams}`;
diff --git a/app/packs/src/fetchers/UsersFetcher.js b/app/packs/src/fetchers/UsersFetcher.js
index 515c8049cd..8ebc2eccb4 100644
--- a/app/packs/src/fetchers/UsersFetcher.js
+++ b/app/packs/src/fetchers/UsersFetcher.js
@@ -15,9 +15,9 @@ export default class UsersFetcher {
}
static fetchElementKlassNames(genericOnly = true) {
- let api = '/api/v1/public/element_klasses_name.json';
+ let api = '/api/v1/labimotion_hub/element_klasses_name.json';
if (genericOnly) {
- api = '/api/v1/public/element_klasses_name.json?generic_only=true';
+ api = '/api/v1/labimotion_hub/element_klasses_name.json?generic_only=true';
}
return fetch(api, {
@@ -35,9 +35,8 @@ export default class UsersFetcher {
});
}
-
- static fetchUsersByName(name) {
- const promise = fetch(`/api/v1/users/name.json?name=${name}`, {
+ static fetchUsersByName(name, type = 'Person') {
+ const promise = fetch(`/api/v1/users/name.json?${new URLSearchParams({ name, type })}`, {
credentials: 'same-origin'
})
.then(response => response.json()).then(json => json).catch((errorMessage) => {
@@ -167,6 +166,8 @@ export default class UsersFetcher {
destroy_group: params.destroy_group,
rm_users: params.rm_users,
add_users: params.add_users,
+ add_admin: params.add_admin,
+ rm_admin: params.rm_admin,
})
}).then(response => response.json()).then(json => json).catch((errorMessage) => {
console.log(errorMessage);
diff --git a/app/packs/src/fetchers/WellplatesFetcher.js b/app/packs/src/fetchers/WellplatesFetcher.js
index 8c271c6f4d..2884362e40 100644
--- a/app/packs/src/fetchers/WellplatesFetcher.js
+++ b/app/packs/src/fetchers/WellplatesFetcher.js
@@ -62,7 +62,7 @@ export default class WellplatesFetcher {
}
return AttachmentFetcher.updateAttachables(newFiles, 'Wellplate', json.wellplate.id, delFiles)();
})
- .then(() => BaseFetcher.updateAnnotationsInContainer(wellplate))
+ .then(() => BaseFetcher.updateAnnotations(wellplate))
.then(() => WellplatesFetcher.fetchById(wellplate.id))
.catch((errorMessage) => {
console.log(errorMessage);
@@ -88,15 +88,17 @@ export default class WellplatesFetcher {
'Content-Type': 'application/json'
},
body: JSON.stringify(wellplate.serialize())
- }).then((response) => response.json()).then((json) => {
- if (files.length <= 0) {
- return new Wellplate(json.wellplate);
- }
- return AttachmentFetcher.updateAttachables(files, 'Wellplate', json.wellplate.id, [])()
- .then(() => new Wellplate(json.wellplate));
- }).catch((errorMessage) => {
- console.log(errorMessage);
- });
+ })
+ .then((response) => response.json())
+ .then((json) => {
+ if (files.length <= 0) {
+ return new Wellplate(json.wellplate);
+ }
+ return AttachmentFetcher.updateAttachables(files, 'Wellplate', json.wellplate.id, [])()
+ .then(() => new Wellplate(json.wellplate));
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
if (containerFiles.length > 0) {
const tasks = [];
diff --git a/app/packs/src/models/Attachment.js b/app/packs/src/models/Attachment.js
index 2edc387a48..08c7e4d839 100644
--- a/app/packs/src/models/Attachment.js
+++ b/app/packs/src/models/Attachment.js
@@ -1,5 +1,5 @@
+/* eslint-disable no-underscore-dangle */
import Element from 'src/models/Element';
-import { formatBytes } from 'src/utilities/MathUtils';
export default class Attachment extends Element {
static NO_PREVIEW_AVAILABLE_PATH = '/images/wild_card/not_available.svg';
diff --git a/app/packs/src/models/Comment.js b/app/packs/src/models/Comment.js
new file mode 100644
index 0000000000..c06f8a6390
--- /dev/null
+++ b/app/packs/src/models/Comment.js
@@ -0,0 +1,93 @@
+/* eslint-disable no-underscore-dangle, camelcase, semi, no-unused-vars */
+import Element from 'src/models/Element';
+
+export default class Comment extends Element {
+ static buildEmpty() {
+ return new Comment({
+ content: '',
+ commentable_id: null,
+ commentable_type: null,
+ created_by: null,
+ created_at: null,
+ });
+ }
+
+ static buildWithElement(element) {}
+
+ get content() {
+ return this._content;
+ }
+
+ set content(content) {
+ this._content = content;
+ }
+
+ get commentable_id() {
+ return this._commentable_id;
+ }
+
+ set commentable_id(commentable_id) {
+ this._commentable_id = commentable_id;
+ }
+
+ get created_by() {
+ return this._created_by;
+ }
+
+ set created_by(created_by) {
+ this._created_by = created_by;
+ }
+
+ get commentable_type() {
+ return this._commentable_type;
+ }
+
+ set commentable_type(commentable_type) {
+ this._commentable_type = commentable_type;
+ }
+
+ get status() {
+ return this._status;
+ }
+
+ set status(status) {
+ this._status = status;
+ }
+
+ get submitter() {
+ return this._submitter;
+ }
+
+ set submitter(submitter) {
+ this._submitter = submitter;
+ }
+
+ get resolver_name() {
+ return this._resolver_name;
+ }
+
+ set resolver_name(resolver_name) {
+ this._resolver_name = resolver_name;
+ }
+
+ get section() {
+ return this._section;
+ }
+
+ set section(section) {
+ this._section = section;
+ }
+
+ serialize() {
+ return super.serialize({
+ content: this.content,
+ commentable_id: this.commentable_id,
+ commentable_type: this.commentable_type,
+ created_by: this.created_by,
+ status: this.status,
+ submitter: this.submitter,
+ resolver_name: this.resolver_name,
+ section: this.section,
+ });
+ }
+}
diff --git a/app/packs/src/models/Container.js b/app/packs/src/models/Container.js
index 7416126e1e..80c9737bbd 100644
--- a/app/packs/src/models/Container.js
+++ b/app/packs/src/models/Container.js
@@ -16,18 +16,18 @@ export default class Container extends Element {
}
static buildAnalysis(kind = 'other', name = '') {
- var analysis = this.buildEmpty()
- analysis.container_type = "analysis"
- analysis.extended_metadata['kind'] = kind
- analysis.name = name
- return analysis
+ const analysis = this.buildEmpty();
+ analysis.container_type = 'analysis';
+ analysis.extended_metadata.kind = kind;
+ analysis.name = name;
+ return analysis;
}
static init() {
- var root = this.buildEmpty();
+ const root = this.buildEmpty();
root.container_type = 'root';
- var analyses = this.buildEmpty();
+ const analyses = this.buildEmpty();
analyses.container_type = 'analyses';
root.children.push(analyses);
@@ -39,17 +39,30 @@ export default class Container extends Element {
return this.name;
}
+ static switchPositionOfChildContainer(children, idToMove, idOfPredecessor) {
+ const indexOfMovedContainer = children.findIndex((container) => container.id === idToMove);
+ const indexOfPredecContainer = children.findIndex((container) => container.id === idOfPredecessor);
+
+ const containerToMove = children[indexOfMovedContainer];
+ children.splice(indexOfMovedContainer, 1);
+ children.splice(indexOfPredecContainer, 0, containerToMove);
+
+ children.forEach((element,index) => {
+ element.extended_metadata.index=index;
+ });
+ }
+
serialize() {
return super.serialize({
id: this.id,
name: this.name,
children: this.children,
- attachments: this.attachments.map(a => a.serialize()),
+ attachments: this.attachments.map((a) => a.serialize()),
is_new: this.isNew || false,
is_deleted: this.deleted || false,
description: this.description,
extended_metadata: this.extended_metadata,
container_type: this.container_type,
- })
+ });
}
}
diff --git a/app/packs/src/models/GenericDS.js b/app/packs/src/models/GenericDS.js
index 295819a1b6..c1fa4710f4 100644
--- a/app/packs/src/models/GenericDS.js
+++ b/app/packs/src/models/GenericDS.js
@@ -1,3 +1,4 @@
+import { cloneDeep } from 'lodash';
import Element from 'src/models/Element';
export default class GenericDS extends Element {
@@ -8,9 +9,10 @@ export default class GenericDS extends Element {
element_type: 'Container',
element_id: containerId,
properties: template,
+ properties_release: cloneDeep(template),
klass_ols: klass.ols_term_id,
klass_label: klass.label,
- changed: false
+ changed: false,
});
}
@@ -20,6 +22,7 @@ export default class GenericDS extends Element {
element_type: 'Container',
element_id: this.element_id,
properties: this.properties,
+ properties_release: this.properties_release,
});
}
diff --git a/app/packs/src/models/GenericEl.js b/app/packs/src/models/GenericEl.js
index 3d47d53b8a..e55151edef 100644
--- a/app/packs/src/models/GenericEl.js
+++ b/app/packs/src/models/GenericEl.js
@@ -1,11 +1,11 @@
import { isEmpty, filter } from 'lodash';
+import { buildInitWF, resetProperties } from 'chem-generic-ui';
import Element from 'src/models/Element';
import Container from 'src/models/Container';
import UserStore from 'src/stores/alt/stores/UserStore';
import Segment from 'src/models/Segment';
export default class GenericEl extends Element {
-
// eslint-disable-next-line camelcase
static buildEmpty(collection_id, klass) {
const template = (klass && klass.properties_release) || {};
@@ -16,13 +16,14 @@ export default class GenericEl extends Element {
short_label: GenericEl.buildNewShortLabel(klass),
name: `New ${klass.label}`,
container: Container.init(),
- properties: template,
+ properties: buildInitWF(template),
+ properties_release: template,
element_klass: klass,
can_copy: false,
- properties_release: [],
attachments: [],
files: [],
- segments: []
+ segments: [],
+ wfLayers: template,
});
}
@@ -34,46 +35,80 @@ export default class GenericEl extends Element {
element_klass: this.element_klass,
element_klass_id: this._element_klass_id,
properties: this.properties,
+ properties_release: this.properties_release,
container: this.container,
attachments: this.attachments,
files: this.files,
- segments: this.segments.map(s => s.serialize())
+ segments: this.segments.map(s => s.serialize()),
+ });
+ }
+
+ analysesContainers() {
+ if (this.container.children.length === 0) {
+ const analyses = Container.buildEmpty();
+ analyses.container_type = 'analyses';
+ this.container.children.push(analyses);
+ }
+ return this.container.children.filter(
+ el => ~el.container_type.indexOf('analyses')
+ );
+ }
+
+ analysisContainers() {
+ let target = [];
+ this.analysesContainers().forEach(aec => {
+ const aics = aec.children.filter(
+ el => ~el.container_type.indexOf('analysis')
+ );
+ target = [...target, ...aics];
});
+ return target;
+ }
+
+ datasetContainers() {
+ let target = [];
+ this.analysisContainers().forEach(aic => {
+ const dts = aic.children.filter(
+ el => ~el.container_type.indexOf('dataset')
+ );
+ target = [...target, ...dts];
+ });
+ return target;
}
static buildNewShortLabel(klass) {
const { currentUser } = UserStore.getState();
- if (!currentUser) { return `new_${klass.label}`; }
- return `${currentUser.initials}-${klass.klass_prefix}${parseInt(currentUser.counters[klass.name] || 0, 10) + 1}`;
+ if (!currentUser) {
+ return `new_${klass.label}`;
+ }
+ return `${currentUser.initials}-${klass.klass_prefix}${
+ parseInt(currentUser.counters[klass.name] || 0, 10) + 1
+ }`;
}
-
buildCopy(params = {}) {
const copy = super.buildCopy();
Object.assign(copy, params);
copy.short_label = GenericEl.buildNewShortLabel(copy.element_klass);
+ copy.container = Container.init();
copy.can_update = true;
copy.can_copy = false;
return copy;
}
static copyFromCollectionId(element, collection_id) {
+ const target = Object.assign({}, element.properties);
const params = {
collection_id,
- role: 'parts',
- timestamp_start: '',
- timestamp_stop: '',
- rf_value: 0.00,
- status: '',
- }
+ properties: resetProperties(target),
+ };
const copy = element.buildCopy(params);
copy.origin = { id: element.id, short_label: element.short_label };
- //copy.name = copy.nameFromRole(copy.role);
return copy;
}
get klassType() {
- return 'GenericEl'
+ return 'GenericEl';
}
get name() {
@@ -107,7 +142,6 @@ export default class GenericEl extends Element {
this._klass_name = klassName;
}
-
get properties() {
return this._properties;
}
@@ -132,6 +166,22 @@ export default class GenericEl extends Element {
return this._segments || [];
}
+ set klass_uuid(klass_uuid) {
+ this._klass_uuid = klass_uuid;
+ }
+
+ get klass_uuid() {
+ return this._klass_uuid;
+ }
+
+ get uuid() {
+ return this._uuid;
+ }
+
+ set uuid(uuid) {
+ this._uuid = uuid;
+ }
+
title() {
return `${this.short_label} ${this.name}`;
}
@@ -142,15 +192,25 @@ export default class GenericEl extends Element {
isValidated() {
const validName = !!(this.name && this.name.trim() !== '');
- const layers = filter(this.properties && this.properties.layers, l => l.parent == null || l.parent.trim().length === 0) || [];
-
- // required fileds, draggable only
- const fieldsDrag = layers.flatMap(l => l.fields).filter(f => f.required && f.type.includes('drag_'));
- const vaildFieldsDrag = fieldsDrag.length === fieldsDrag.filter(f => f.value && f.value.el_id).length;
-
- // required fileds, excludes draggable
- const fields = layers.flatMap(l => l.fields).filter(f => f.required && !f.type.includes('drag_'));
- const vaildFields = fields.length === fields.filter(f => f.value && f.value.trim() !== '').length;
+ const layers =
+ filter(
+ this.properties && this.properties.layers,
+ l => l.parent == null || l.parent.trim().length === 0
+ ) || [];
+
+ const fieldsDrag = layers
+ .flatMap(l => l.fields)
+ .filter(f => f.required && f.type.includes('drag_'));
+ const vaildFieldsDrag =
+ fieldsDrag.length ===
+ fieldsDrag.filter(f => f.value && f.value.el_id).length;
+
+ const fields = layers
+ .flatMap(l => l.fields)
+ .filter(f => f.required && !f.type.includes('drag_'));
+ const vaildFields =
+ fields.length ===
+ fields.filter(f => f.value && f.value.trim() !== '').length;
return validName && vaildFieldsDrag && vaildFields;
}
diff --git a/app/packs/src/models/Reaction.js b/app/packs/src/models/Reaction.js
index f194ac768b..9dd7ccf3f8 100644
--- a/app/packs/src/models/Reaction.js
+++ b/app/packs/src/models/Reaction.js
@@ -13,8 +13,42 @@ import Container from 'src/models/Container';
import UserStore from 'src/stores/alt/stores/UserStore';
import Segment from 'src/models/Segment';
+import {
+ removeObsoleteMaterialsFromVariations,
+ addMissingMaterialsToVariations,
+ updateYields,
+ updateEquivalents,
+} from 'src/apps/mydb/elements/details/reactions/variationsTab/ReactionVariationsUtils';
+
const TemperatureUnit = ['°C', '°F', 'K'];
+const TemperatureDefault = {
+ valueUnit: '°C',
+ userText: '',
+ data: []
+};
+
+export const convertTemperature = (temperature, fromUnit, toUnit) => {
+ if (fromUnit === toUnit) {
+ return temperature;
+ }
+ const conversionTable = {
+ 'K': {
+ '°C': (t) => parseFloat(t) - 273.15,
+ '°F': (t) => (parseFloat(t) * 9 / 5) - 459.67
+ },
+ '°C': {
+ 'K': (t) => parseFloat(t) + 273.15,
+ '°F': (t) => (parseFloat(t) * 1.8) + 32
+ },
+ '°F': {
+ 'K': (t) => (parseFloat(t) + 459.67) * 5 / 9,
+ '°C': (t) => (parseFloat(t) - 32) / 1.8
+ }
+ };
+ return conversionTable[fromUnit][toUnit](temperature);
+};
+
const MomentUnit = {
'Week(s)': 'weeks',
'Day(s)': 'days',
@@ -46,7 +80,7 @@ const DurationDefault = {
memUnit: 'Hour(s)'
};
-const convertDuration = (value, unit, newUnit) => {
+export const convertDuration = (value, unit, newUnit) => {
const d = moment.duration(Number.parseFloat(value), LegMomentUnit[unit])
.as(MomentUnit[newUnit]);
return round(d, 1).toString();
@@ -74,12 +108,6 @@ const highestUnitFromDuration = (d, threshold = 1.0) => {
export default class Reaction extends Element {
static buildEmpty(collection_id) {
- const temperatureDefault = {
- 'valueUnit': '°C',
- 'userText': '',
- 'data': []
- }
-
const reaction = new Reaction({
collection_id,
container: Container.init(),
@@ -89,6 +117,7 @@ export default class Reaction extends Element {
duration: '',
durationDisplay: DurationDefault,
literatures: {},
+ research_plans: {},
name: '',
observation: Reaction.quillDefault(),
products: [],
@@ -101,14 +130,15 @@ export default class Reaction extends Element {
solvents: [],
status: '',
starting_materials: [],
- temperature: temperatureDefault,
+ temperature: TemperatureDefault,
timestamp_start: '',
timestamp_stop: '',
tlc_description: '',
tlc_solvents: '',
type: 'reaction',
can_update: true,
- can_copy: false
+ can_copy: false,
+ variations: []
})
reaction.short_label = this.buildReactionShortLabel()
@@ -149,6 +179,7 @@ export default class Reaction extends Element {
durationCalc: this.durationCalc(),
id: this.id,
literatures: this.literatures,
+ research_plans: this.research_plans,
materials: {
starting_materials: this.starting_materials.map(s => s.serializeMaterial()),
reactants: this.reactants.map(s => s.serializeMaterial()),
@@ -172,10 +203,74 @@ export default class Reaction extends Element {
temperature: this.temperature,
timestamp_start: this.timestamp_start,
timestamp_stop: this.timestamp_stop,
- segments: this.segments.map(s => s.serialize())
+ segments: this.segments.map(s => s.serialize()),
+ variations: this.variations
});
}
+ set variations(variations) {
+ // variations data structure (also see Entities::ReactionVariationEntity):
+ // [
+ // {
+ // "id": ,
+ // "properties": {
+ // "temperature": {"value": , "unit": },
+ // "duration": {"value": , "unit": }
+ // },
+ // "startingMaterials": {
+ // , "unit": , "aux": {...}},
+ // : {"value": , "unit": , "aux": {...}},
+ // ...
+ // },
+ // "reactants": {
+ // , "unit": , "aux": {...}},
+ // : {"value": , "unit": , "aux": {...}},
+ // ...
+ // },
+ // "products": {
+ // , "unit": , "aux": {...}},
+ // : {"value": , "unit": , "aux": {...}},
+ // ...
+ // },
+ // "solvents": {
+ // , "unit": , "aux": {...}},
+ // : {"value": , "unit": , "aux": {...}},
+ // ...
+ // },
+ // },
+ // {
+ // "id": "",
+ // ...
+ // },
+ // ...
+ // ]
+ if (!Array.isArray(variations) || !variations.length) {
+ this._variations = [];
+ } else {
+ const currentMaterials = {
+ startingMaterials: this.starting_materials,
+ reactants: this.reactants,
+ products: this.products,
+ solvents: this.solvents
+ };
+ // Keep set of materials up-to-date. Materials could have been added or removed in the scheme tab
+ // (of the reaction detail modal); these changes need to be reflected in the variations.
+ let updatedVariations = removeObsoleteMaterialsFromVariations(variations, currentMaterials);
+ updatedVariations = addMissingMaterialsToVariations(updatedVariations, currentMaterials);
+ // The products' yields need to be updated, since the products' amounts could have been edited in
+ // the variations tab (of the reaction detail modal).
+ updatedVariations = updateYields(updatedVariations, this.hasPolymers());
+ // A potential change in the reference material's amount needs to be reflected in the remaining materials' equivalents.
+ updatedVariations = updateEquivalents(updatedVariations);
+
+ this._variations = updatedVariations;
+ }
+ }
+
+ get variations() {
+ return this._variations;
+ }
+
// Reaction Duration
durationCalc() {
@@ -299,60 +394,22 @@ export default class Reaction extends Element {
}
convertTemperature(newUnit) {
- let temperature = this._temperature
- let oldUnit = temperature.valueUnit
- temperature.valueUnit = newUnit
-
- let convertFunc
- switch (oldUnit) {
- case "K":
- convertFunc = this.convertFromKelvin
- break
- case "°F":
- convertFunc = this.convertFromFarenheit
- break
- default:
- convertFunc = this.convertFromCelcius
- break
- }
+ const temperature = this._temperature
+ const oldUnit = temperature.valueUnit;
+ temperature.valueUnit = newUnit;
// If userText is number only, treat as normal temperature value
if (/^[\-|\d]\d*\.{0,1}\d{0,2}$/.test(temperature.userText)) {
- temperature.userText =
- convertFunc(newUnit, temperature.userText).toFixed(2)
+ temperature.userText = convertTemperature(temperature.userText, oldUnit, newUnit).toFixed(2);
- return temperature
+ return temperature;
}
- temperature.data.forEach(function (data, index, theArray) {
- theArray[index].value = convertFunc(newUnit, data.value).toFixed(2)
- })
-
- return temperature
- }
-
- convertFromKelvin(unit, temperature) {
- if (unit == "°C") {
- return (parseFloat(temperature) - 273.15)
- } else { // Farenheit
- return ((parseFloat(temperature) * 9 / 5) - 459.67)
- }
- }
-
- convertFromFarenheit(unit, temperature) {
- if (unit == "°C") {
- return ((parseFloat(temperature) - 32) / 1.8)
- } else { // Kelvin
- return ((parseFloat(temperature) + 459.67) * 5 / 9)
- }
- }
+ temperature.data.forEach((data, index, theArray) => {
+ theArray[index].value = convertTemperature(data.value, oldUnit, newUnit).toFixed(2);
+ });
- convertFromCelcius(unit, temperature) {
- if (unit == "°F") {
- return ((parseFloat(temperature) * 1.8) + 32)
- } else { // Kelvin
- return (parseFloat(temperature) + 273.15)
- }
+ return temperature;
}
get short_label() {
@@ -446,9 +503,11 @@ export default class Reaction extends Element {
}
static copyFromReactionAndCollectionId(reaction, collection_id) {
+ const target = Segment.buildCopy(reaction.segments);
const params = {
collection_id,
role: 'parts',
+ segments: target,
timestamp_start: '',
timestamp_stop: '',
rf_value: 0.00,
@@ -748,6 +807,10 @@ export default class Reaction extends Element {
});
}
+ getReferenceMaterial() {
+ return this.referenceMaterial;
+ }
+
updateMaterial(material, refreshCoefficient) {
const cats = ['starting_materials', 'reactants', 'solvents', 'products'];
let i = 0;
@@ -806,16 +869,24 @@ export default class Reaction extends Element {
return this._literatures || {};
}
+ get research_plans() {
+ return this._research_plans || {};
+ }
+
set literatures(literatures) {
this._literatures = literatures;
}
+ set research_plans(research_plans) {
+ this._research_plans = research_plans;
+ }
+
get totalVolume() {
let totalVolume = 0.0;
const materials = [...this.starting_materials,
- ...this.reactants,
- ...this.products,
- ...this.solvents];
+ ...this.reactants,
+ ...this.products,
+ ...this.solvents];
materials.map(m => totalVolume += m.amount_l);
return totalVolume;
}
diff --git a/app/packs/src/models/ResearchPlan.js b/app/packs/src/models/ResearchPlan.js
index b59b0813e6..1830cf43a9 100644
--- a/app/packs/src/models/ResearchPlan.js
+++ b/app/packs/src/models/ResearchPlan.js
@@ -198,7 +198,7 @@ export default class ResearchPlan extends Element {
return this._wellplates || [];
}
- upsertAttachments(attachmentsToAdd=[]) {
+ upsertAttachments(attachmentsToAdd = []) {
const idsOfAttachmentsInResearchPlan = this.attachments.map(
(attachmentInResearchPlan) => attachmentInResearchPlan.identifier
);
@@ -252,8 +252,19 @@ export default class ResearchPlan extends Element {
delete value.old_value;
});
}
- getAttachmentByIdentifier(identifier){
- return this.attachments
- .filter((attachment)=>attachment.identifier===identifier)[0];
+
+ getAttachmentByIdentifier(identifier) {
+ return this.attachments
+ .filter((attachment) => attachment.identifier === identifier)[0];
+ }
+
+ getNewAttachments() {
+ return this.attachments
+ .filter((attachment) => attachment.is_new === true && !attachment.is_deleted);
+ }
+
+ getMarkedAsDeletedAttachments() {
+ return this.attachments
+ .filter((attachment) => attachment.is_deleted === true && !attachment.is_new);
}
}
diff --git a/app/packs/src/models/Sample.js b/app/packs/src/models/Sample.js
index 95e28aa7d3..0a1c452606 100644
--- a/app/packs/src/models/Sample.js
+++ b/app/packs/src/models/Sample.js
@@ -1,13 +1,15 @@
+/* eslint-disable no-underscore-dangle */
+/* eslint-disable camelcase */
import React from 'react';
import _ from 'lodash';
import Element from 'src/models/Element';
import Molecule from 'src/models/Molecule';
import UserStore from 'src/stores/alt/stores/UserStore';
-import Container from 'src/models/Container.js';
+import Container from 'src/models/Container';
import Segment from 'src/models/Segment';
-const prepareRangeBound = (args, field) => {
+const prepareRangeBound = (args = {}, field) => {
const argsNew = args;
if (args[field] && typeof args[field] === 'string') {
const bounds = args[field].split(/\.{2,3}/);
@@ -20,7 +22,8 @@ const prepareRangeBound = (args, field) => {
if (argsNew[`${field}_upperbound`] == null || argsNew[`${field}_upperbound`] == null) {
argsNew[`${field}_display`] = (argsNew[`${field}_lowerbound`] || '').toString().trim();
} else {
- argsNew[`${field}_display`] = ((argsNew[`${field}_lowerbound`] || '').toString().concat(' – ', argsNew[`${field}_upperbound`])).trim();
+ argsNew[`${field}_display`] = ((argsNew[`${field}_lowerbound`] || '')
+ .toString().concat(' – ', argsNew[`${field}_upperbound`])).trim();
}
}
return argsNew;
@@ -43,7 +46,13 @@ export default class Sample extends Element {
this.melting_point = null;
}
- static copyFromSampleAndCollectionId(sample, collection_id, structure_only = false, keepResidueInfo = false, keepExternalLabel = true) {
+ static copyFromSampleAndCollectionId(
+ sample,
+ collection_id,
+ structure_only = false,
+ keepResidueInfo = false,
+ keepExternalLabel = true
+ ) {
const newSample = sample.buildCopy();
newSample.collection_id = collection_id;
if (sample.name) { newSample.name = sample.name; }
@@ -67,8 +76,7 @@ export default class Sample extends Element {
}
newSample.filterElementalComposition();
- newSample.segments = _.cloneDeep(sample.segments);
-
+ newSample.segments = Segment.buildCopy(sample.segments);
return newSample;
}
@@ -92,14 +100,15 @@ export default class Sample extends Element {
// set default polymer data
this.residues = [
{
- residue_type: 'polymer', custom_info: {
- "formula": 'CH',
- "loading": null,
- "polymer_type": (this.decoupled ? "self_defined" : "polystyrene"),
- "loading_type": "external",
- "external_loading": 0.0,
- "reaction_product": (this.reaction_product ? true : null),
- "cross_linkage": null
+ residue_type: 'polymer',
+ custom_info: {
+ formula: 'CH',
+ loading: null,
+ polymer_type: (this.decoupled ? 'self_defined' : 'polystyrene'),
+ loading_type: 'external',
+ external_loading: 0.0,
+ reaction_product: (this.reaction_product ? true : null),
+ cross_linkage: null
}
}
];
@@ -113,7 +122,7 @@ export default class Sample extends Element {
Object.assign(residue.custom_info, {
external_loading: 0.0,
loading: null,
- loading_type: "external"
+ loading_type: 'external'
});
});
} else {
@@ -122,13 +131,13 @@ export default class Sample extends Element {
Object.assign(residue, {
residue_type: 'polymer',
custom_info: {
- "formula": 'CH',
- "loading": (residue.custom_info ? residue.custom_info.loading : null),
- "polymer_type": (this.decoupled ? "self_defined" : "polystyrene"),
- "loading_type": "external",
- "external_loading": 0.0,
- "reaction_product": (this.reaction_product ? true : null),
- "cross_linkage": null
+ formula: 'CH',
+ loading: (residue.custom_info ? residue.custom_info.loading : null),
+ polymer_type: (this.decoupled ? 'self_defined' : 'polystyrene'),
+ loading_type: 'external',
+ external_loading: 0.0,
+ reaction_product: (this.reaction_product ? true : null),
+ cross_linkage: null
}
});
});
@@ -199,12 +208,12 @@ export default class Sample extends Element {
}
getChildrenCount() {
- return parseInt(Sample.children_count[this.id] || this.children_count);
+ return parseInt(Sample.children_count[this.id] || this.children_count, 10);
}
buildSplitShortLabel() {
- let children_count = this.getChildrenCount() + 1;
- return this.short_label + "-" + children_count;
+ const children_count = this.getChildrenCount() + 1;
+ return `${this.short_label}-${children_count}`;
}
buildCopy() {
@@ -273,7 +282,7 @@ export default class Sample extends Element {
}
get isSplit() {
- return this.is_split
+ return this.is_split;
}
set isSplit(is_split) {
@@ -281,7 +290,7 @@ export default class Sample extends Element {
}
serialize() {
- let serialized = super.serialize({
+ const serialized = super.serialize({
name: this.name,
external_label: this.external_label,
target_amount_value: this.target_amount_value,
@@ -301,6 +310,7 @@ export default class Sample extends Element {
molecule_name_id: this.molecule_name && this.molecule_name.value,
sample_svg_file: this.sample_svg_file,
is_top_secret: this.is_top_secret || false,
+ dry_solvent: this.dry_solvent,
parent_id: this.parent_id,
density: this.density,
metrics: this.metrics,
@@ -321,7 +331,7 @@ export default class Sample extends Element {
molecular_mass: this.molecular_mass,
sum_formula: this.sum_formula,
inventory_sample: this.inventory_sample,
- segments: this.segments.map(s => s.serialize()),
+ segments: this.segments.map((s) => s.serialize()),
});
return serialized;
@@ -335,28 +345,32 @@ export default class Sample extends Element {
this._is_top_secret = is_top_secret;
}
+ get dry_solvent() {
+ return this._dry_solvent;
+ }
+
+ set dry_solvent(dry_solvent) {
+ this._dry_solvent = dry_solvent;
+ }
+
set contains_residues(value) {
this._contains_residues = value;
if (value) {
if (!this.residues.length) {
-
this.setDefaultResidue();
} else {
this.residues[0]._destroy = undefined;
}
- this.elemental_compositions.map(function (item) {
- if (item.composition_type == 'formula')
- item._destroy = true;
+ this.elemental_compositions.map((item) => {
+ if (item.composition_type == 'formula') { item._destroy = true; }
});
} else {
// this.sample_svg_file = '';
- if (this.residues.length)
- this.residues[0]._destroy = true; // delete residue info
+ if (this.residues.length) { this.residues[0]._destroy = true; } // delete residue info
- this.elemental_compositions.map(function (item) {
- if (item.composition_type == 'loading')
- item._destroy = true;
+ this.elemental_compositions.map((item) => {
+ if (item.composition_type == 'loading') { item._destroy = true; }
});
}
}
@@ -365,32 +379,21 @@ export default class Sample extends Element {
return this._contains_residues;
}
- title(selected = false) {
- const profile = UserStore.getState().profile
- const show_external_name = profile ? profile.show_external_name : false
- const show_sample_name = profile ? profile.show_sample_name : false
- const external_label = this.external_label;
- const extLabelClass = this.highlight_label(!selected);
- const name = this.name;
- const short_label = this.short_label;
+ title() {
+ const { profile } = UserStore.getState();
+ const show_external_name = profile ? profile.show_external_name : false;
+ const show_sample_name = profile ? profile.show_sample_name : false;
+ const { external_label } = this;
+ const extLabelClass = 'label--bold';
+ const { name } = this;
+ const { short_label } = this;
if (show_external_name) {
return (external_label ? {external_label} : short_label);
- } else if(show_sample_name) {
+ } if (show_sample_name) {
return (name ? {name} : short_label);
- } else {
- return short_label;
}
- }
-
- highlight_label(gray) {
- let cssClass = null;
- if (!gray) {
- cssClass = 'label--bold';
- } else {
- cssClass = 'label--bold c-text--grey';
- }
- return cssClass;
+ return short_label;
}
get molecule_name_label() {
@@ -434,11 +437,11 @@ export default class Sample extends Element {
}
set preferred_label(label) {
-
+ this._preferred_label = label;
}
set segments(segments) {
- this._segments = (segments && segments.map(s => new Segment(s))) || [];
+ this._segments = (segments && segments.map((s) => new Segment(s))) || [];
}
get segments() {
@@ -454,11 +457,10 @@ export default class Sample extends Element {
}
iupac_name_tag(length) {
- let iupac_name = this.molecule.iupac_name || "";
- return iupac_name.length > length ?
- iupac_name.slice(0, length) + "..."
- :
- iupac_name
+ const iupac_name = this.molecule.iupac_name || '';
+ return iupac_name.length > length
+ ? `${iupac_name.slice(0, length)}...`
+ : iupac_name;
}
get location() {
@@ -540,15 +542,15 @@ export default class Sample extends Element {
this.metrics = (this.metrics && this.metrics.replace(/(.{2}).{1}/, `$1${mp}`)) || 'mmmm';
} else if (unit === 'mol/l') {
if (this.metrics && this.metrics.length === 3) {
- this.metrics = this.metrics + mp;
+ this.metrics += mp;
} else {
this.metrics = (this.metrics && this.metrics.replace(/(.{3}).{1}/, `$1${mp}`)) || 'mmmm';
}
- }
- else {
+ } else {
this.metrics = (this.metrics && this.metrics.replace(/(.{0}).{1}/, `$1${mp}`)) || 'mmmm';
}
}
+
setAmountAndNormalizeToGram(amount) {
this.amount_value = this.convertToGram(amount.value, amount.unit);
this.amount_unit = 'g';
@@ -590,7 +592,7 @@ export default class Sample extends Element {
}
get defined_part_amount() {
- let mw = this.molecule_molecular_weight;
+ const mw = this.molecule_molecular_weight;
return this.amount_mol * mw / 1000.0;
}
@@ -600,7 +602,7 @@ export default class Sample extends Element {
return ({
value: this.amount_value,
unit: this.amount_unit
- })
+ });
}
get amount_value() {
@@ -642,7 +644,7 @@ export default class Sample extends Element {
}
set target_amount_value(amount_value) {
- this._target_amount_value = amount_value
+ this._target_amount_value = amount_value;
}
get target_amount_unit() {
@@ -650,7 +652,7 @@ export default class Sample extends Element {
}
set target_amount_unit(amount_unit) {
- this._target_amount_unit = amount_unit
+ this._target_amount_unit = amount_unit;
}
// real amount
@@ -660,7 +662,7 @@ export default class Sample extends Element {
}
set real_amount_value(amount_value) {
- this._real_amount_value = amount_value
+ this._real_amount_value = amount_value;
}
get real_amount_unit() {
@@ -668,7 +670,7 @@ export default class Sample extends Element {
}
set real_amount_unit(amount_unit) {
- this._real_amount_unit = amount_unit
+ this._real_amount_unit = amount_unit;
}
get amount_g() {
@@ -691,7 +693,7 @@ export default class Sample extends Element {
convertGramToUnit(amount_g = 0, unit) {
if (this.contains_residues) {
- let loading = this.residues[0].custom_info.loading;
+ const { loading } = this.residues[0].custom_info;
switch (unit) {
case 'g':
return amount_g;
@@ -710,8 +712,8 @@ export default class Sample extends Element {
const purity = this.purity || 1.0;
const molarity = this.molarity_value;
return (amount_g * purity) / (molarity * molecularWeight);
- } else if (this.has_density) {
- const density = this.density;
+ } if (this.has_density) {
+ const { density } = this;
return amount_g / (density * 1000);
}
@@ -741,7 +743,7 @@ export default class Sample extends Element {
case 'mg':
return amountValue / 1000.0;
case 'mol': {
- const loading = this.residues[0].custom_info.loading;
+ const { loading } = this.residues[0].custom_info;
if (!loading) return 0.0;
return (amountValue / loading) * 1000.0;
@@ -759,7 +761,7 @@ export default class Sample extends Element {
if (this.has_molarity) {
const molecularWeight = this.molecule_molecular_weight;
return amount_value * this.molarity_value * molecularWeight;
- } else if (this.has_density) {
+ } if (this.has_density) {
return amount_value * (this.density || 1.0) * 1000;
}
return 0;
@@ -814,15 +816,15 @@ export default class Sample extends Element {
}
get purity() {
- return this._purity
+ return this._purity;
}
set purity(purity) {
- this._purity = purity
+ this._purity = purity;
}
get molecule() {
- return this._molecule
+ return this._molecule;
}
set molecule(molecule) {
@@ -880,30 +882,30 @@ export default class Sample extends Element {
get error_loading() {
// TODO: temporary disabled
- //return this.contains_residues && !this.loading && !this.reaction_product;
+ // return this.contains_residues && !this.loading && !this.reaction_product;
return false;
}
-
get isValid() {
- return (this && ((this.molfile && !this.decoupled) || this.decoupled) &&
- !this.error_loading && !this.error_polymer_type);
+ return (this && ((this.molfile && !this.decoupled) || this.decoupled)
+ && !this.error_loading && !this.error_polymer_type);
}
get svgPath() {
if (this.show_label) {
- return `svg_text/${this.labelText}`
+ return `svg_text/${this.labelText}`;
}
if (this.sample_svg_file) {
if (this.sample_svg_file === '***') {
- return `/images/wild_card/no_image_180.svg`
+ return '/images/wild_card/no_image_180.svg';
}
return `/images/samples/${this.sample_svg_file}`;
}
- return this.molecule && this.molecule.molecule_svg_file ? `/images/molecules/${this.molecule.molecule_svg_file}` : '';
+ return this.molecule && this.molecule.molecule_svg_file
+ ? `/images/molecules/${this.molecule.molecule_svg_file}` : '';
}
- //todo: have a dedicated Material Sample subclass
+ // todo: have a dedicated Material Sample subclass
get labelText() {
return this.name || this.molecule_formula || this.molecule.iupac_name;
@@ -947,10 +949,10 @@ export default class Sample extends Element {
return params;
}
- //Container & Analyses routines
+ // Container & Analyses routines
addAnalysis(analysis) {
this.container.children.filter(
- element => ~element.container_type.indexOf('analyses')
+ (element) => ~element.container_type.indexOf('analyses')
)[0].children.push(analysis);
}
@@ -966,7 +968,7 @@ export default class Sample extends Element {
calculateMaxAmount(referenceSample) {
const refAmount = referenceSample.amount_mol;
const sampleCoeff = this.coefficient || 1.0;
- const refCoeff = (referenceSample.coefficient || 1.0)
+ const refCoeff = (referenceSample.coefficient || 1.0);
const coeffQuotient = sampleCoeff / refCoeff;
this.maxAmount = refAmount * coeffQuotient * this.molecule_molecular_weight;
@@ -974,73 +976,69 @@ export default class Sample extends Element {
get solvent() {
try {
- //handle the old solvent data
- const jsonSolvent = JSON.parse(this._solvent)
- let solv = []
+ // handle the old solvent data
+ const jsonSolvent = JSON.parse(this._solvent);
+ const solv = [];
if (jsonSolvent) {
- solv.push(jsonSolvent)
+ solv.push(jsonSolvent);
}
- return solv
+ return solv;
+ } catch (e) {
+ return this._solvent;
}
- catch (e) {}
- return this._solvent
}
set solvent(solvent) {
- this._solvent = solvent
+ this._solvent = solvent;
}
addSolvent(newSolvent) {
- const molecule = newSolvent.molecule
+ const { molecule } = newSolvent;
if (molecule) {
- let tmpSolvents = []
+ const tmpSolvents = [];
if (this.solvent) {
- Object.assign(tmpSolvents, this.solvent)
+ Object.assign(tmpSolvents, this.solvent);
}
- const solventData = { label: molecule.iupac_name, smiles: molecule.cano_smiles, inchikey: molecule.inchikey, ratio: 1 }
- const filtered = tmpSolvents.find((solv) => {
- return (solv && solv.label === solventData.label &&
- solv.smiles === solventData.smiles &&
- solv.inchikey && solventData.inchikey)
- })
+ const solventData = {
+ label: molecule.iupac_name, smiles: molecule.cano_smiles, inchikey: molecule.inchikey, ratio: 1
+ };
+ const filtered = tmpSolvents.find((solv) => (solv && solv.label === solventData.label
+ && solv.smiles === solventData.smiles
+ && solv.inchikey && solventData.inchikey));
if (!filtered) {
- tmpSolvents.push(solventData)
+ tmpSolvents.push(solventData);
}
- this.solvent = tmpSolvents
+ this.solvent = tmpSolvents;
}
}
deleteSolvent(solventToDelete) {
- let tmpSolvents = []
+ const tmpSolvents = [];
if (this.solvent) {
- Object.assign(tmpSolvents, this.solvent)
+ Object.assign(tmpSolvents, this.solvent);
}
- const filteredIndex = tmpSolvents.findIndex((solv) => {
- return (solv.label === solventToDelete.label &&
- solv.smiles === solventToDelete.smiles &&
- solv.inchikey === solventToDelete.inchikey)
- })
+ const filteredIndex = tmpSolvents.findIndex((solv) => (solv.label === solventToDelete.label
+ && solv.smiles === solventToDelete.smiles
+ && solv.inchikey === solventToDelete.inchikey));
if (filteredIndex >= 0) {
tmpSolvents.splice(filteredIndex, 1);
}
- this.solvent = tmpSolvents
+ this.solvent = tmpSolvents;
}
updateSolvent(solventToUpdate) {
- let tmpSolvents = []
+ const tmpSolvents = [];
if (this.solvent) {
- Object.assign(tmpSolvents, this.solvent)
+ Object.assign(tmpSolvents, this.solvent);
}
- const filteredIndex = tmpSolvents.findIndex((solv) => {
- return (solv.smiles === solventToUpdate.smiles &&
- solv.inchikey && solventToUpdate.inchikey)
- })
+ const filteredIndex = tmpSolvents.findIndex((solv) => (solv.smiles === solventToUpdate.smiles
+ && solv.inchikey && solventToUpdate.inchikey));
if (filteredIndex >= 0) {
- tmpSolvents[filteredIndex] = solventToUpdate
+ tmpSolvents[filteredIndex] = solventToUpdate;
}
- this.solvent = tmpSolvents
+ this.solvent = tmpSolvents;
}
}
diff --git a/app/packs/src/models/Segment.js b/app/packs/src/models/Segment.js
index e3673b51ff..ede2aee10e 100644
--- a/app/packs/src/models/Segment.js
+++ b/app/packs/src/models/Segment.js
@@ -1,3 +1,5 @@
+import { cloneDeep } from 'lodash';
+import { buildInitWF, resetProperties } from 'chem-generic-ui';
import Element from 'src/models/Element';
export default class Segment extends Element {
@@ -5,69 +7,33 @@ export default class Segment extends Element {
const template = (klass && klass.properties_release) || {};
return new Segment({
segment_klass_id: this.segment_klass_id || (klass && klass.id),
- properties: template,
+ properties: buildInitWF(template),
select_options: template.select_options || {},
segment_klass: klass,
- properties_release: [],
- files: []
+ properties_release: cloneDeep(template),
+ files: [],
+ wfLayers: template,
});
}
+ static buildCopy(_segments) {
+ const newSegments = cloneDeep(_segments);
+ newSegments.map((_segment) => {
+ // eslint-disable-next-line no-param-reassign
+ _segment.properties = resetProperties(_segment.properties);
+ return _segment;
+ });
+ return newSegments;
+ }
+
serialize() {
return super.serialize({
klassType: 'Segment',
segment_klass: this.segment_klass,
segment_klass_id: this.segment_klass_id,
properties: this.properties,
- files: this.files
+ properties_release: this.properties_release,
+ files: this.files,
});
}
-
- get name() {
- return this._name;
- }
-
- set name(name) {
- this._name = name;
- }
-
- get segment_klass() {
- return this._segment_klass;
- }
-
- set segment_klass(klass) {
- this._segment_klass = klass;
- }
-
- get klassName() {
- return this._klass_name;
- }
- set klassName(klassName) {
- this._klass_name = klassName;
- }
-
-
- get properties() {
- return this._properties;
- }
-
- set properties(properties) {
- this._properties = properties;
- }
-
- get select_options() {
- return this._select_options;
- }
-
- set select_options(select_options) {
- this._select_options = select_options;
- }
-
- get segment_klass_id() {
- return this._segment_klass_id;
- }
-
- set segment_klass_id(segment_klass_id) {
- this._segment_klass_id = segment_klass_id;
- }
}
diff --git a/app/packs/src/models/Wellplate.js b/app/packs/src/models/Wellplate.js
index b99e1b8c36..4aa86c2c21 100644
--- a/app/packs/src/models/Wellplate.js
+++ b/app/packs/src/models/Wellplate.js
@@ -1,6 +1,8 @@
+/* eslint-disable camelcase */
+/* eslint-disable no-underscore-dangle */
import Element from 'src/models/Element';
import Well from 'src/models/Well';
-import Container from 'src/models/Container.js';
+import Container from 'src/models/Container';
import Segment from 'src/models/Segment';
export default class Wellplate extends Element {
@@ -13,7 +15,7 @@ export default class Wellplate extends Element {
static buildEmpty(collection_id) {
return new Wellplate(
{
- collection_id: collection_id,
+ collection_id,
type: 'wellplate',
name: 'New Wellplate',
size: 96,
@@ -24,35 +26,31 @@ export default class Wellplate extends Element {
segments: [],
attachments: []
}
- )
+ );
}
static buildFromSamplesAndCollectionId(clipboardSamples, collection_id) {
- let samples = clipboardSamples.map(sample => {
- return sample.buildChild();
- });
+ const samples = clipboardSamples.map((sample) => sample.buildChild());
- let wells = samples.map(sample => {
- return new Well({
- sample: sample,
- readouts: []
- });
- })
+ const wells = samples.map((sample) => new Well({
+ sample,
+ readouts: []
+ }));
return new Wellplate(
{
- collection_id: collection_id,
+ collection_id,
type: 'wellplate',
name: 'New Wellplate',
size: 96,
description: Wellplate.quillDefault(),
- wells: wells,
+ wells,
readout_titles: [],
container: Container.init(),
segments: [],
attachments: [],
}
- )
+ );
}
get name() {
@@ -72,15 +70,15 @@ export default class Wellplate extends Element {
}
get wells() {
- return this._wells
+ return this._wells;
}
set wells(wells) {
- this._wells = wells.map(w => new Well(w));
+ this._wells = wells.map((w) => new Well(w));
}
set segments(segments) {
- this._segments = (segments && segments.map(s => new Segment(s))) || [];
+ this._segments = (segments && segments.map((s) => new Segment(s))) || [];
}
get segments() {
@@ -92,11 +90,11 @@ export default class Wellplate extends Element {
name: this.name,
size: this.size,
description: this.description,
- wells: this.wells.map(w => w.serialize()),
+ wells: this.wells.map((w) => w.serialize()),
readout_titles: this.readout_titles,
container: this.container,
attachments: this.attachments,
- segments: this.segments.map(s => s.serialize())
+ segments: this.segments.map((s) => s.serialize())
});
}
@@ -127,7 +125,7 @@ export default class Wellplate extends Element {
}
title() {
- const short_label = this.short_label ? this.short_label : ''
- return this.name ? `${short_label} ${this.name}` : short_label
+ const short_label = this.short_label ? this.short_label : '';
+ return this.name ? `${short_label} ${this.name}` : short_label;
}
}
diff --git a/app/packs/src/models/cellLine/CellLine.js b/app/packs/src/models/cellLine/CellLine.js
new file mode 100644
index 0000000000..5b539865d2
--- /dev/null
+++ b/app/packs/src/models/cellLine/CellLine.js
@@ -0,0 +1,95 @@
+import Element from 'src/models/Element';
+import Container from 'src/models/Container';
+
+export default class CellLine extends Element {
+ static buildEmpty(collectionId, shortLabelIn) {
+ if (collectionId === undefined || !Number.isInteger(Number(collectionId))) {
+ throw new Error(`collection id is not valid: ${collectionId}`);
+ }
+ const cellLine = new CellLine({
+ container: Container.init(),
+ collectionId: Number(collectionId),
+ type: 'cell_line',
+ short_label: shortLabelIn
+ });
+
+ return cellLine;
+ }
+
+ title() {
+ return this.short_label;
+ }
+
+ static createFromRestResponse(collectionId, response) {
+ const cellLine = CellLine.buildEmpty(collectionId, response.short_label);
+ cellLine.amount = response.amount;
+ cellLine.unit = response.unit;
+ cellLine.contamination = response.contamination;
+ cellLine.itemComment = response.description;
+ cellLine.itemName = response.name;
+ cellLine.passage = response.passage;
+ cellLine.id = String(response.id);
+ cellLine.tag = response.tag;
+
+ cellLine.cellLineName = response.cellline_material.name;
+ cellLine.source = response.cellline_material.source;
+ cellLine.growthMedium = response.cellline_material.growth_medium;
+ cellLine.mutation = response.cellline_material.mutation;
+ cellLine.gender = response.cellline_material.gender;
+ cellLine.disease = response.cellline_material.disease;
+ cellLine.organism = response.cellline_material.organism;
+ cellLine.tissue = response.cellline_material.tissue;
+ cellLine.variant = response.cellline_material.variant;
+ cellLine.optimal_growth_temp = response.cellline_material.optimal_growth_temp;
+ cellLine.materialDescription = response.cellline_material.description;
+ cellLine.cellType = response.cellline_material.cell_type;
+ cellLine.bioSafetyLevel = response.cellline_material.biosafety_level;
+ cellLine.cryopreservationMedium = response.cellline_material.cryo_pres_medium;
+ cellLine.is_new = false;
+
+ cellLine.container = response.container;
+
+ return cellLine;
+ }
+
+ copyMaterialFrom(cellLineItem) {
+ this.organism = cellLineItem.organism;
+ this.tissue = cellLineItem.tissue;
+ this.disease = cellLineItem.disease;
+ this.growthMedium = cellLineItem.growthMedium;
+ this.cellLineName = cellLineItem.cellLineName;
+ this.cellType = cellLineItem.cellType;
+ this.mutation = cellLineItem.mutation;
+ this.bioSafetyLevel = cellLineItem.bioSafetyLevel;
+ this.variant = cellLineItem.variant;
+ this.optimal_growth_temp = cellLineItem.optimal_growth_temp;
+ this.cryopreservationMedium = cellLineItem.cryopreservationMedium;
+ this.gender = cellLineItem.gender;
+ this.materialDescription = cellLineItem.materialDescription;
+ this.source = cellLineItem.source;
+ }
+
+ adoptPropsFromMobXModel(mobx) {
+ this.amount = mobx.amount;
+ this.passage = mobx.passage;
+ this.contamination = mobx.contamination;
+ this.source = mobx.source;
+ this.growthMedium = mobx.growthMedium;
+ this.itemDescription = mobx.itemDescription;
+ this.materialDescription = mobx.materialDescription;
+ this.itemName = mobx.itemName;
+ this.gender = mobx.gender;
+ this.optimal_growth_temp = mobx.optimalGrowthTemperature;
+ this.unit = mobx.unit;
+
+ this.cellLineName = mobx.cellLineName;
+ this.mutation = mobx.mutation;
+ this.disease = mobx.disease;
+ this.organism = mobx.organism;
+ this.tissue = mobx.tissue;
+ this.variant = mobx.variant;
+ this.bioSafetyLevel = mobx.bioSafetyLevel;
+ this.cellType = mobx.cellType;
+ this.cryopreservationMedium = mobx.cryopreservationMedium;
+ }
+}
diff --git a/app/packs/src/models/cellLine/CellLineGroup.js b/app/packs/src/models/cellLine/CellLineGroup.js
new file mode 100644
index 0000000000..e1e456efe3
--- /dev/null
+++ b/app/packs/src/models/cellLine/CellLineGroup.js
@@ -0,0 +1,49 @@
+export default class CellLineGroup {
+ constructor() {
+ this.cellLineItems = [];
+ }
+
+ static buildFromElements(cellLineElements = []) {
+ const cellLineGroups = [];
+ cellLineElements.forEach((cellLine) => {
+ CellLineGroup.addCelllineToGroup(cellLine, cellLineGroups);
+ });
+
+ return cellLineGroups;
+ }
+
+ static addCelllineToGroup(cellLine, cellLineGroups) {
+ const matchingGroups = CellLineGroup.findMatchingGroups(cellLineGroups, cellLine);
+
+ if (matchingGroups.length === 0) {
+ CellLineGroup.addCellLineToNewGroup(cellLineGroups, cellLine);
+ } else {
+ matchingGroups[0].cellLineItems.push(cellLine);
+ }
+ }
+
+ static addCellLineToNewGroup(cellLineGroups, cellLine) {
+ const groupInFocus = new CellLineGroup();
+ cellLineGroups.push(groupInFocus);
+ groupInFocus.cellLineItems.push(cellLine);
+ }
+
+ static findMatchingGroups(cellLineGroups, cellLine) {
+ let matchingGroups = [];
+ cellLineGroups.forEach((g) => {
+ if (g.matchingGroup(cellLine)) {
+ matchingGroups = [g];
+ }
+ });
+ return matchingGroups;
+ }
+
+ matchingGroup(cellLineToCheck) {
+ if (this.cellLineItems.length === 0) { return false; }
+
+ const firstItemInGroup = this.cellLineItems[0];
+
+ return firstItemInGroup.cellLineName === cellLineToCheck.cellLineName
+ && firstItemInGroup.source === cellLineToCheck.source;
+ }
+}
diff --git a/app/packs/src/models/cellLine/CellLinePropTypes.js b/app/packs/src/models/cellLine/CellLinePropTypes.js
new file mode 100644
index 0000000000..c693a06d95
--- /dev/null
+++ b/app/packs/src/models/cellLine/CellLinePropTypes.js
@@ -0,0 +1,14 @@
+import PropTypes from 'prop-types';
+
+export const CellLinePropTypeTableEntry = PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ cellLineName: PropTypes.string.isRequired,
+ organism: PropTypes.string.isRequired,
+ disease: PropTypes.string.isRequired,
+ tissue:PropTypes.string.isRequired,
+ mutation:PropTypes.string.isRequired,
+ variant:PropTypes.string.isRequired,
+ bioSafetyLevel:PropTypes.string.isRequired,
+ cryopreservationMedium:PropTypes.string.isRequired,
+ gender:PropTypes.string.isRequired,
+})
\ No newline at end of file
diff --git a/app/packs/src/models/collection/CollectionUtils.js b/app/packs/src/models/collection/CollectionUtils.js
new file mode 100644
index 0000000000..63573347d5
--- /dev/null
+++ b/app/packs/src/models/collection/CollectionUtils.js
@@ -0,0 +1,13 @@
+export default class CollectionUtils {
+ static isReadOnly(currentCollection, userId, isSync) {
+ if (currentCollection.permission_level > 0) { return false; }
+
+ const isShared = currentCollection.is_shared
+ && currentCollection.shared_by_id !== userId;
+
+ const isSynced = isSync
+ && currentCollection.shared_by_id !== userId;
+
+ return isSynced || isShared;
+ }
+}
diff --git a/app/packs/src/stores/alt/actions/CollectionActions.js b/app/packs/src/stores/alt/actions/CollectionActions.js
index 2c35ec858d..62a0f431c2 100644
--- a/app/packs/src/stores/alt/actions/CollectionActions.js
+++ b/app/packs/src/stores/alt/actions/CollectionActions.js
@@ -94,6 +94,28 @@ class CollectionActions {
};
}
+ createTabsSegment(params) {
+ return (dispatch) => {
+ CollectionsFetcher.createTabsSegment(params)
+ .then(() => {
+ dispatch();
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
+ updateTabsSegment(params) {
+ return (dispatch) => {
+ CollectionsFetcher.updateTabsLayout(params)
+ .then(() => {
+ dispatch();
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
bulkUpdateUnsharedCollections(params) {
return (dispatch) => {
CollectionsFetcher.bulkUpdateUnsharedCollections(params)
diff --git a/app/packs/src/stores/alt/actions/CommentActions.js b/app/packs/src/stores/alt/actions/CommentActions.js
new file mode 100644
index 0000000000..29860ba9e7
--- /dev/null
+++ b/app/packs/src/stores/alt/actions/CommentActions.js
@@ -0,0 +1,31 @@
+/* eslint-disable class-methods-use-this */
+
+import alt from 'src/stores/alt/alt';
+import CommentFetcher from 'src/fetchers/CommentFetcher';
+
+class CommentActions {
+ setCommentSection(section) {
+ return section;
+ }
+
+ fetchComments(element) {
+ return (dispatch) => {
+ CommentFetcher.fetchByCommentableId(element.id, element.type)
+ .then((result) => {
+ dispatch(result);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
+ toggleCommentModal(btnAction) {
+ return btnAction;
+ }
+
+ toggleCommentSection() {
+ return null;
+ }
+}
+
+export default alt.createActions(CommentActions);
diff --git a/app/packs/src/stores/alt/actions/ElementActions.js b/app/packs/src/stores/alt/actions/ElementActions.js
index 6f211bcf66..33dd8ef1a9 100644
--- a/app/packs/src/stores/alt/actions/ElementActions.js
+++ b/app/packs/src/stores/alt/actions/ElementActions.js
@@ -10,6 +10,7 @@ import SamplesFetcher from 'src/fetchers/SamplesFetcher';
import MoleculesFetcher from 'src/fetchers/MoleculesFetcher';
import ReactionsFetcher from 'src/fetchers/ReactionsFetcher';
import WellplatesFetcher from 'src/fetchers/WellplatesFetcher';
+import CellLinesFetcher from 'src/fetchers/CellLinesFetcher';
import CollectionsFetcher from 'src/fetchers/CollectionsFetcher';
import ScreensFetcher from 'src/fetchers/ScreensFetcher';
import ResearchPlansFetcher from 'src/fetchers/ResearchPlansFetcher';
@@ -24,6 +25,7 @@ import GenericEl from 'src/models/GenericEl';
import Sample from 'src/models/Sample';
import Reaction from 'src/models/Reaction';
import Wellplate from 'src/models/Wellplate';
+import CellLine from 'src/models/cellLine/CellLine';
import Screen from 'src/models/Screen';
import ResearchPlan from 'src/models/ResearchPlan';
import Report from 'src/models/Report';
@@ -35,6 +37,7 @@ import LiteratureMap from 'src/models/LiteratureMap';
import Prediction from 'src/models/Prediction';
import ReactionSvgFetcher from 'src/fetchers/ReactionSvgFetcher';
import Metadata from 'src/models/Metadata';
+import UserStore from 'src/stores/alt/stores/UserStore';
import _ from 'lodash';
@@ -197,8 +200,29 @@ class ElementActions {
NotificationActions.removeByUid(uid);
}).catch((errorMessage) => { console.log(errorMessage); });
};
+ }
+ fetchBasedOnSearchResultIds(params) {
+ let uid;
+ NotificationActions.add({
+ title: "Searching ...",
+ level: "info",
+ position: "tc",
+ onAdd: function (notificationObject) { uid = notificationObject.uid; }
+ });
+ return (dispatch) => {
+ SearchFetcher.fetchBasedOnSearchResultIds(params)
+ .then((result) => {
+ dispatch(result);
+ NotificationActions.removeByUid(uid);
+ }).catch((errorMessage) => { console.log(errorMessage); });
+ };
+ }
+ dispatchSearchResult(result) {
+ return (dispatch) => {
+ dispatch(result);
+ }
}
// -- Generic --
@@ -298,6 +322,16 @@ class ElementActions {
});
};
}
+ fetchCellLinesByCollectionId(id, queryParams = {}, collectionIsSync = false) {
+ return (dispatch) => {
+ CellLinesFetcher.fetchByCollectionId(id, queryParams, collectionIsSync)
+ .then((result) => {
+ dispatch(result);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
// -- Samples --
@@ -396,6 +430,40 @@ class ElementActions {
return Sample.buildEmpty(collection_id)
}
+ tryFetchCellLineElById(cellLineId) {
+ return (dispatch) => {
+ CellLinesFetcher.fetchById(cellLineId)
+ .then((result) => {
+ dispatch(result);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
+ createCellLine(params){
+ return (dispatch) => {
+ const { currentUser } = UserStore.getState();
+ CellLinesFetcher.create(params,currentUser)
+ .then((result) => {
+ dispatch(result);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
+ generateEmptyCellLine(collectionId,template){
+ const { currentUser } = UserStore.getState();
+ if (!currentUser) {return }
+
+ const cellLineSample= CellLine.buildEmpty(collectionId,`${currentUser.initials}-C${currentUser.cell_lines_count}`);
+ if(template){
+ cellLineSample.copyMaterialFrom(template);
+ }
+ return cellLineSample;
+ }
+
splitAsSubsamples(ui_state) {
return (dispatch) => {
SamplesFetcher.splitAsSubsamples(ui_state)
@@ -745,6 +813,17 @@ class ElementActions {
};
}
+ updateCellLine(params){
+ return (dispatch) => {
+ CellLinesFetcher.update(params)
+ .then((result) => {
+ dispatch(result);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
updateResearchPlan(params) {
return (dispatch) => {
ResearchPlansFetcher.update(params)
@@ -846,7 +925,7 @@ class ElementActions {
// -- General --
refreshElements(type) {
- return type
+ return type;
}
deleteElements(options) {
@@ -907,6 +986,10 @@ class ElementActions {
return sort;
}
+ changeElementsFilter(filter) {
+ return filter;
+ }
+
updateContainerContent(params) {
return (dispatch) => {
ContainerFetcher.updateContainerContent(params)
diff --git a/app/packs/src/stores/alt/actions/InboxActions.js b/app/packs/src/stores/alt/actions/InboxActions.js
index 79ef9e8202..e8d15b7b78 100644
--- a/app/packs/src/stores/alt/actions/InboxActions.js
+++ b/app/packs/src/stores/alt/actions/InboxActions.js
@@ -23,6 +23,14 @@ class InboxActions {
return null;
}
+ changeInboxFilter(filter) {
+ return filter;
+ }
+
+ changeInboxSize(size) {
+ return size;
+ }
+
checkedAll(params) {
return params;
}
@@ -35,11 +43,34 @@ class InboxActions {
return params;
}
+ checkedDeviceAll(params) {
+ return params;
+ }
+
+ checkedDeviceIds(params) {
+ return params;
+ }
+
+ checkDeviceAttachments(params) {
+ return params;
+ }
+
+ prevClick() {
+ return null;
+ }
+
+ nextClick() {
+ return null;
+ }
+
fetchInbox(queryParams = {}) {
return (dispatch) => {
InboxFetcher.fetchInbox(false, queryParams)
.then((result) => {
- dispatch(result.inbox);
+ dispatch({
+ inbox: result.inbox,
+ activeDeviceBoxId: queryParams.activeDeviceBoxId,
+ });
}).catch((errorMessage) => {
console.log(errorMessage);
});
@@ -71,6 +102,17 @@ class InboxActions {
};
}
+ fetchInboxUnsorted() {
+ return (dispatch) => {
+ InboxFetcher.fetchInboxUnsorted()
+ .then((result) => {
+ dispatch(result.inbox);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
+
removeAttachmentFromList(attachment) {
return attachment;
}
diff --git a/app/packs/src/stores/alt/actions/SpectraActions.js b/app/packs/src/stores/alt/actions/SpectraActions.js
index 6d7aa02651..26975ebeb5 100644
--- a/app/packs/src/stores/alt/actions/SpectraActions.js
+++ b/app/packs/src/stores/alt/actions/SpectraActions.js
@@ -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, detector) {
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, detector)
.then((fetchedFiles) => {
dispatch({ fetchedFiles, spcInfo });
cb();
diff --git a/app/packs/src/stores/alt/actions/UIActions.js b/app/packs/src/stores/alt/actions/UIActions.js
index 2fd33151ee..d1f446fdca 100644
--- a/app/packs/src/stores/alt/actions/UIActions.js
+++ b/app/packs/src/stores/alt/actions/UIActions.js
@@ -95,6 +95,10 @@ class UIActions {
return selection;
}
+ setSearchById(selection) {
+ return selection;
+ }
+
selectCollectionWithoutUpdating(collection) {
return collection;
}
@@ -103,6 +107,10 @@ class UIActions {
return null;
}
+ clearSearchById() {
+ return null;
+ }
+
changeNumberOfResultsShown(value) {
return value;
}
@@ -130,6 +138,9 @@ class UIActions {
setProductOnly(bool) {
return bool;
}
+
+ rerenderGenericWorkflow(params) { return params; }
+ showGenericWorkflowModal(show) { return show; }
}
export default alt.createActions(UIActions);
diff --git a/app/packs/src/stores/alt/actions/UserActions.js b/app/packs/src/stores/alt/actions/UserActions.js
index 2470a0c78e..824d7a3255 100644
--- a/app/packs/src/stores/alt/actions/UserActions.js
+++ b/app/packs/src/stores/alt/actions/UserActions.js
@@ -1,6 +1,6 @@
import alt from 'src/stores/alt/alt';
import UsersFetcher from 'src/fetchers/UsersFetcher';
-import SegmentsFetcher from 'src/fetchers/SegmentsFetcher';
+import GenericSgsFetcher from 'src/fetchers/GenericSgsFetcher';
import GenericDSsFetcher from 'src/fetchers/GenericDSsFetcher';
import DocumentHelper from 'src/utilities/DocumentHelper';
@@ -27,6 +27,16 @@ class UserActions {
});
};
}
+ fetchOlsBao() {
+ return (dispatch) => {
+ UsersFetcher.fetchOls('bao')
+ .then((result) => {
+ dispatch(result);
+ }).catch((errorMessage) => {
+ console.log(errorMessage);
+ });
+ };
+ }
fetchCurrentUser() {
return (dispatch) => {
@@ -119,7 +129,7 @@ class UserActions {
fetchSegmentKlasses() {
return (dispatch) => {
- SegmentsFetcher.fetchKlass()
+ GenericSgsFetcher.listSegmentKlass()
.then((result) => {
dispatch(result);
}).catch((errorMessage) => {
diff --git a/app/packs/src/stores/alt/stores/CollectionStore.js b/app/packs/src/stores/alt/stores/CollectionStore.js
index 1c201dc315..1fb4b77cc5 100644
--- a/app/packs/src/stores/alt/stores/CollectionStore.js
+++ b/app/packs/src/stores/alt/stores/CollectionStore.js
@@ -17,7 +17,6 @@ class CollectionStore {
this.bindListeners({
handleTakeOwnership: CollectionActions.takeOwnership,
- //handleFetchGenericEls: CollectionActions.fetchGenericEls,
handleFetchLockedCollectionRoots: CollectionActions.fetchLockedCollectionRoots,
handleFetchUnsharedCollectionRoots: CollectionActions.fetchUnsharedCollectionRoots,
handleFetchSharedCollectionRoots: CollectionActions.fetchSharedCollectionRoots,
@@ -45,11 +44,6 @@ class CollectionStore {
CollectionActions.fetchSyncInCollectionRoots();
}
- //handleFetchGenericEls(result) {
- // console.log(result);
- // this.state.genericEls = result.genericEls;
- //}
-
handleFetchLockedCollectionRoots(results) {
this.state.lockedRoots = results.collections;
}
diff --git a/app/packs/src/stores/alt/stores/CommentStore.js b/app/packs/src/stores/alt/stores/CommentStore.js
new file mode 100644
index 0000000000..9cf4a2c129
--- /dev/null
+++ b/app/packs/src/stores/alt/stores/CommentStore.js
@@ -0,0 +1,38 @@
+import alt from 'src/stores/alt/alt';
+import CommentActions from 'src/stores/alt/actions/CommentActions';
+
+class CommentStore {
+ constructor() {
+ this.state = {
+ comments: [],
+ section: null,
+ showCommentModal: false,
+ showCommentSection: false,
+ };
+
+ this.bindListeners({
+ handleSetCommentSection: CommentActions.setCommentSection,
+ handleFetchComments: CommentActions.fetchComments,
+ handleToggleCommentModal: CommentActions.toggleCommentModal,
+ handleToggleCommentSection: CommentActions.toggleCommentSection,
+ });
+ }
+
+ handleSetCommentSection(section) {
+ this.setState({ section });
+ }
+
+ handleFetchComments(comments) {
+ this.setState({ comments: comments ?? [] });
+ }
+
+ handleToggleCommentModal = (btnAction) => {
+ this.setState({ showCommentModal: btnAction });
+ };
+
+ handleToggleCommentSection() {
+ this.setState({ showCommentSection: !this.state.showCommentSection });
+ }
+}
+
+export default alt.createStore(CommentStore, 'CommentStore');
diff --git a/app/packs/src/stores/alt/stores/ElementStore.js b/app/packs/src/stores/alt/stores/ElementStore.js
index 19bacfa457..2dfd3f13b0 100644
--- a/app/packs/src/stores/alt/stores/ElementStore.js
+++ b/app/packs/src/stores/alt/stores/ElementStore.js
@@ -95,6 +95,13 @@ class ElementStore {
pages: null,
perPage: null
},
+ cell_lines: {
+ elements: [],
+ totalElements: 0,
+ page: null,
+ pages: null,
+ perPage: null
+ },
};
this.state = {
@@ -107,7 +114,6 @@ class ElementStore {
refreshCoefficient: [],
activeKey: 0,
deletingElement: null,
- ////
};
this.bindListeners({
@@ -135,16 +141,21 @@ class ElementStore {
handleDuplicateAnalysisExperiment: ElementActions.duplicateAnalysisExperiment,
handleFetchBasedOnSearchSelection: ElementActions.fetchBasedOnSearchSelectionAndCollection,
+ handleFetchBasedOnSearchResultIds: ElementActions.fetchBasedOnSearchResultIds,
+ handleDispatchSearchResult: ElementActions.dispatchSearchResult,
handleFetchGenericElsByCollectionId: ElementActions.fetchGenericElsByCollectionId,
handleFetchGenericElById: ElementActions.fetchGenericElById,
handleCreateGenericEl: ElementActions.createGenericEl,
+ handleCreateCellLine: ElementActions.createCellLine,
+
handleFetchSamplesByCollectionId: ElementActions.fetchSamplesByCollectionId,
handleFetchReactionsByCollectionId: ElementActions.fetchReactionsByCollectionId,
handleFetchWellplatesByCollectionId: ElementActions.fetchWellplatesByCollectionId,
handleFetchScreensByCollectionId: ElementActions.fetchScreensByCollectionId,
handlefetchResearchPlansByCollectionId: ElementActions.fetchResearchPlansByCollectionId,
+ handlefetchCellLinesByCollectionId: ElementActions.fetchCellLinesByCollectionId,
handleFetchSampleById: ElementActions.fetchSampleById,
handleCreateSample: ElementActions.createSample,
@@ -162,6 +173,7 @@ class ElementStore {
handleSetCurrentElement: ElementActions.setCurrentElement,
handleDeselectCurrentElement: ElementActions.deselectCurrentElement,
handleChangeSorting: ElementActions.changeSorting,
+ handleChangeElementsFilter: ElementActions.changeElementsFilter,
handleFetchReactionById: ElementActions.fetchReactionById,
handleTryFetchById: [
@@ -169,6 +181,7 @@ class ElementStore {
ElementActions.tryFetchWellplateById,
ElementActions.tryFetchGenericElById
],
+ handleFetchCellLineById:ElementActions.tryFetchCellLineElById,
handleCloseWarning: ElementActions.closeWarning,
handleCreateReaction: ElementActions.createReaction,
handleCopyReactionFromId: ElementActions.copyReactionFromId,
@@ -211,13 +224,14 @@ class ElementStore {
ElementActions.generateEmptyResearchPlan,
ElementActions.generateEmptySample,
ElementActions.generateEmptyReaction,
+ ElementActions.generateEmptyCellLine,
ElementActions.showReportContainer,
ElementActions.showFormatContainer,
ElementActions.showComputedPropsGraph,
ElementActions.showComputedPropsTasks,
ElementActions.showDeviceControl,
ElementActions.showLiteratureDetail,
- ElementActions.showPredictionContainer,
+ ElementActions.showPredictionContainer
],
handleFetchMoleculeByMolfile: ElementActions.fetchMoleculeByMolfile,
handleFetchMetadata: ElementActions.fetchMetadata,
@@ -247,6 +261,7 @@ class ElementStore {
ElementActions.updateWellplate,
ElementActions.updateScreen,
ElementActions.updateResearchPlan,
+ ElementActions.updateCellLine,
ElementActions.updateGenericEl,
],
handleUpdateEmbeddedResearchPlan: ElementActions.updateEmbeddedResearchPlan,
@@ -496,6 +511,18 @@ class ElementStore {
});
}
+ handleFetchBasedOnSearchResultIds(result) {
+ Object.keys(result).forEach((key) => {
+ this.state.elements[key] = result[key];
+ });
+ }
+
+ handleDispatchSearchResult(result) {
+ Object.keys(result).forEach((key) => {
+ this.state.elements[key] = result[key];
+ });
+ }
+
handlefetchBasedOnStructureAndCollection(result) {
Object.keys(result).forEach((key) => {
this.state.elements[key] = result[key];
@@ -506,7 +533,7 @@ class ElementStore {
handleDeleteElements(options) {
this.waitFor(UIStore.dispatchToken);
const ui_state = UIStore.getState();
- const { sample, reaction, wellplate, screen, research_plan, currentCollection } = ui_state;
+ const { sample, reaction, wellplate, screen, research_plan, currentCollection, cell_line } = ui_state;
const selecteds = this.state.selecteds.map(s => ({ id: s.id, type: s.type }));
const params = {
options,
@@ -516,7 +543,8 @@ class ElementStore {
screen,
research_plan,
currentCollection,
- selecteds
+ selecteds,
+ cell_line
};
const currentUser = (UserStore.getState() && UserStore.getState().currentUser) || {};
@@ -563,10 +591,12 @@ class ElementStore {
const { profile } = UserStore.getState();
if (profile && profile.data && profile.data.layout) {
const { layout } = profile.data;
+
if (layout.sample && layout.sample > 0) { this.handleRefreshElements('sample'); }
if (layout.reaction && layout.reaction > 0) { this.handleRefreshElements('reaction'); }
if (layout.wellplate && layout.wellplate > 0) { this.handleRefreshElements('wellplate'); }
if (layout.screen && layout.screen > 0) { this.handleRefreshElements('screen'); }
+ if (layout.cell_line && layout.cell_line > 0) { this.handleRefreshElements('cell_line'); }
if (!isSync && layout.research_plan && layout.research_plan > 0) { this.handleRefreshElements('research_plan'); }
@@ -621,6 +651,9 @@ class ElementStore {
handlefetchResearchPlansByCollectionId(result) {
this.state.elements.research_plans = result;
}
+ handlefetchCellLinesByCollectionId(result) {
+ this.state.elements.cell_lines = result;
+ }
// -- Samples --
@@ -921,6 +954,15 @@ class ElementStore {
}
}
+ handleFetchCellLineById(result){
+ this.changeCurrentElement(result);
+ }
+
+ handleCreateCellLine(cellLine) {
+ this.handleRefreshElements('cell_line');
+ this.navigateToNewElement(cellLine);
+ }
+
handleCloseWarning() {
this.state.elementWarning = false
}
@@ -1021,7 +1063,7 @@ class ElementStore {
// TODO if page changed -> fetch
// if there is a currentSearchSelection
// we have to execute the respective action
- const { currentSearchSelection } = uiState;
+ const { currentSearchSelection, currentSearchByID } = uiState;
if (currentSearchSelection != null) {
currentSearchSelection.page_size = uiState.number_of_results;
@@ -1032,6 +1074,8 @@ class ElementStore {
isSync: uiState.isSync,
moleculeSort
});
+ } else if (currentSearchByID != null) {
+ this.handleRefreshElementsForSearchById(type, uiState, currentSearchByID);
} else {
const per_page = uiState.number_of_results;
const { fromDate, toDate, productOnly } = uiState;
@@ -1043,7 +1087,8 @@ class ElementStore {
'fetchReactionsByCollectionId',
'fetchWellplatesByCollectionId',
'fetchScreensByCollectionId',
- 'fetchResearchPlansByCollectionId'
+ 'fetchResearchPlansByCollectionId',
+ 'fetchCellLinesByCollectionId'
];
if (allowedActions.includes(fn)) {
ElementActions[fn](uiState.currentCollection.id, params, uiState.isSync, moleculeSort);
@@ -1063,6 +1108,45 @@ class ElementStore {
})
}
+ handleRefreshElementsForSearchById(type, uiState, currentSearchByID) {
+ currentSearchByID.page_size = uiState.number_of_results;
+ const { filterCreatedAt, fromDate, toDate, productOnly } = uiState;
+ const { moleculeSort } = this.state;
+ const { page } = uiState[type];
+ let filterParams = {};
+ const elnElements = ['sample', 'reaction', 'screen', 'wellplate', 'research_plan'];
+ let modelName = !elnElements.includes(type) ? 'element' : type;
+
+ if (fromDate || toDate || productOnly) {
+ filterParams = {
+ filter_created_at: filterCreatedAt,
+ from_date: fromDate,
+ to_date: toDate,
+ product_only: productOnly,
+ }
+ }
+
+ const selection = {
+ elementType: 'by_ids',
+ id_params: {
+ model_name: `${modelName}`,
+ ids: currentSearchByID[`${type}s`].ids,
+ total_elements: currentSearchByID[`${type}s`].totalElements,
+ with_filter: true,
+ },
+ list_filter_params: filterParams,
+ search_by_method: 'search_by_ids',
+ page_size: currentSearchByID.page_size,
+ };
+
+ ElementActions.fetchBasedOnSearchResultIds.defer({
+ selection: selection,
+ collectionId: uiState.currentCollection.id,
+ page: page,
+ isSync: uiState.isSync,
+ moleculeSort
+ });
+ }
// CurrentElement
handleSetCurrentElement(result) {
@@ -1076,7 +1160,21 @@ class ElementStore {
handleChangeSorting(sort) {
this.state.moleculeSort = sort;
this.waitFor(UIStore.dispatchToken);
- this.handleRefreshElements("sample");
+ this.handleRefreshElements('sample');
+ }
+
+ handleChangeElementsFilter(filter) {
+ const userState = UserStore.getState();
+ if (!userState.profile.filters) {
+ userState.profile.data.filters = {};
+ }
+ userState.profile.data.filters[filter.name] = {
+ sort: filter.sort,
+ group: filter.group,
+ direction: filter.direction,
+ };
+
+ this.handleRefreshElements(filter.name);
}
// //////////////////////
@@ -1228,6 +1326,10 @@ class ElementStore {
this.handleRefreshElements('research_plan');
this.handleUpdateResearchPlanAttaches(updatedElement);
break;
+ case 'cell_line':
+ this.changeCurrentElement(updatedElement);
+ this.handleRefreshElements('cell_line');
+ break;
case 'wellplate':
fetchOls('wellplate');
this.handleRefreshElements('wellplate');
diff --git a/app/packs/src/stores/alt/stores/InboxStore.js b/app/packs/src/stores/alt/stores/InboxStore.js
index e5b37762a4..46c4ed4f9a 100644
--- a/app/packs/src/stores/alt/stores/InboxStore.js
+++ b/app/packs/src/stores/alt/stores/InboxStore.js
@@ -5,6 +5,7 @@ import ElementActions from 'src/stores/alt/actions/ElementActions';
import DetailActions from 'src/stores/alt/actions/DetailActions';
import ElementStore from 'src/stores/alt/stores/ElementStore';
import ArrayUtils from 'src/utilities/ArrayUtils';
+import UserStore from 'src/stores/alt/stores/UserStore';
class InboxStore {
constructor() {
@@ -15,14 +16,19 @@ class InboxStore {
numberOfAttachments: 0,
checkedIds: [],
checkedAll: false,
+ checkedDeviceIds: [],
+ checkedDeviceAll: false,
inboxModalVisible: false,
inboxVisible: false,
currentPage: 1,
itemsPerPage: 20,
currentContainerPage: 1,
+ currentUnsortedBoxPage: 1,
+ currentDeviceBoxPage: 1,
dataItemsPerPage: 35,
totalPages: null,
activeDeviceBoxId: null,
+ inboxSize: 'Medium',
};
this.bindListeners({
@@ -40,6 +46,11 @@ class InboxStore {
handleDeleteContainerLink: InboxActions.deleteContainerLink,
handleCheckedAll: InboxActions.checkedAll,
handleCheckedIds: InboxActions.checkedIds,
+ handleCheckDeviceAttachments: InboxActions.checkDeviceAttachments,
+ handleCheckedDeviceIds: InboxActions.checkedDeviceIds,
+ handleCheckedDeviceAll: InboxActions.checkedDeviceAll,
+ handlePrevClick: InboxActions.prevClick,
+ handleNextClick: InboxActions.nextClick,
handleUpdateCreateElementDict: [
ElementActions.createSample,
@@ -59,6 +70,9 @@ class InboxStore {
handleSetPagination: InboxActions.setInboxPagination,
setInboxVisible: InboxActions.setInboxVisible,
setActiveDeviceBoxId: InboxActions.setActiveDeviceBoxId,
+ handleFetchInboxUnsorted: InboxActions.fetchInboxUnsorted,
+ handleChangeInboxFilter: InboxActions.changeInboxFilter,
+ handleChangeInboxSize: InboxActions.changeInboxSize,
});
}
@@ -76,16 +90,44 @@ class InboxStore {
}
}
- handleFetchInbox(result) {
+ handleFetchInbox(payload) {
const { itemsPerPage } = this.state;
- this.state.inbox = result;
+ this.state.inbox = payload.inbox;
this.state.totalPages = Math.ceil(this.state.inbox.count / itemsPerPage);
- this.state.activeDeviceBoxId = null;
+ this.state.activeDeviceBoxId = payload.activeDeviceBoxId ? payload.activeDeviceBoxId : null;
this.sync();
this.countAttachments();
}
+ handleFetchInboxUnsorted(payload) {
+ this.setState((prevState) => ({
+ inbox: {
+ ...prevState.inbox,
+ unlinked_attachments: payload.unlinked_attachments,
+ inbox_count: payload.inbox_count,
+ },
+ currentUnsortedBoxPage: 1,
+ }));
+ }
+
+ handleChangeInboxFilter(filter) {
+ const userState = UserStore.getState();
+ if (!userState.profile.filters) {
+ userState.profile.data.filters = {};
+ }
+ userState.profile.data.filters[filter.name] = {
+ sort: filter.sort,
+ };
+
+ const { currentPage, itemsPerPage, activeDeviceBoxId } = this.state;
+ InboxActions.fetchInbox({ currentPage, itemsPerPage, activeDeviceBoxId });
+ }
+
+ handleChangeInboxSize(inboxSize) {
+ this.state.inboxSize = inboxSize;
+ }
+
handleFetchInboxCount(result) {
this.state.numberOfAttachments = result.inbox_count;
}
@@ -132,6 +174,22 @@ class InboxStore {
this.countAttachments();
}
+ handlePrevClick() {
+ this.setState((prevState) => ({
+ currentUnsortedBoxPage: prevState.currentUnsortedBoxPage - 1,
+ checkedAll: false,
+ checkedIds: [],
+ }));
+ }
+
+ handleNextClick = () => {
+ this.setState((prevState) => ({
+ currentUnsortedBoxPage: prevState.currentUnsortedBoxPage + 1,
+ checkedAll: false,
+ checkedIds: [],
+ }));
+ };
+
handleRemoveUnlinkedAttachmentFromList(attachment) {
const { inbox } = this.state;
@@ -304,19 +362,84 @@ class InboxStore {
}
handleCheckedIds(params) {
- const { inbox, checkedIds } = this.state;
- const unlikedAttachments = inbox.unlinked_attachments;
+ const {
+ inbox, checkedIds, currentUnsortedBoxPage, dataItemsPerPage,
+ } = this.state;
+ const unlinkedAttachments = inbox.unlinked_attachments;
+ const startIndex = (currentUnsortedBoxPage - 1) * dataItemsPerPage;
+ const endIndex = startIndex + dataItemsPerPage;
+ const currentAttachments = unlinkedAttachments.slice(startIndex, endIndex);
+
if (params.type && params.range === 'child') {
ArrayUtils.pushUniq(checkedIds, params.ids);
} else if (params.type === false && params.range === 'child') {
ArrayUtils.removeFromListByValue(checkedIds || [], params.ids);
} else if (params.range === 'all' && params.type === true) {
- unlikedAttachments.map(attachment => ArrayUtils.pushUniq(checkedIds, attachment.id));
+ currentAttachments.forEach((attachment) => ArrayUtils.pushUniq(checkedIds, attachment.id));
+
this.handleCheckedAll(params);
} else if (params.range === 'all' && params.type === false) {
- unlikedAttachments.map(attachment => ArrayUtils.removeFromListByValue(checkedIds || [], attachment.id));
+ currentAttachments.forEach((attachment) => ArrayUtils.removeFromListByValue(checkedIds || [], attachment.id));
this.handleCheckedAll(params);
}
+
+ // If unsortedBox, remove devicebox attachments from checkedIds
+ if (this.state.activeDeviceBoxId === -1) {
+ for (let i = checkedIds.length - 1; i >= 0; i--) {
+ const checkedId = checkedIds[i];
+ const hasCorrespondingAttachment = currentAttachments.some((attachment) => attachment.id === checkedId);
+ if (!hasCorrespondingAttachment) {
+ checkedIds.splice(i, 1);
+ }
+ }
+ }
+ }
+
+ handleCheckedDeviceAll(params) {
+ const { checkedDeviceAll, inbox, activeDeviceBoxId } = this.state;
+
+ if (params.range === 'all') {
+ if (params.type) {
+ const currentDeviceBox = inbox.children.find((deviceBox) => deviceBox.id === activeDeviceBoxId);
+ if (currentDeviceBox) {
+ const allDatasetIdsFlat = currentDeviceBox.children.map((dataset) => dataset.id);
+ const allAttachments = currentDeviceBox.children.reduce((acc, dataset) => {
+ acc.push(...dataset.attachments);
+ return acc;
+ }, []);
+ const allAttachmentsFlat = _.flatten(allAttachments).map((attachment) => attachment.id);
+
+ this.setState({
+ checkedDeviceIds: allDatasetIdsFlat,
+ checkedIds: allAttachmentsFlat,
+ });
+ }
+ } else {
+ this.setState({
+ checkedDeviceIds: [],
+ checkedIds: [],
+ });
+ }
+ }
+
+ this.setState({ checkedDeviceAll: !checkedDeviceAll });
+ }
+
+ handleCheckedDeviceIds(params) {
+ this.setState({
+ checkedDeviceIds: params.checkedDeviceIds,
+ checkedIds: params.checkedIds
+ });
+ }
+
+ handleCheckDeviceAttachments(params) {
+ const { checkedIds } = this.state;
+
+ const newCheckedIds = (params.isSelected)
+ ? checkedIds.filter((checkedId) => checkedId !== params.ids)
+ : [...checkedIds, params.ids];
+
+ this.setState({ checkedIds: newCheckedIds });
}
}
diff --git a/app/packs/src/stores/alt/stores/LoadingStore.js b/app/packs/src/stores/alt/stores/LoadingStore.js
index 862b9d24c0..1d17852029 100644
--- a/app/packs/src/stores/alt/stores/LoadingStore.js
+++ b/app/packs/src/stores/alt/stores/LoadingStore.js
@@ -38,6 +38,7 @@ class LoadingStore {
ElementActions.storeMetadata,
InboxActions.fetchInbox,
InboxActions.fetchInboxContainer,
+ InboxActions.fetchInboxUnsorted,
PredictionActions.infer,
],
handleStartLoadingWithProgress: LoadingActions.startLoadingWithProgress,
diff --git a/app/packs/src/stores/alt/stores/NotificationStore.js b/app/packs/src/stores/alt/stores/NotificationStore.js
index 4299fbe4d1..af28ca082d 100644
--- a/app/packs/src/stores/alt/stores/NotificationStore.js
+++ b/app/packs/src/stores/alt/stores/NotificationStore.js
@@ -36,48 +36,51 @@ class NotificationStore {
}
handleNotificationImportSamplesFromFile(result) {
- let num = result.data.length;
- let status = result.status;
- let sdf = result.sdf
- let message = result.message;
- this.handleRemoveByUid("import_samples_upload");
+ const num = result.data?.length ?? 0;
+ const { status, sdf, message } = result;
+ this.handleRemoveByUid('import_samples_upload');
let notification = {
- title: "Oops!",
- message: message + "\n Please check the file and try again.",
- level: "error",
- position: "bl",
+ title: 'Oops!',
+ message: `${message}\n Please check the file and try again.`,
+ level: 'error',
+ position: 'bl',
autoDismiss: 0
- }
+ };
if (sdf) {
- if (status == "ok") {
- notification = {
- title: "Success",
- message: message,
- level: "success",
- position: "bl",
- autoDismiss: 10
- }
- } else if (status == "failed"){
- } else if (status == "error"){
- } else if (status == "invalid"){
- notification.message = message;
- }
- } else {
- if (status == "ok") {
+ if (status === 'ok') {
notification = {
- title: "Success",
- message: "The "+num+" samples have been imported successfully",
- level: "success",
- position: "bl",
+ title: 'Success',
+ message,
+ level: 'success',
+ position: 'bl',
autoDismiss: 10
- }
- } else if (status == "failed"){
- } else if (status == "error"){
- } else if (status == "invalid"){
+ };
+ } else if (status === 'invalid') {
notification.message = message;
}
+ } else if (status === 'ok') {
+ notification = {
+ title: 'Success',
+ message: `The ${num} samples have been imported successfully`,
+ level: 'success',
+ position: 'bl',
+ autoDismiss: 10
+ };
+ } else if (status === 'invalid') {
+ notification.message = message;
+ } else if (status === 'in progress') {
+ notification.message = message;
+ notification.title = 'Status';
+ notification.level = 'success';
+ } else if (status === 'warning') {
+ notification = {
+ title: 'Status',
+ message: `The ${num} samples have been imported successfully but ${message}`,
+ level: 'success',
+ position: 'bl',
+ autoDismiss: 10
+ };
}
-
this.handleAdd(notification);
}
diff --git a/app/packs/src/stores/alt/stores/ReportStore.js b/app/packs/src/stores/alt/stores/ReportStore.js
index e91532e601..2f37130d0d 100644
--- a/app/packs/src/stores/alt/stores/ReportStore.js
+++ b/app/packs/src/stores/alt/stores/ReportStore.js
@@ -9,40 +9,49 @@ import UserStore from 'src/stores/alt/stores/UserStore';
import { reOrderArr } from 'src/utilities/DndControl';
import { UpdateSelectedObjs, OrderPreviewObjs } from 'src/utilities/ReportHelper';
+const splSettings = [
+ { checked: true, text: 'diagram' },
+ { checked: true, text: 'collection' },
+ { checked: true, text: 'analyses' },
+ { checked: true, text: 'reaction description' },
+ { checked: true, text: 'literature' },
+];
+
+const rxnSettings = [
+ { checked: true, text: 'diagram' },
+ { checked: true, text: 'material' },
+ { checked: true, text: 'description' },
+ { checked: true, text: 'purification' },
+ { checked: true, text: 'dangerous products' },
+ { checked: true, text: 'tlc' },
+ { checked: true, text: 'observation' },
+ { checked: true, text: 'analysis' },
+ { checked: true, text: 'literature' },
+ { checked: true, text: 'variations' },
+];
+
+const siRxnSettings = [
+ { checked: true, text: 'Name' },
+ { checked: true, text: 'CAS' },
+ { checked: true, text: 'Formula' },
+ { checked: true, text: 'Smiles' },
+ { checked: true, text: 'InChI' },
+ { checked: true, text: 'Molecular Mass' },
+ { checked: true, text: 'Exact Mass' },
+ { checked: true, text: 'EA' },
+];
+
+const configs = [
+ { checked: true, text: 'Page Break' },
+ { checked: true, text: 'Show all chemicals in schemes (unchecked to show products only)' },
+];
+
class ReportStore {
constructor() {
- this.splSettings = [
- { checked: true, text: 'diagram' },
- { checked: true, text: 'collection' },
- { checked: true, text: 'analyses' },
- { checked: true, text: 'reaction description' },
- { checked: true, text: 'literature' },
- ];
- this.rxnSettings = [
- { checked: true, text: 'diagram' },
- { checked: true, text: 'material' },
- { checked: true, text: 'description' },
- { checked: true, text: 'purification' },
- { checked: true, text: 'dangerous products' },
- { checked: true, text: 'tlc' },
- { checked: true, text: 'observation' },
- { checked: true, text: 'analysis' },
- { checked: true, text: 'literature' },
- ];
- this.siRxnSettings = [
- { checked: true, text: 'Name' },
- { checked: true, text: 'CAS' },
- { checked: true, text: 'Formula' },
- { checked: true, text: 'Smiles' },
- { checked: true, text: 'InChI' },
- { checked: true, text: 'Molecular Mass' },
- { checked: true, text: 'Exact Mass' },
- { checked: true, text: 'EA' },
- ];
- this.configs = [
- { checked: true, text: 'Page Break' },
- { checked: true, text: 'Show all chemicals in schemes (unchecked to show products only)' },
- ];
+ this.splSettings = splSettings;
+ this.rxnSettings = rxnSettings;
+ this.siRxnSettings = siRxnSettings;
+ this.configs = configs;
this.checkedAllSplSettings = true;
this.checkedAllRxnSettings = true;
this.checkedAllSiRxnSettings = true;
@@ -452,6 +461,7 @@ class ReportStore {
{ text: 'observation', checked: rs.observation },
{ text: 'analysis', checked: rs.analysis },
{ text: 'literature', checked: rs.literature },
+ { text: 'variations', checked: rs.variations },
],
siRxnSettings:
[
@@ -533,42 +543,10 @@ class ReportStore {
checkedAllRxnSettings: true,
checkedAllSiRxnSettings: true,
checkedAllConfigs: true,
- splSettings:
- [
- { text: 'diagram', checked: true },
- { text: 'collection', checked: true },
- { text: 'analyses', checked: true },
- { text: 'reaction description', checked: true },
- { text: 'literature', checked: true },
- ],
- rxnSettings:
- [
- { text: 'diagram', checked: true },
- { text: 'material', checked: true },
- { text: 'description', checked: true },
- { text: 'purification', checked: true },
- { text: 'dangerous products', checked: true },
- { text: 'tlc', checked: true },
- { text: 'observation', checked: true },
- { text: 'analysis', checked: true },
- { text: 'literature', checked: true },
- ],
- siRxnSettings:
- [
- { checked: true, text: 'Name' },
- { checked: true, text: 'CAS' },
- { checked: true, text: 'Formula' },
- { checked: true, text: 'Smiles' },
- { checked: true, text: 'InChI' },
- { checked: true, text: 'Molecular Mass' },
- { checked: true, text: 'Exact Mass' },
- { checked: true, text: 'EA' },
- ],
- configs:
- [
- { text: 'Page Break', checked: true },
- { text: 'Show all chemicals in schemes (unchecked to show products only)', checked: true },
- ],
+ splSettings,
+ rxnSettings,
+ siRxnSettings,
+ configs,
defaultObjTags: { sampleIds: [], reactionIds: [] },
selectedObjTags: { sampleIds: [], reactionIds: [] },
selectedObjs: [],
diff --git a/app/packs/src/stores/alt/stores/SpectraStore.js b/app/packs/src/stores/alt/stores/SpectraStore.js
index 6d5828918e..45a286e7c0 100644
--- a/app/packs/src/stores/alt/stores/SpectraStore.js
+++ b/app/packs/src/stores/alt/stores/SpectraStore.js
@@ -42,7 +42,7 @@ class SpectraStore {
const { file, predictions, id } = target;
if (!file) return null;
let spectrum = { predictions: defaultPred, idx: id };
- if (predictions.outline && predictions.outline.code) {
+ if (predictions && predictions.outline && predictions.outline.code) {
spectrum = Object.assign({}, spectrum, { predictions });
}
@@ -83,14 +83,21 @@ class SpectraStore {
handleLoadSpectra({ fetchedFiles, spcInfos }) {
const spcMetas = this.decodeSpectra(fetchedFiles);
+ const sortedSpcInfo = [...spcInfos];
+ sortedSpcInfo.sort((a, b) => a.label.localeCompare(b.label));
+ const sortedSpcIdxs = sortedSpcInfo.map((info) => (info.idx));
+ spcMetas.sort((a, b) => {
+ return sortedSpcIdxs.indexOf(a.idx) - sortedSpcIdxs.indexOf(b.idx);
+ });
let newArrSpcIdx = spcMetas.map(spci => (
spci.idx
)).filter(r => r !== null);
if (newArrSpcIdx.length <= 1) {
newArrSpcIdx = [];
}
+
this.setState({
- spcInfos,
+ spcInfos: sortedSpcInfo,
spcMetas,
fetched: true,
spcIdx: (spcMetas[0].idx || 0),
diff --git a/app/packs/src/stores/alt/stores/UIStore.js b/app/packs/src/stores/alt/stores/UIStore.js
index 51f8d229cc..6d5975582a 100644
--- a/app/packs/src/stores/alt/stores/UIStore.js
+++ b/app/packs/src/stores/alt/stores/UIStore.js
@@ -51,6 +51,13 @@ class UIStore {
currentId: null,
page: 1,
},
+ cell_line: {
+ checkedAll: false,
+ checkedIds: List(),
+ uncheckedIds: List(),
+ currentId: null,
+ page: 1,
+ },
showPreviews: true,
showAdvancedSearch: false,
filterCreatedAt: true,
@@ -60,6 +67,7 @@ class UIStore {
number_of_results: 15,
currentCollection: null,
currentSearchSelection: null,
+ currentSearchByID: null,
showCollectionManagement: false,
showDeviceManagement: false,
isSync: false,
@@ -67,22 +75,10 @@ class UIStore {
modalParams: {},
hasChemSpectra: false,
hasNmriumWrapper: false,
- matrices: {}
+ matrices: {},
+ thirdPartyApps: [],
};
- // console.log(this.state.klasses);
- // // eslint-disable-next-line no-unused-expressions
- // this.state.klasses && this.state.klasses.forEach((klass) => {
- // this.state[`${klass}`] = {
- // checkedAll: false,
- // checkedIds: List(),
- // uncheckedIds: List(),
- // currentId: null,
- // page: 1,
- // activeTab: 0,
- // };
- // });
-
this.bindListeners({
handleInitialize: UIActions.initialize,
handleSelectTab: UIActions.selectTab,
@@ -101,9 +97,11 @@ class UIStore {
handleSetPagination: UIActions.setPagination,
handleDeselectAllElements: UIActions.deselectAllElements,
handleSetSearchSelection: UIActions.setSearchSelection,
+ handleSetSearchById: UIActions.setSearchById,
handleSelectCollectionWithoutUpdating:
UIActions.selectCollectionWithoutUpdating,
handleClearSearchSelection: UIActions.clearSearchSelection,
+ handleClearSearchById: UIActions.clearSearchById,
handleShowCollectionManagement: UIActions.showCollectionManagement,
handleShowElements: UIActions.showElements,
handleToggleCollectionManagement: UIActions.toggleCollectionManagement,
@@ -117,13 +115,16 @@ class UIStore {
handleSetFromDate: UIActions.setFromDate,
handleSetToDate: UIActions.setToDate,
handleSetProductOnly: UIActions.setProductOnly,
+ handleRerenderGenericWorkflow: UIActions.rerenderGenericWorkflow,
+ handleShowGenericWorkflowModal: UIActions.showGenericWorkflowModal,
});
}
handleInitialize(result) {
+ console.log(result)
this.setState(result);
const { klasses } = result;
- klasses && klasses.forEach((klass) => {
+ klasses?.forEach((klass) => {
this.state[`${klass}`] = {
checkedAll: false,
checkedIds: List(),
@@ -135,6 +136,16 @@ class UIStore {
});
}
+
+ handleRerenderGenericWorkflow(params) {
+ this.state.propGenericWorkflow = params;
+ if (params.toggle) { this.state.showGenericWorkflow = !this.state.showGenericWorkflow; }
+ }
+
+ handleShowGenericWorkflowModal(show) {
+ this.state.showGenericWorkflow = show;
+ }
+
handleToggleCollectionManagement() {
this.state.showCollectionManagement = !this.state.showCollectionManagement;
}
@@ -219,9 +230,11 @@ class UIStore {
handleUncheckAllElements(params) {
let { type, range } = params;
- this.state[type].checkedAll = false;
- this.state[type].checkedIds = List();
- this.state[type].uncheckedIds = List();
+ if (this.state[type]) {
+ this.state[type].checkedAll = false;
+ this.state[type].checkedIds = List();
+ this.state[type].uncheckedIds = List();
+ }
}
handleUncheckWholeSelection() {
@@ -230,7 +243,8 @@ class UIStore {
this.handleUncheckAllElements({ type: 'reaction', range: 'all' });
this.handleUncheckAllElements({ type: 'wellplate', range: 'all' });
this.handleUncheckAllElements({ type: 'research_plan', range: 'all' });
- this.state.klasses && this.state.klasses.forEach((klass) => { this.handleUncheckAllElements({ type: klass, range: 'all' }); });
+ this.handleUncheckAllElements({ type: 'cell_line', range: 'all' });
+ this.state.klasses?.forEach((klass) => { this.handleUncheckAllElements({ type: klass, range: 'all' }); });
}
handleCheckElement(element) {
@@ -287,6 +301,7 @@ class UIStore {
hasChanged = hasChanged || state.currentCollection.id != collection.id;
hasChanged = hasChanged || isSync != state.isSync;
hasChanged = hasChanged || state.currentSearchSelection != null;
+ hasChanged = hasChanged || state.currentSearchByID != null;
}
if (collection['clearSearch']) {
@@ -300,56 +315,118 @@ class UIStore {
this.state.currentCollection = collection;
const per_page = state.number_of_results;
const params = { per_page, filterCreatedAt, fromDate, toDate, productOnly };
-
const { profile } = UserStore.getState();
+
if (profile && profile.data && profile.data.layout) {
const { layout } = profile.data;
- if (layout.sample && layout.sample > 0) {
- ElementActions.fetchSamplesByCollectionId(
- collection.id, Object.assign(params, { page: state.sample.page }),
- isSync, ElementStore.getState().moleculeSort
- );
- }
- if (layout.reaction && layout.reaction > 0) {
- ElementActions.fetchReactionsByCollectionId(
- collection.id, Object.assign(params, { page: state.reaction.page }),
- isSync
- );
- }
- if (layout.wellplate && layout.wellplate > 0) {
- ElementActions.fetchWellplatesByCollectionId(
- collection.id, Object.assign(params, { page: state.wellplate.page }),
- isSync
- );
- }
- if (layout.screen && layout.screen > 0) {
- ElementActions.fetchScreensByCollectionId(
- collection.id, Object.assign(params, { page: state.screen.page }),
- isSync
- );
- }
- if (!isSync && layout.research_plan && layout.research_plan > 0) {
- ElementActions.fetchResearchPlansByCollectionId(
- collection.id,
- Object.assign(params, { page: state.research_plan.page }),
- );
- }
- Object.keys(layout).filter(l => !['sample', 'reaction', 'screen', 'wellplate', 'research_plan'].includes(l)).forEach((key) => {
- if (typeof layout[key] !== 'undefined' && layout[key] > 0) {
- const page = state[key] ? state[key].page : 1;
- ElementActions.fetchGenericElsByCollectionId(
+ if (state.currentSearchByID) {
+ this.handleSelectCollectionForSearchById(layout, collection);
+ } else {
+ if (layout.sample && layout.sample > 0) {
+ ElementActions.fetchSamplesByCollectionId(
+ collection.id, Object.assign(params, { page: state.sample.page }),
+ isSync, ElementStore.getState().moleculeSort
+ );
+ }
+ if (layout.reaction && layout.reaction > 0) {
+ ElementActions.fetchReactionsByCollectionId(
+ collection.id, Object.assign(params, { page: state.reaction.page }),
+ isSync
+ );
+ }
+ if (layout.wellplate && layout.wellplate > 0) {
+ ElementActions.fetchWellplatesByCollectionId(
+ collection.id, Object.assign(params, { page: state.wellplate.page }),
+ isSync
+ );
+ }
+ if (layout.screen && layout.screen > 0) {
+ ElementActions.fetchScreensByCollectionId(
+ collection.id, Object.assign(params, { page: state.screen.page }),
+ isSync
+ );
+ }
+ if (!isSync && layout.research_plan && layout.research_plan > 0) {
+ ElementActions.fetchResearchPlansByCollectionId(
collection.id,
- Object.assign(params, { page, name: key }),
- isSync,
- key
+ Object.assign(params, { page: state.research_plan.page }),
);
}
- });
+ if (!isSync && layout.cell_line && layout.cell_line > 0) {
+ ElementActions.fetchCellLinesByCollectionId(
+ collection.id,
+ Object.assign(params, { page: state.cell_line.page }),
+ );
+ }
+
+ Object.keys(layout).filter(l => !['sample', 'reaction', 'screen', 'wellplate', 'research_plan', 'cell_line'].includes(l)).forEach((key) => {
+ if (typeof layout[key] !== 'undefined' && layout[key] > 0) {
+ const page = state[key] ? state[key].page : 1;
+ ElementActions.fetchGenericElsByCollectionId(
+ collection.id,
+ Object.assign(params, { page, name: key }),
+ isSync,
+ key
+ );
+ }
+ });
+ }
}
}
}
+ handleSelectCollectionForSearchById(layout, collection) {
+ const state = this.state;
+ const isSync = state.isSync;
+ const searchResult = { ...state.currentSearchByID };
+ const { filterCreatedAt, fromDate, toDate, productOnly } = state;
+ const { moleculeSort } = ElementStore.getState();
+ const per_page = state.number_of_results;
+
+ Object.keys(state.currentSearchByID).forEach((key) => {
+ if (layout[key.slice(0, -1)] > 0 && searchResult[key].totalElements > 0) {
+ if (productOnly && key != 'samples') { return }
+ let filterParams = {};
+ const elnElements = ['sample', 'reaction', 'screen', 'wellplate', 'research_plan'];
+ let modelName = !elnElements.includes(key.slice(0, -1)) ? 'element' : key.slice(0, -1);
+
+ if (fromDate || toDate || productOnly) {
+ filterParams = {
+ filter_created_at: filterCreatedAt,
+ from_date: fromDate,
+ to_date: toDate,
+ product_only: productOnly,
+ }
+ }
+
+ const with_filter = Object.keys(filterParams).length >= 1 ? true : false;
+
+ const selection = {
+ elementType: 'by_ids',
+ id_params: {
+ model_name: modelName,
+ ids: searchResult[key].ids,
+ total_elements: searchResult[key].totalElements,
+ with_filter: with_filter,
+ },
+ list_filter_params: filterParams,
+ search_by_method: 'search_by_ids',
+ page_size: per_page
+ };
+
+ ElementActions.fetchBasedOnSearchResultIds.defer({
+ selection,
+ collectionId: collection.id,
+ isSync: isSync,
+ page_size: per_page,
+ page: searchResult[key].page,
+ moleculeSort
+ });
+ }
+ });
+ }
+
handleSelectSyncCollection(collection) {
this.handleSelectCollection(collection)
}
@@ -364,6 +441,10 @@ class UIStore {
this.state.currentSearchSelection = selection;
}
+ handleSetSearchById(selection) {
+ this.state.currentSearchByID = selection;
+ }
+
handleSelectCollectionWithoutUpdating(collection) {
this.state.currentCollection = collection;
this.state.isSync = collection.is_sync_to_me ? true : false;
@@ -374,6 +455,10 @@ class UIStore {
this.state.showAdvancedSearch = false;
}
+ handleClearSearchById() {
+ this.state.currentSearchByID = null;
+ }
+
handleChangeNumberOfResultsShown(value) {
this.state.number_of_results = value;
}
diff --git a/app/packs/src/stores/alt/stores/UserStore.js b/app/packs/src/stores/alt/stores/UserStore.js
index e6451e19bf..62a1876a6e 100644
--- a/app/packs/src/stores/alt/stores/UserStore.js
+++ b/app/packs/src/stores/alt/stores/UserStore.js
@@ -19,12 +19,14 @@ class UserStore {
dsKlasses: [],
unitsSystem: {},
matriceConfigs: [],
- omniauthProviders: []
+ omniauthProviders: [],
+ bao:[]
};
this.bindListeners({
handleFetchOlsRxno: UserActions.fetchOlsRxno,
handleFetchOlsChmo: UserActions.fetchOlsChmo,
+ handleFetchOlsBao: UserActions.fetchOlsBao,
handleFetchGenericEls: UserActions.fetchGenericEls,
handleFetchCurrentUser: UserActions.fetchCurrentUser,
handleFetchUserLabels: UserActions.fetchUserLabels,
@@ -47,6 +49,9 @@ class UserStore {
handleFetchEditors(result) {
this.state.matriceConfigs = result.matrices;
}
+ handleFetchOlsBao(result) {
+ this.state.bao = result.ols_terms;
+ }
handleFetchOlsRxno(result) {
this.state.rxnos = result.ols_terms;
@@ -109,7 +114,8 @@ class UserStore {
}
handleOmniauthProviders(result) {
- this.state.omniauthProviders = result;
+ this.state.omniauthProviders = result.omniauth_providers;
+ this.state.extraRules = result.extra_rules;
}
}
diff --git a/app/packs/src/stores/mobx/CellLineDetailsStore.jsx b/app/packs/src/stores/mobx/CellLineDetailsStore.jsx
new file mode 100644
index 0000000000..73e55582ef
--- /dev/null
+++ b/app/packs/src/stores/mobx/CellLineDetailsStore.jsx
@@ -0,0 +1,226 @@
+import { types } from 'mobx-state-tree';
+import Container from 'src/models/Container';
+
+const MAX_AMOUNT = 10e17;
+
+const CellLineAnalysis = types
+ .model({
+ id: 0,
+ children: types.array(types.late(() => CellLineAnalysis)),
+ name: '',
+ container_type: '',
+ extended_metadata: '',
+ description: ''
+
+ }).actions((self) => ({
+ setDescription(newValue) {
+ self.description = newValue;
+ }
+ }
+ ));
+
+const CellLineItem = types
+ .model({
+ cellLineId: -1,
+ id: '',
+ organism: '',
+ tissue: '',
+ gender: '',
+ cellType: '',
+ mutation: '',
+ disease: '',
+ bioSafetyLevel: 'S0',
+ variant: '',
+ optimalGrowthTemperature: 0,
+ cryopreservationMedium: '',
+ cellLineName: '',
+ materialDescription: '',
+ amount: 0,
+ passage: 0,
+ contamination: '',
+ shortLabel: '',
+ unit: '',
+ source: '',
+ growthMedium: '',
+ itemDescription: '',
+ itemName: '',
+ changed: false
+ }).views((self) => ({
+ isAmountValid() {
+ return Number.isInteger(self.amount) && self.amount > 0 && self.amount < MAX_AMOUNT;
+ }
+ })).actions((self) => ({
+ setChanged(newChanged) {
+ self.changed = newChanged;
+ }
+ }));
+
+export const CellLineDetailsStore = types
+ .model({
+ cellLineItem: types.map(CellLineItem)
+ })
+ .actions((self) => ({
+ changeItemName(id, newItemName) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).itemName = newItemName;
+ },
+ changeGrowthMedium(id, newGrowthMedium) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).growthMedium = newGrowthMedium;
+ },
+ changeSource(id, newSource) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).source = newSource;
+ },
+ changeAmount(id, newAmount) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).amount = newAmount;
+ },
+ changeUnit(id, newUnit) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).unit = newUnit;
+ },
+ changeContamination(id, newContamination) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).contamination = newContamination;
+ },
+ changePassage(id, newPassage) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).passage = newPassage;
+ },
+ changeCellLineName(id, newCellLineName) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).cellLineName = newCellLineName;
+ },
+ changeMutation(id, newMutation) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).mutation = newMutation;
+ },
+ changeDisease(id, newDisease) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).disease = newDisease;
+ },
+ changeOrganism(id, newOrganism) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).organism = newOrganism;
+ },
+ changeItemDescription(id, newDesc) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).itemDescription = newDesc;
+ },
+ changeMaterialDescription(id, newDesc) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).materialDescription = newDesc;
+ },
+ changeTissue(id, newTissue) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).tissue = newTissue;
+ },
+ changeOptimalGrowthTemp(id, newTemp) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).optimalGrowthTemperature = newTemp;
+ },
+ changeVariant(id, newVariant) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).variant = newVariant;
+ },
+ changeBioSafetyLevel(id, newBioSafetyLevel) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).bioSafetyLevel = newBioSafetyLevel;
+ },
+ changeCryoMedium(id, newCryoMedium) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).cryopreservationMedium = newCryoMedium;
+ },
+ changeGender(id, newGender) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).gender = newGender;
+ },
+ changeCellType(id, newType) {
+ self.cellLineItem.get(id).changed = true;
+ self.cellLineItem.get(id).cellType = newType;
+ },
+ removeCellLineFromStore(id) {
+ self.cellLineItem.delete(id);
+ },
+ addEmptyContainer(id) {
+ const container = Container.buildEmpty();
+ container.container_type="analysis"
+ return container;
+ },
+ setMaterialProperties(id, properties) {
+ const item = self.cellLineItem.get(id);
+ if (item === undefined) { throw new Error(`no cellline with id found: ${id}`); }
+
+ item.bioSafetyLevel = properties.biosafety_level;
+ item.cellType = properties.cell_type;
+ item.cryopreservationMedium = properties.cryo_pres_medium;
+ item.materialDescription = properties.description;
+ item.disease = properties.disease;
+ item.gender = properties.gender;
+ this.changeOptimalGrowthTemp(id, properties.optimal_growth_temp);
+ item.organism = properties.organism;
+ item.tissue = properties.tissue;
+ item.variant = properties.variant;
+ item.mutation = properties.mutation;
+ item.source = properties.source;
+ item.growthMedium = properties.growth_medium;
+ },
+ convertJsModelToMobxModel(container) {
+ return CellLineAnalysis.create({
+ id: container.id,
+ children: [],
+ name: container.name,
+ container_type: container.container_type
+ });
+ },
+ convertCellLineToModel(jsCellLineModel) {
+ if (self.cellLineItem.has(jsCellLineModel.id)) {
+ return;
+ }
+
+ self.cellLineItem.set(jsCellLineModel.id, CellLineItem.create({
+ cellLineId: jsCellLineModel.cellLineId,
+ id: jsCellLineModel.id.toString(),
+ organism: jsCellLineModel.organism,
+ tissue: jsCellLineModel.tissue,
+ cellType: jsCellLineModel.cellType,
+ mutation: jsCellLineModel.mutation,
+ disease: jsCellLineModel.disease,
+ itemDescription: jsCellLineModel.itemComment,
+ bioSafetyLevel: jsCellLineModel.bioSafetyLevel,
+ variant: jsCellLineModel.variant,
+ optimalGrowthTemperature: jsCellLineModel.optimal_growth_temp,
+ cryopreservationMedium: jsCellLineModel.cryopreservationMedium,
+ cellLineName: jsCellLineModel.cellLineName,
+ materialDescription: jsCellLineModel.materialDescription,
+ gender: jsCellLineModel.gender,
+ amount: jsCellLineModel.amount,
+ unit: jsCellLineModel.unit,
+ passage: jsCellLineModel.passage,
+ contamination: jsCellLineModel.contamination,
+ source: jsCellLineModel.source,
+ growthMedium: jsCellLineModel.growthMedium,
+ itemName: jsCellLineModel.itemName,
+ shortLabel: jsCellLineModel.short_label,
+ }));
+ }
+ }))
+ .views((self) => ({
+ cellLines(id) {
+ return self.cellLineItem.get(id);
+ },
+ analysisAmount(id) {
+ return self.cellLineItem.get(id).container.children[0].children.length;
+ },
+ checkInputValidity(id) {
+ const result = [];
+ const item = self.cellLineItem.get(id);
+ if (item.cellLineName.trim() === '') { result.push('cellLineName'); }
+ if (item.source.trim() === '') { result.push('source'); }
+ if (item.unit.trim() === '') { result.push('unit'); }
+ if (!item.isAmountValid()) { result.push('amount'); }
+ if (!Number.isInteger(item.passage) || item.passage === 0) { result.push('passage'); }
+ return result;
+ }
+ }));
diff --git a/app/packs/src/stores/mobx/RootStore.jsx b/app/packs/src/stores/mobx/RootStore.jsx
index ea473fdaf4..c5938d0b24 100644
--- a/app/packs/src/stores/mobx/RootStore.jsx
+++ b/app/packs/src/stores/mobx/RootStore.jsx
@@ -2,14 +2,20 @@ import React from 'react';
import { types } from 'mobx-state-tree';
import { MeasurementsStore } from 'src/stores/mobx/MeasurementsStore';
import { SampleTasksStore } from 'src/stores/mobx/SampleTasksStore';
+import { CellLineDetailsStore } from 'src/stores/mobx/CellLineDetailsStore';
+import { SearchStore } from 'src/stores/mobx/SearchStore';
export const RootStore = types
.model({
measurementsStore: types.optional(MeasurementsStore, { measurements: {}, sampleHeaders: {} }),
- sampleTasksStore: types.optional(SampleTasksStore, {})
+ sampleTasksStore: types.optional(SampleTasksStore, {}),
+ cellLineDetailsStore: types.optional(CellLineDetailsStore, {}),
+ searchStore: types.optional(SearchStore, {})
})
.views(self => ({
get measurements() { return self.measurementsStore },
- get sampleTasks() { return self.sampleTasksStore }
+ get sampleTasks() { return self.sampleTasksStore },
+ get cellLineDetails() { return self.CellLineDetailsStore },
+ get search() { return self.searchStore }
}));
export const StoreContext = React.createContext(RootStore.create({}));
diff --git a/app/packs/src/stores/mobx/SampleTasksStore.jsx b/app/packs/src/stores/mobx/SampleTasksStore.jsx
index d42e802b29..35a63cfbd5 100644
--- a/app/packs/src/stores/mobx/SampleTasksStore.jsx
+++ b/app/packs/src/stores/mobx/SampleTasksStore.jsx
@@ -19,14 +19,14 @@ const SampleTask = types.model({
display_name: types.maybeNull(types.string),
short_label: types.maybeNull(types.string),
sample_svg_file: types.maybeNull(types.string),
- image: types.maybeNull(types.string),
+ required_scan_results: types.number,
scan_results: types.array(ScanResult)
});
export const SampleTasksStore = types
.model({
sample_tasks: types.map(SampleTask), // automatically wrapped to types.optional(types.map(SampleTask), {})
- inbox_visible: types.optional(types.boolean, false) // default set manually
+ inbox_visible: types.optional(types.boolean, false), // default set manually
})
.actions(self => ({
// here we are using async actions (https://mobx-state-tree.js.org/concepts/async-actions) to use promises
@@ -54,6 +54,13 @@ export const SampleTasksStore = types
let createdSampleTask = SampleTask.create({ ...result });
self.sample_tasks.set(createdSampleTask.id, createdSampleTask)
}
+ }),
+ deleteSampleTask: flow(function* deleteSampleTask(sampleTask) {
+ let result = yield SampleTasksFetcher.deleteSampleTask(sampleTask.id)
+ if (result.deleted == sampleTask.id) {
+ self.sample_tasks.delete(sampleTask.id)
+ }
+ return result
})
}))
.views(self => ({
@@ -61,5 +68,6 @@ export const SampleTasksStore = types
get inboxVisible() { return self.inbox_visible },
sampleTaskForSample(sampleId) {
return values(self.sample_tasks).find(task => task.sample_id == sampleId)
- }
+ },
+ get sortedSampleTasks() { return values(self.sample_tasks).sort((taskA, taskB) => taskB.id - taskA.id) },
}));
diff --git a/app/packs/src/stores/mobx/SearchStore.jsx b/app/packs/src/stores/mobx/SearchStore.jsx
new file mode 100644
index 0000000000..413109a8c0
--- /dev/null
+++ b/app/packs/src/stores/mobx/SearchStore.jsx
@@ -0,0 +1,309 @@
+import { keys, values } from 'mobx';
+import { flow, types } from 'mobx-state-tree';
+
+import SearchFetcher from 'src/fetchers/SearchFetcher';
+
+const SearchResult = types.model({
+ id: types.maybeNull(types.string),
+ results: types.maybeNull(types.frozen({}))
+});
+
+const SearchFilter = types.model({
+ id: types.maybeNull(types.string),
+ filters: types.maybeNull(types.frozen([]))
+});
+
+const advancedSearch = {
+ value: 'advanced',
+ label: 'Text Search'
+}
+
+const defaultSearchValues = [{
+ link: '',
+ match: '=',
+ table: 'samples',
+ element_id: 0,
+ field: {
+ column: 'name',
+ label: 'Name',
+ },
+ value: '',
+ smiles: '',
+ sub_values: [],
+ unit: '',
+ validationState: null
+}];
+
+const defaultPublicationValues = [{
+ link: '',
+ match: '=',
+ table: 'literatures',
+ field: {
+ column: 'doi',
+ label: 'DOI',
+ },
+ value: '',
+}];
+
+const defaultKetcherValues = {
+ queryMolfile: null,
+ searchType: 'sub',
+ tanimotoThreshold: 0.7
+};
+
+const searchElementValues = {
+ table: 'samples',
+ element_id: 0,
+ element_table: 'samples'
+}
+
+export const SearchStore = types
+ .model({
+ search_modal_visible: types.optional(types.boolean, false),
+ search_modal_minimized: types.optional(types.boolean, false),
+ search_modal_selected_form: types.optional(types.frozen({}), advancedSearch),
+ search_type: types.optional(types.string, "advanced"),
+ search_element: types.optional(types.frozen({}), searchElementValues),
+ advanced_search_values: types.optional(types.array(types.frozen({})), defaultSearchValues),
+ detail_search_values: types.optional(types.array(types.frozen({})), []),
+ ketcher_rails_values: types.optional(types.frozen({}), defaultKetcherValues),
+ publication_search_values: types.optional(types.array(types.frozen({})), defaultPublicationValues),
+ search_results: types.map(SearchResult),
+ tab_search_results: types.map(SearchResult),
+ search_result_panel_visible: types.optional(types.boolean, false),
+ search_results_visible: types.optional(types.boolean, false),
+ search_visible: types.optional(types.boolean, true),
+ search_filters: types.map(SearchFilter),
+ search_values: types.optional(types.array(types.string), []),
+ search_icon: types.optional(types.enumeration("search_icon", ["right", "down"]), "down"),
+ result_icon: types.optional(types.enumeration("result_icon", ["right", "down"]), "right"),
+ error_messages: types.optional(types.array(types.string), []),
+ tab_current_page: types.optional(types.array(types.frozen({})), []),
+ active_tab_key: types.optional(types.number, 0),
+ show_search_result_list: types.optional(types.boolean, false),
+ result_error_messages: types.optional(types.array(types.string), []),
+ })
+ .actions(self => ({
+ // here we are using async actions (https://mobx-state-tree.js.org/concepts/async-actions) to use promises
+ // within an action
+ loadSearchResults: flow(function* loadSearchResults(params) {
+ let result = yield SearchFetcher.fetchBasedOnSearchSelectionAndCollection(params);
+ self.search_results.clear();
+ self.tab_search_results.clear();
+ Object.entries(result).forEach(([key, value]) => {
+ let errorExists = self.result_error_messages.find((e) => { return e == value.error });
+ if (value.error !== undefined && value.error !== '' && errorExists === undefined) {
+ self.result_error_messages.push(value.error);
+ }
+ let searchResult = SearchResult.create({
+ id: key,
+ results: {
+ ids: value.ids,
+ page: value.page,
+ pages: value.pages,
+ per_page: value.perPage,
+ total_elements: value.totalElements
+ }
+ })
+ self.search_results.set(searchResult.id, searchResult)
+ self.addSearchResult(key, value, value.ids.slice(0, 15))
+ });
+ }),
+ loadSearchResultTab: flow(function* loadSearchResultTab(params) {
+ let result = yield SearchFetcher.fetchBasedOnSearchResultIds(params);
+ Object.entries(result).forEach(([key, value]) => {
+ self.addSearchResult(key, value, [])
+ });
+ }),
+ showSearchModal() {
+ self.search_modal_visible = true;
+ },
+ hideSearchModal() {
+ self.search_modal_visible = false;
+ },
+ showMinimizedSearchModal() {
+ self.search_modal_minimized = false;
+ },
+ toggleSearchModalMinimized() {
+ self.search_modal_minimized = !self.search_modal_minimized;
+ },
+ changeSearchModalSelectedForm(value) {
+ self.search_modal_selected_form = value;
+ self.clearSearchResults();
+ self.showMinimizedSearchModal();
+ },
+ changeSearchType(e) {
+ self.resetAdvancedSearchValue();
+ self.detail_search_values = [];
+ self.resetPublicationSearchValue();
+ self.search_type = (e.target.checked == true ? 'detail' : 'advanced');
+ self.active_tab_key = 0;
+ },
+ changeSearchElement(elementValues) {
+ self.resetAdvancedSearchValue();
+ self.detail_search_values = [];
+ self.resetPublicationSearchValue();
+ self.search_element = elementValues;
+ self.active_tab_key = 0;
+ },
+ addAdvancedSearchValue(id, values) {
+ self.advanced_search_values[id] = values;
+ },
+ resetAdvancedSearchValue() {
+ self.advanced_search_values = defaultSearchValues;
+ },
+ addDetailSearchValue(key, values) {
+ let index = self.detail_search_values.findIndex((x) => { return Object.keys(x).indexOf(key) != -1 })
+ if (index != -1) {
+ self.detail_search_values[index] = { [key]: values };
+ } else {
+ self.detail_search_values.push({ [key]: values });
+ }
+ },
+ removeDetailSearchValue(key) {
+ let index = self.detail_search_values.findIndex((x) => { return Object.keys(x).indexOf(key) != -1 })
+ if (index != -1) {
+ self.detail_search_values.splice(index, 1);
+ }
+ },
+ changeKetcherRailsValue(key, value) {
+ let ketcherValues = { ...self.ketcher_rails_values };
+ ketcherValues[key] = value;
+ self.ketcher_rails_values = ketcherValues;
+ },
+ resetKetcherRailsValues() {
+ self.ketcher_rails_values = defaultKetcherValues;
+ },
+ addPublicationSearchValue(id, values) {
+ self.publication_search_values[id] = values;
+ },
+ resetPublicationSearchValue() {
+ self.publication_search_values = defaultPublicationValues;
+ },
+ addSearchResult(key, result, ids) {
+ let tabSearchResult = SearchResult.create({
+ id: `${key}-${result.page || 1}`,
+ results: {
+ elements: result.elements,
+ ids: ids.length > 0 ? ids : result.ids,
+ page: result.page
+ }
+ })
+ self.tab_search_results.set(tabSearchResult.id, tabSearchResult)
+ },
+ showSearchResults() {
+ self.search_results_visible = true;
+ self.search_result_panel_visible = true;
+ self.search_visible = false;
+ self.search_icon = "right";
+ self.result_icon = "down";
+ },
+ hideSearchResults() {
+ self.search_results_visible = false;
+ self.search_result_panel_visible = false;
+ self.search_visible = true;
+ self.search_icon = "down";
+ self.result_icon = "right";
+ },
+ toggleSearchResults() {
+ self.search_results_visible = !self.search_results_visible;
+ self.result_icon = self.search_results_visible ? "down" : "right";
+ self.search_icon = self.result_icon == "right" ? "down" : "right";
+ },
+ clearSearchAndTabResults() {
+ self.search_results.clear();
+ self.tab_search_results.clear();
+ self.clearTabCurrentPage();
+ },
+ clearSearchResults() {
+ self.clearSearchAndTabResults();
+ self.hideSearchResults();
+ self.search_filters.clear();
+ self.search_values.clear();
+ self.error_messages = [];
+ self.clearTabCurrentPage();
+ self.resetAdvancedSearchValue();
+ self.detail_search_values = [];
+ self.active_tab_key = 0;
+ self.resetKetcherRailsValues();
+ self.resetPublicationSearchValue();
+ self.result_error_messages = [];
+ },
+ toggleSearch() {
+ self.search_visible = !self.search_visible;
+ self.search_icon = self.search_visible ? "down" : "right";
+ self.result_icon = self.search_icon == "right" ? "down" : "right";
+ },
+ changeSearchFilter(filtered_options) {
+ let filter = SearchFilter.create({ id: 'filter', filters: filtered_options });
+ self.search_filters.clear();
+ self.search_filters.set(filter.id, filter);
+ },
+ changeSearchValues(values) {
+ self.search_values.clear();
+ self.search_values = values;
+ },
+ addErrorMessage(message) {
+ if (!self.error_messages.includes(message)) {
+ self.error_messages.push(message);
+ }
+ },
+ removeErrorMessage(message) {
+ let neededFieldsMessage = 'Please fill out all needed fields';
+ let error_messages = self.error_messages.filter((m) => { return m != message && m != neededFieldsMessage });
+ self.error_messages = error_messages;
+ },
+ changeTabCurrentPage(key, index, id) {
+ self.tab_current_page[id] = { [key]: index };
+ },
+ clearTabCurrentPage() {
+ self.tab_current_page.splice(0, self.tab_current_page.length);
+ },
+ changeActiveTabKey(key) {
+ self.active_tab_key = key;
+ },
+ handleCancel() {
+ self.hideSearchModal();
+ self.hideSearchResults();
+ if (!self.show_search_result_list) {
+ self.clearSearchResults();
+ }
+ self.active_tab_key = 0;
+ self.result_error_messages = [];
+ },
+ handleAdopt() {
+ self.hideSearchModal();
+ self.hideSearchResults();
+ self.active_tab_key = 0;
+ self.changeShowSearchResultListValue(true);
+ self.result_error_messages = [];
+ },
+ changeShowSearchResultListValue(value) {
+ self.show_search_result_list = value;
+ if (!value) {
+ self.clearSearchResults();
+ }
+ }
+ }))
+ .views(self => ({
+ get searchModalVisible() { return self.search_modal_visible },
+ get searchModalMinimized() { return self.search_modal_minimized },
+ get searchModalSelectedForm() { return self.search_modal_selected_form },
+ get searchResultsCount() { return keys(self.search_results).length },
+ get searchResultValues() { return values(self.search_results) },
+ get tabSearchResultValues() { return values(self.tab_search_results) },
+ get searchResultVisible() { return self.search_results_visible },
+ get searchVisible() { return self.search_visible },
+ get searchFilters() { return values(self.search_filters) },
+ get searchValues() { return values(self.search_values) },
+ get searchType() { return self.search_type },
+ get searchElement() { return self.search_element },
+ get advancedSearchValues() { return values(self.advanced_search_values) },
+ get detailSearchValues() { return values(self.detail_search_values) },
+ get ketcherRailsValues() { return self.ketcher_rails_values },
+ get publicationSearchValues() { return values(self.publication_search_values) },
+ get tabCurrentPage() { return values(self.tab_current_page) },
+ get activeTabKey() { return self.active_tab_key },
+ get errorMessages() { return values(self.error_messages) },
+ get resultErrorMessage() { return values(self.result_error_messages) },
+ }));
diff --git a/app/packs/src/utilities/CellLineUtils.js b/app/packs/src/utilities/CellLineUtils.js
new file mode 100644
index 0000000000..a546fc538a
--- /dev/null
+++ b/app/packs/src/utilities/CellLineUtils.js
@@ -0,0 +1,32 @@
+const extractApiParameter = (cellLine) => {
+ return {
+ "cell_line_sample_id":cellLine.id,
+ "organism":cellLine.organism,
+ "tissue":cellLine.tissue,
+ "amount":cellLine.amount,
+ "passage":cellLine.passage,
+ "disease":cellLine.disease,
+ "growth_medium":cellLine.growthMedium,
+ "material_names":cellLine.cellLineName,
+ "collection_id":cellLine.collectionId,
+ "cell_type":cellLine.cellType,
+ "mutation":cellLine.mutation,
+ "unit":cellLine.unit,
+ "biosafety_level":cellLine.bioSafetyLevel,
+ "variant":cellLine.variant,
+ "optimal_growth_temp":cellLine.optimal_growth_temp,
+ "cryo_pres_medium":cellLine.cryopreservationMedium,
+ "gender":cellLine.gender,
+ "material_description":cellLine.materialDescription,
+ "contamination":cellLine.contamination,
+ "source":cellLine.source,
+ "name":cellLine.itemName,
+ "description":cellLine.itemDescription,
+ "short_label":cellLine.short_label,
+ "container":cellLine.container
+};
+}
+
+export {
+ extractApiParameter
+};
\ No newline at end of file
diff --git a/app/packs/src/utilities/CollectionTabsHelper.js b/app/packs/src/utilities/CollectionTabsHelper.js
new file mode 100644
index 0000000000..f734b7f0cc
--- /dev/null
+++ b/app/packs/src/utilities/CollectionTabsHelper.js
@@ -0,0 +1,60 @@
+import { getElementSegments } from './ElementUtils';
+import Immutable from 'immutable';
+
+const getVisibilityList = (layout, availableTabs, addInventoryTab) => {
+ const layoutKeys = Object.keys(layout);
+
+ if (addInventoryTab) {
+ layout.inventory = layoutKeys.length + 1;
+ }
+ const enabled = availableTabs.filter(val => layoutKeys.includes(val));
+ const leftover = availableTabs.filter(val => !layoutKeys.includes(val));
+ const visible = [];
+ let hidden = [];
+
+ enabled.forEach((key) => {
+ const order = layout[key];
+ if (order < 0) { hidden[Math.abs(order)] = key; }
+ if (order > 0) { visible[order] = key; }
+ });
+
+ leftover.forEach(key => hidden.push(key));
+
+ let first = null;
+ if (visible.length === 0) {
+ first = hidden.filter(n => n !== undefined)[0];
+ if (first) {
+ visible.push(first);
+ }
+ }
+ hidden = hidden.filter(n => n);
+ if (hidden.length === 0) {
+ hidden.push('hidden');
+ }
+ return {
+ visible: Immutable.List(visible.filter(n => n !== undefined)),
+ hidden: Immutable.List(hidden.filter(n => (n !== undefined && n !== first)))
+ };
+};
+
+const getArrayFromLayout = (layout, element, addInventoryTab, availableTabs = null ) => {
+ let layoutKeys = Object.keys(layout);
+ let segmentAvailableTabs = availableTabs ? [] : getElementSegments(element, layoutKeys);
+ availableTabs = [...availableTabs, ...segmentAvailableTabs];
+ return getVisibilityList(layout, availableTabs, addInventoryTab);
+};
+
+const filterTabLayout = (layoutState) => {
+ const { visible, hidden } = layoutState;
+ const layout = {};
+
+ visible.forEach((value, index) => {
+ layout[value] = (index + 1);
+ });
+ hidden.filter(val => val !== 'hidden').forEach((value, index) => {
+ layout[value] = (-index - 1);
+ });
+ return layout;
+};
+
+export { getArrayFromLayout, filterTabLayout };
diff --git a/app/packs/src/utilities/CommentHelper.js b/app/packs/src/utilities/CommentHelper.js
new file mode 100644
index 0000000000..3112ed4f3b
--- /dev/null
+++ b/app/packs/src/utilities/CommentHelper.js
@@ -0,0 +1,24 @@
+const formatSection = (section, type = '') => {
+ const words = type ? section?.replace(`${type}_`, '')?.split('_') : section?.replace('_header', '')?.split('_');
+ for (let i = 0; i < words?.length; i += 1) {
+ words[i] = words[i][0].toUpperCase() + words[i].substr(1);
+ }
+ return words?.join(' ');
+};
+
+const getSectionComments = (comments, section) => {
+ return comments?.filter((cmt) => (cmt.section === section));
+};
+const getAllComments = (comments, section) => comments?.filter((cmt) => (cmt.section !== section));
+
+const selectCurrentUser = (state) => state.currentUser || {};
+
+const commentActivation = 'commentActivation';
+
+export {
+ formatSection,
+ getSectionComments,
+ getAllComments,
+ selectCurrentUser,
+ commentActivation,
+};
diff --git a/app/packs/src/utilities/ElementUtils.js b/app/packs/src/utilities/ElementUtils.js
index d35c1b001d..96b60a7407 100644
--- a/app/packs/src/utilities/ElementUtils.js
+++ b/app/packs/src/utilities/ElementUtils.js
@@ -2,8 +2,10 @@ import Aviator from 'aviator';
import _ from 'lodash';
import { deltaToMarkdown, markdownToDelta } from 'src/utilities/deltaMarkdownConverter';
import { searchAndReplace } from 'src/utilities/markdownUtils';
+import MatrixCheck from 'src/components/common/MatrixCheck';
import UIStore from 'src/stores/alt/stores/UIStore';
+import UserStore from '../stores/alt/stores/UserStore';
const rfValueFormat = (input) => {
if (typeof input !== 'string') { return input; }
@@ -459,6 +461,16 @@ const instrumentText = (analysis) => {
return ` Instrument: ${ttlIns.length}/${analysis.children.length}`;
};
+const getElementSegments = (elementName, tabs) => {
+ let segmentKlasses = (UserStore.getState() && UserStore.getState().segmentKlasses) || [];
+ const currentUser = (UserStore.getState() && UserStore.getState().currentUser) || {};
+ let labels = segmentKlasses.filter(s => s.element_klass.name == elementName).map(s => s.label);
+ if (!MatrixCheck(currentUser.matrix, 'segment')) {
+ return tabs.filter((key) => !labels.includes(key));
+ }
+ return _.uniq(tabs.concat(labels));
+}
+
export {
rfValueFormat,
hNmrCheckMsg,
@@ -478,4 +490,5 @@ export {
atomCountCInNMRDescription,
emwInStr,
instrumentText,
+ getElementSegments
};
diff --git a/app/packs/src/utilities/SpectraHelper.js b/app/packs/src/utilities/SpectraHelper.js
index fdb96328ac..3667de4fc4 100644
--- a/app/packs/src/utilities/SpectraHelper.js
+++ b/app/packs/src/utilities/SpectraHelper.js
@@ -66,7 +66,7 @@ const extractJcampWithFailedFiles = (container) => {
const isJcamp = acceptables.indexOf(ext.toLowerCase()) >= 0;
const isApp = [
'idle', 'queueing', 'done',
- 'backup', 'image','non_jcamp',
+ 'backup', 'image', 'non_jcamp',
].indexOf(att.aasm_state) < 0;
if (isJcamp && isApp) {
const file = Object.assign({}, att, {
@@ -90,7 +90,7 @@ const extractNMRiumFiles = (container) => {
const fns = att.filename.split('.');
const ext = fns[fns.length - 1];
const isNMRium = ext.toLowerCase() === 'nmrium';
-
+
if (isNMRium) {
const file = Object.assign({}, att, {
idDt: dt.id,
@@ -122,7 +122,7 @@ const BuildSpcInfos = (sample, container) => {
const files = extractJcampFiles(container);
if (files.length < 1) return [];
const idAe = extractAnalysesId(sample, container);
- return files.map(file => (
+ return files.map((file) => (
{
value: null,
label: file.filename,
@@ -143,7 +143,7 @@ const BuildSpcInfosForNMRDisplayer = (sample, container) => {
files.push(...nmriumFiles);
if (files.length < 1) return [];
const idAe = extractAnalysesId(sample, container);
- return files.map(file => (
+ return files.map((file) => (
{
value: null,
label: file.filename,
@@ -157,4 +157,72 @@ const BuildSpcInfosForNMRDisplayer = (sample, container) => {
));
};
-export { BuildSpcInfos, BuildSpcInfosForNMRDisplayer, JcampIds }; // eslint-disable-line
+const listNMROntology = (chmos, storedSet, parentIsNMR = false) => {
+ if (Array.isArray(chmos)) {
+ chmos.forEach((obj) => {
+ const { children } = obj;
+ if (children && children.length > 0) {
+ children.forEach((child) => {
+ listNMROntology(child, storedSet);
+ });
+ } else {
+ return storedSet;
+ }
+ });
+ } else {
+ const { children, value } = chmos;
+ let isNMR = parentIsNMR;
+ if (value && (value.toLowerCase().includes('nuclear magnetic resonance') || parentIsNMR)) {
+ storedSet.add(value);
+ isNMR = true;
+ } else if(typeof chmos === 'string' && (chmos.toLowerCase().includes('nuclear magnetic resonance') || parentIsNMR)) {
+ storedSet.add(value);
+ isNMR = true;
+ } else {
+ isNMR = false;
+ }
+ if (children && children.length > 0) {
+ children.forEach((child) => {
+ listNMROntology(child, storedSet, isNMR);
+ });
+ } else {
+ return storedSet;
+ }
+ }
+ return storedSet;
+};
+
+const isNMRKind = (container, chmos = []) => {
+ if (!(container && container.extended_metadata && container.extended_metadata.kind)) return false;
+ const { extended_metadata } = container; // eslint-disable-line
+ const { kind } = extended_metadata; // eslint-disable-line
+ let setToBeStored = new Set([]);
+ const ontologies = Array.from(listNMROntology(chmos, setToBeStored));
+ const filtered = ontologies.filter((ontology) => {
+ return kind === ontology || kind.toLowerCase().includes(ontology);
+ });
+ return filtered.length > 0;
+};
+
+const cleaningNMRiumData = (nmriumData) => {
+ if (!nmriumData) return null;
+ const cleanedNMRiumData = { ...nmriumData };
+
+ const { data } = cleanedNMRiumData;
+ if (!data) return cleanedNMRiumData;
+
+ const { spectra } = data;
+ if (!spectra) return cleanedNMRiumData;
+
+ const newSpectra = spectra.map((spc) => {
+ const tmpSpc = { ...spc };
+ delete tmpSpc.originalData;
+ return tmpSpc;
+ });
+
+ data.spectra = [...newSpectra];
+
+ return cleanedNMRiumData;
+};
+
+export { BuildSpcInfos, BuildSpcInfosForNMRDisplayer, JcampIds, isNMRKind, cleaningNMRiumData }; // eslint-disable-line
diff --git a/app/packs/src/utilities/imageHelper.js b/app/packs/src/utilities/imageHelper.js
index e096e1e690..1c486d795b 100644
--- a/app/packs/src/utilities/imageHelper.js
+++ b/app/packs/src/utilities/imageHelper.js
@@ -1,4 +1,8 @@
-const previewContainerImage = (container, noAttSvg = '/images/wild_card/no_attachment.svg', noAvaSvg = '/images/wild_card/not_available.svg') => {
+const previewContainerImage = (
+ container,
+ noAttSvg = '/images/wild_card/no_attachment.svg',
+ noAvaSvg = '/images/wild_card/not_available.svg'
+) => {
const rawImg = (container.preview_img || {}).preview;
switch (rawImg) {
case null:
@@ -11,7 +15,10 @@ const previewContainerImage = (container, noAttSvg = '/images/wild_card/no_attac
}
};
-const previewAttachmentImage = (attachment, noAvaSvg = '/images/wild_card/not_available.svg') => {
+const previewAttachmentImage = (
+ attachment,
+ noAvaSvg = '/images/wild_card/not_available.svg'
+) => {
if (attachment.thumb) {
return `/images/thumbnail/${attachment.identifier}`;
}
diff --git a/app/packs/src/utilities/quillToolbarSymbol.js b/app/packs/src/utilities/quillToolbarSymbol.js
index 432e6f87ed..9d1de5a5ad 100644
--- a/app/packs/src/utilities/quillToolbarSymbol.js
+++ b/app/packs/src/utilities/quillToolbarSymbol.js
@@ -1,6 +1,6 @@
import React from 'react';
-const minusRender = name => (
+const minusRender = (name) => (
@@ -232,6 +232,13 @@ const ops13CHead = (freqStr = '', solvent = '') => (
]
);
+const ops15NHead = (freqStr = '', solvent = '') => (
+ [
+ { attributes: { script: 'super' }, insert: '15' },
+ { insert: `N NMR (${freqStr}${solvent}ppm) δ = ` },
+ ]
+);
+
const ops19FHead = (freqStr = '', solvent = '') => (
[
{ attributes: { script: 'super' }, insert: '19' },
@@ -239,6 +246,20 @@ const ops19FHead = (freqStr = '', solvent = '') => (
]
);
+const ops29SiHead = (freqStr = '', solvent = '') => (
+ [
+ { attributes: { script: 'super' }, insert: '29' },
+ { insert: `Si NMR (${freqStr}${solvent}ppm) δ = ` },
+ ]
+);
+
+const ops31PHead = (freqStr = '', solvent = '') => (
+ [
+ { attributes: { script: 'super' }, insert: '31' },
+ { insert: `P NMR (${freqStr}${solvent}ppm) δ = ` },
+ ]
+);
+
const opsCommonTail = () => (
[
{ insert: '. ' },
@@ -347,16 +368,45 @@ const opsMSTail = () => (
[]
);
+const opsDLSIntensityHead = () => (
+ [
+ { insert: 'DLS: ' },
+ ]
+);
+
+const opsEmmissionHead = () => (
+ [
+ { insert: 'Emission: ' },
+ ]
+);
+
+const opsXRDHead = () => (
+ [
+ { insert: 'XRD ' },
+ ]
+);
+
+const opsCommonHead = () => (
+ []
+);
+
const SpectraOps = {
PLAIN: { head: [], tail: [] },
'1H': { head: ops1HHead, tail: opsCommonTail },
'13C': { head: ops13CHead, tail: opsCommonTail },
+ '15N': { head: ops15NHead, tail: opsCommonTail },
'19F': { head: ops19FHead, tail: opsCommonTail },
+ '29Si': { head: ops29SiHead, tail: opsCommonTail },
+ '31P': { head: ops31PHead, tail: opsCommonTail },
IR: { head: opsIRHead, tail: opsIRTail },
RAMAN: { head: opsRAMANHead, tail: opsRAMANTail },
'UV/VIS': { head: opsUVVISHead, tail: opsUVVISTail },
'HPLC UV/VIS': { head: opsHPLCUVVISHead, tail: opsHPLCUVVISTail },
MS: { head: opsMSHead, tail: opsMSTail },
+ Emissions: { head: opsEmmissionHead, tail: opsCommonTail },
+ 'DLS ACF': { head: opsCommonHead, tail: opsCommonTail },
+ 'DLS intensity': { head: opsDLSIntensityHead, tail: opsCommonTail },
+ 'X-RAY DIFFRACTION': { head: opsXRDHead, tail: opsCommonHead }
};
const reactionAnalysesMacros = {
diff --git a/app/packs/src/utilities/routesUtils.js b/app/packs/src/utilities/routesUtils.js
index 5e39d5b57b..11e0573cb5 100644
--- a/app/packs/src/utilities/routesUtils.js
+++ b/app/packs/src/utilities/routesUtils.js
@@ -5,7 +5,8 @@ import UserActions from 'src/stores/alt/actions/UserActions';
import ElementActions from 'src/stores/alt/actions/ElementActions';
import ElementStore from 'src/stores/alt/stores/ElementStore';
import UserStore from 'src/stores/alt/stores/UserStore';
-import DetailActions from 'src/stores/alt/actions/DetailActions'
+import DetailActions from 'src/stores/alt/actions/DetailActions';
+import { elementNames } from 'src/apps/generic/Utils';
const collectionShow = (e) => {
UIActions.showElements.defer();
@@ -16,6 +17,7 @@ const collectionShow = (e) => {
}
const uiState = UIStore.getState();
const currentSearchSelection = uiState.currentSearchSelection;
+ const currentSearchByID = uiState.currentSearchByID;
const collectionId = e.params['collectionID'];
let collectionPromise = null;
if (collectionId === 'all') {
@@ -34,6 +36,9 @@ const collectionShow = (e) => {
collectionId: collection.id,
isSync: !!collection.is_sync_to_me });
} else {
+ if (currentSearchByID) {
+ UIActions.clearSearchById();
+ }
UIActions.selectCollection(collection);
}
@@ -43,6 +48,7 @@ const collectionShow = (e) => {
UIActions.uncheckAllElements({ type: 'reaction', range: 'all' });
UIActions.uncheckAllElements({ type: 'wellplate', range: 'all' });
UIActions.uncheckAllElements({ type: 'screen', range: 'all' });
+ elementNames(false).forEach((klass) => { UIActions.uncheckAllElements({ type: klass, range: 'all' }); });
// }
});
};
@@ -60,6 +66,7 @@ const scollectionShow = (e) => {
}
const uiState = UIStore.getState();
const currentSearchSelection = uiState.currentSearchSelection;
+ const currentSearchByID = uiState.currentSearchByID;
const collectionId = e.params['collectionID'];
let collectionPromise = null;
collectionPromise = CollectionStore.findBySId(collectionId);
@@ -75,6 +82,9 @@ const scollectionShow = (e) => {
isSync: !!collection.is_sync_to_me });
} else {
UIActions.selectSyncCollection(collection);
+ if (currentSearchByID) {
+ UIActions.clearSearchById();
+ }
}
// if (!e.params['sampleID'] && !e.params['reactionID'] && !e.params['wellplateID'] && !e.params['screenID']) {
@@ -82,6 +92,8 @@ const scollectionShow = (e) => {
UIActions.uncheckAllElements({ type: 'reaction', range: 'all' });
UIActions.uncheckAllElements({ type: 'wellplate', range: 'all' });
UIActions.uncheckAllElements({ type: 'screen', range: 'all' });
+ elementNames(false).forEach((klass) => { UIActions.uncheckAllElements({ type: klass, range: 'all' }); });
+
// }
});
};
@@ -96,25 +108,45 @@ const predictionShowFwdRxn = () => {
const sampleShowOrNew = (e) => {
const { sampleID, collectionID } = e.params;
+ const { selecteds, activeKey } = ElementStore.getState();
+ const index = selecteds.findIndex((el) => el.type === 'sample' && el.id === sampleID);
+
if (sampleID === 'new') {
ElementActions.generateEmptySample(collectionID);
} else if (sampleID === 'copy') {
ElementActions.copySampleFromClipboard.defer(collectionID);
- } else {
+ } else if (index < 0) {
ElementActions.fetchSampleById(sampleID);
+ } else if (index !== activeKey) {
+ DetailActions.select(index);
}
// UIActions.selectTab(1);
};
+const cellLineShowOrNew = (e) => {
+ if(e.params.new_cellLine||(e.params.new_cellLine===undefined&&e.params.cell_lineID==="new")){
+ ElementActions.generateEmptyCellLine(e.params.collectionID,e.params.cell_line_template);
+ }else{
+ if(e.params.cellLineID){
+ e.params.cellLineId=e.params.cellLineID
+ }
+ ElementActions.tryFetchCellLineElById.defer(e.params.cellLineId);
+ }
+}
+
const reactionShow = (e) => {
const { reactionID, collectionID } = e.params;
+ const { selecteds, activeKey } = ElementStore.getState();
+ const index = selecteds.findIndex((el) => el.type === 'reaction' && el.id === reactionID);
// UIActions.selectTab(2);
- if (reactionID !== 'new' && reactionID !== 'copy') {
- ElementActions.fetchReactionById(reactionID);
+ if (reactionID === 'new') {
+ ElementActions.generateEmptyReaction(collectionID);
} else if (reactionID === 'copy') {
//ElementActions.copyReactionFromClipboard(collectionID);
- } else {
- ElementActions.generateEmptyReaction(collectionID);
+ } else if (index < 0) {
+ ElementActions.fetchReactionById(reactionID);
+ } else if (index !== activeKey) {
+ DetailActions.select(index);
}
};
@@ -125,13 +157,17 @@ const reactionShowSample = (e) => {
const wellplateShowOrNew = (e) => {
const { wellplateID, collectionID } = e.params;
+ const { selecteds, activeKey } = ElementStore.getState();
+ const index = selecteds.findIndex((el) => el.type === 'wellplate' && el.id === wellplateID);
if (wellplateID === 'new') {
ElementActions.generateEmptyWellplate(collectionID);
} else if (wellplateID === 'template') {
ElementActions.generateWellplateFromClipboard.defer(collectionID);
- } else {
+ } else if (index < 0) {
ElementActions.fetchWellplateById(wellplateID);
+ } else if (index !== activeKey) {
+ DetailActions.select(index);
}
};
@@ -142,12 +178,17 @@ const wellplateShowSample = (e) => {
const screenShowOrNew = (e) => {
const { screenID, collectionID } = e.params;
+ const { selecteds, activeKey } = ElementStore.getState();
+ const index = selecteds.findIndex((el) => el.type === 'screen' && el.id === screenID);
+
if (screenID === 'new') {
ElementActions.generateEmptyScreen(collectionID);
} else if (screenID === 'template') {
ElementActions.generateScreenFromClipboard.defer(collectionID);
- } else {
+ } else if (index < 0) {
ElementActions.fetchScreenById(screenID);
+ } else if (index !== activeKey) {
+ DetailActions.select(index);
}
};
@@ -172,10 +213,15 @@ const deviceShowDeviceManagement = () => {
const researchPlanShowOrNew = (e) => {
const { research_planID, collectionID } = e.params;
+ const { selecteds, activeKey } = ElementStore.getState();
+ const index = selecteds.findIndex(el => el.type === 'research_plan' && el.id === research_planID);
+
if (research_planID === 'new') {
ElementActions.generateEmptyResearchPlan(collectionID);
- } else {
+ } else if (index < 0) {
ElementActions.fetchResearchPlanById(research_planID);
+ } else if (index !== activeKey) {
+ DetailActions.select(index);
}
};
@@ -210,6 +256,7 @@ const genericElShowOrNew = (e, type) => {
} else if (genericElID === 'copy') {
//
} else {
+
ElementActions.fetchGenericElById(genericElID, itype);
}
};
@@ -235,6 +282,9 @@ const elementShowOrNew = (e) => {
case 'metadata':
metadataShowOrNew(e);
break;
+ case 'cell_line':
+ cellLineShowOrNew(e);
+ break;
default:
if (e && e.klassType == 'GenericEl') {
genericElShowOrNew(e, type);
@@ -264,5 +314,6 @@ export {
metadataShowOrNew,
elementShowOrNew,
predictionShowFwdRxn,
- genericElShowOrNew
+ genericElShowOrNew,
+ cellLineShowOrNew
};
diff --git a/app/packs/src/utilities/selectHelper.js b/app/packs/src/utilities/selectHelper.js
new file mode 100644
index 0000000000..1db0009e5b
--- /dev/null
+++ b/app/packs/src/utilities/selectHelper.js
@@ -0,0 +1,27 @@
+// Format data for react-select component when using with users data as returned by the API
+// input: { users: [{ id: 1, name: 'John Doe', initials: 'JD', type: 'Person' }, ...]}
+// output: { options: [{ value: 1, label: 'John Doe (JD - Person)' }, ...]}
+
+const buildLabel = (user, withType = false) => (
+ withType ? `${user.name} (${user.initials} - ${user.type})` : `${user.name} (${user.initials})`
+);
+
+const filterCurrentUser = (data, currentUserId = null) => {
+ const { users } = data;
+ if (!currentUserId) { return users || []; }
+ return (users || []).filter((user) => user.id !== currentUserId);
+};
+
+const selectUserOptionFormater = ({ data = {}, withType = false, currentUserId = null }) => {
+ const users = filterCurrentUser(data, currentUserId);
+ const usersEntries = (users).map((user) => ({
+ value: user.id,
+ name: user.name,
+ label: buildLabel(user, withType),
+ }));
+ return { options: usersEntries };
+};
+
+export {
+ selectUserOptionFormater
+};
diff --git a/app/packs/src/utilities/textHelper.js b/app/packs/src/utilities/textHelper.js
new file mode 100644
index 0000000000..990c7d4c66
--- /dev/null
+++ b/app/packs/src/utilities/textHelper.js
@@ -0,0 +1,8 @@
+// replace _ with space and capitalize first letter of each word
+const capitalizeWords = (string) => (string || '')
+ .replace(/_+/, ' ')
+ .replace(/\s+/g, ' ')
+ .trim()
+ .replace(/\b\w/g, (m) => m.toUpperCase());
+
+export default capitalizeWords;
diff --git a/app/packs/src/utilities/timezoneHelper.js b/app/packs/src/utilities/timezoneHelper.js
new file mode 100644
index 0000000000..e05829c3cb
--- /dev/null
+++ b/app/packs/src/utilities/timezoneHelper.js
@@ -0,0 +1,42 @@
+import moment from 'moment';
+
+// see config/locale/en.yml for the format
+const elnTimestampFormat = 'DD.MM.YYYY, HH:mm:ss Z';
+
+const regExpTimestamp = /^\d{2}\.\d{2}\.\d{4}, \d{2}:\d{2}:\d{2}/;
+
+const parseDate = (dateString) => {
+ if (regExpTimestamp.test(dateString)) {
+ const date = moment(dateString, elnTimestampFormat);
+ if (date.isValid()) {
+ return date;
+ }
+ }
+ // assume ISO 8601 format
+ return moment(dateString);
+};
+
+const formatDate = (dateString) => {
+ const date = parseDate(dateString);
+
+ const localDate = date.local();
+
+ const formattedDate = localDate.format('llll');
+
+ return formattedDate;
+};
+
+// return `Created at: ${formattedCreatedAt} | Updated at: ${formattedUpdatedAt}`;
+const formatTimeStampsOfElement = (element) => {
+ const { created_at, updated_at } = element;
+ const formattedCreatedAt = formatDate(created_at);
+ const formattedUpdatedAt = formatDate(updated_at);
+ return `Created ${formattedCreatedAt} - Updated ${formattedUpdatedAt}`;
+};
+
+export {
+ elnTimestampFormat,
+ parseDate,
+ formatDate,
+ formatTimeStampsOfElement,
+};
diff --git a/app/policies/element_policy.rb b/app/policies/element_policy.rb
index cac558408c..d97791d051 100644
--- a/app/policies/element_policy.rb
+++ b/app/policies/element_policy.rb
@@ -60,7 +60,7 @@ def maximum_permission_level(collections,sync_collections=SyncCollectionsUser.no
end
def maximum_element_permission_level(sync_collections = SyncCollectionsUser.none)
- sync_collections.pluck("#{@record.class.name.downcase}_detail_level").max || -1
+ sync_collections.pluck("#{Labimotion::Utils.element_name_dc(@record.class.to_s)}_detail_level").max || -1
end
def user_ids
diff --git a/app/proxies/element_permission_proxy.rb b/app/proxies/element_permission_proxy.rb
index 0660e928dc..5ce84b7a09 100644
--- a/app/proxies/element_permission_proxy.rb
+++ b/app/proxies/element_permission_proxy.rb
@@ -1,3 +1,6 @@
+# frozen_string_literal: true
+
+# rubocop: disable Metrics/CyclomaticComplexity, Lint/DuplicateBranch
class ElementPermissionProxy
attr_reader :user, :element, :detail_level
@@ -36,13 +39,13 @@ def detail_level_for_element
# Fall 2: User besitzt mindestens einen Share, der das Element enthält...von diesen Shares nutzt man das maximale
# Element Detaillevel
- c.map { |cc| [cc.is_shared, cc.send("#{element.class.to_s.downcase}_detail_level")] }.each do |bool, dl|
+ c.map { |cc| [cc.is_shared, cc.send("#{Labimotion::Utils.element_name_dc(element.class.to_s)}_detail_level")] }.each do |bool, dl|
return (@dl = max_detail_level) if !bool
@dl = dl if dl > @dl
end
sc.each do |sc|
- dl = sc.send("#{element.class.to_s.downcase}_detail_level")
+ dl = sc.send("#{Labimotion::Utils.element_name_dc(element.class.to_s)}_detail_level")
@dl = dl if dl > @dl
end
@@ -84,16 +87,19 @@ def max_detail_level_by_element_class
10
when ResearchPlan
10
- when Element
+ when Labimotion::Element
+ 10
+ when CelllineSample
10
end
end
def user_collections_for_element
- # collection_ids = element.collections.pluck(:id)
- # Collection.where("id IN (?) AND user_id IN (?)", collection_ids, @user_ids)
+ # collection_ids = element.collections.pluck(:id)
+ # Collection.where("id IN (?) AND user_id IN (?)", collection_ids, @user_ids)
element.collections.select { |c| @user_ids.include?(c.user_id) }
end
+
def sync_collections_users_for_element
coll_ids = element.collections.map(&:id)
element.collections.map(&:sync_collections_users).flatten.select do |sc|
@@ -101,3 +107,4 @@ def sync_collections_users_for_element
end
end
end
+# rubocop: enable Metrics/CyclomaticComplexity, Lint/DuplicateBranch
diff --git a/app/services/element_detail_level_calculator.rb b/app/services/element_detail_level_calculator.rb
index 35857162bc..304f005f34 100644
--- a/app/services/element_detail_level_calculator.rb
+++ b/app/services/element_detail_level_calculator.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# rubocop: disable Metrics/CyclomaticComplexity
class ElementDetailLevelCalculator
attr_reader :user, :element, :detail_levels
@@ -10,6 +11,7 @@ class ElementDetailLevelCalculator
reaction_detail_level
wellplate_detail_level
screen_detail_level
+ celllinesample_detail_level
].freeze
def initialize(user:, element:)
@@ -20,16 +22,17 @@ def initialize(user:, element:)
private
- def calculate_detail_levels
+ def calculate_detail_levels # rubocop:disable Metrics/AbcSize
detail_levels = Hash.new(0)
all_collections_detail_levels = user_collection_detail_levels + sync_collection_detail_levels
- detail_levels[Element] = all_collections_detail_levels.pluck(:element_detail_level).max || 0
+ detail_levels[Labimotion::Element] = all_collections_detail_levels.pluck(:element_detail_level).max || 0
detail_levels[Reaction] = all_collections_detail_levels.pluck(:reaction_detail_level).max || 0
detail_levels[ResearchPlan] = all_collections_detail_levels.pluck(:researchplan_detail_level).max || 0
detail_levels[Sample] = all_collections_detail_levels.pluck(:sample_detail_level).max || 0
detail_levels[Screen] = all_collections_detail_levels.pluck(:screen_detail_level).max || 0
detail_levels[Wellplate] = all_collections_detail_levels.pluck(:wellplate_detail_level).max || 0
+ detail_levels[CelllineSample] = all_collections_detail_levels.pluck(:celllinesample_detail_level).max || 0
detail_levels[Well] = detail_levels[Wellplate]
detail_levels
@@ -70,3 +73,4 @@ def sync_collection_detail_levels
.map { |values| Hash[DETAIL_LEVEL_FIELDS.zip(values)] }
end
end
+# rubocop: enable Metrics/CyclomaticComplexity
\ No newline at end of file
diff --git a/app/services/inbox_service.rb b/app/services/inbox_service.rb
index ae7b9a2f65..13310c9efd 100644
--- a/app/services/inbox_service.rb
+++ b/app/services/inbox_service.rb
@@ -5,21 +5,36 @@ def initialize(container)
@container = container
end
- def to_hash(device_boxes)
- {
- inbox: {
- children: device_boxes,
- count: @container.children.size,
- container_type: @container.container_type,
- unlinked_attachments: Attachment.where(
- attachable_type: 'Container',
- attachable_id: nil,
- created_for: @container&.containable&.id,
- ),
- inbox_count: Container.where(id: @container.descendant_ids)
- .joins(children: :attachments)
- .count('attachments.id'),
- },
- }
+ def to_hash(device_boxes, sort_params, full_response = true)
+ if full_response
+ {
+ inbox: {
+ children: device_boxes,
+ count: @container.children.size,
+ container_type: @container.container_type,
+ unlinked_attachments: Attachment.where(
+ attachable_type: 'Container',
+ attachable_id: nil,
+ created_for: @container&.containable&.id,
+ ).order("#{sort_params[:sort_column]} #{sort_params[:sort_direction]}"),
+ inbox_count: Container.where(id: @container.descendant_ids)
+ .joins(children: :attachments)
+ .count('attachments.id'),
+ },
+ }
+ else
+ {
+ inbox: {
+ unlinked_attachments: Attachment.where(
+ attachable_type: 'Container',
+ attachable_id: nil,
+ created_for: @container&.containable&.id,
+ ).order("#{sort_params[:sort_column]} #{sort_params[:sort_direction]}"),
+ inbox_count: Container.where(id: @container.descendant_ids)
+ .joins(children: :attachments)
+ .count('attachments.id'),
+ },
+ }
+ end
end
end
diff --git a/app/usecases/calendar_entries/index.rb b/app/usecases/calendar_entries/index.rb
index 4f38e7e2b1..991b5da358 100644
--- a/app/usecases/calendar_entries/index.rb
+++ b/app/usecases/calendar_entries/index.rb
@@ -51,7 +51,7 @@ def shared_entries(entries)
eventable: [
Sample.joins(:collections).where(collections: { id: collection_ids }),
Reaction.joins(:collections).where(collections: { id: collection_ids }),
- Element.joins(:collections).where(collections: { id: collection_ids }),
+ Labimotion::Element.joins(:collections).where(collections: { id: collection_ids }),
Wellplate.joins(:collections).where(collections: { id: collection_ids }),
ResearchPlan.joins(:collections).where(collections: { id: collection_ids }),
Screen.joins(:collections).where(collections: { id: collection_ids }),
@@ -67,7 +67,7 @@ def elements
entry_ids_grouped_by_type.each do |type, ids|
next if type.nil?
- elements[type] = if type == 'Element'
+ elements[type] = if type == 'Labimotion::Element'
type.constantize.where(id: ids).includes(:element_klass, :collections).index_by(&:id)
else
type.constantize.where(id: ids).includes(:collections).index_by(&:id)
@@ -92,7 +92,7 @@ def calendar_entries_with_preloaded_elements
element = elements.dig(entry.eventable_type, entry.eventable_id)
entry.instance_variable_set(:@element, element)
- entry.instance_variable_set(:@element_klass, element&.element_klass) if entry.eventable_type == 'Element'
+ entry.instance_variable_set(:@element_klass, element&.element_klass) if entry.eventable_type == 'Labimotion::Element'
entry.instance_variable_set(:@accessible, (collection_ids & (element&.collection_ids || [])).any?)
entry.instance_variable_set(:@notified_users, entry.notified_users)
end
diff --git a/app/usecases/cell_lines/create.rb b/app/usecases/cell_lines/create.rb
new file mode 100644
index 0000000000..36f586ac9f
--- /dev/null
+++ b/app/usecases/cell_lines/create.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Usecases
+ module CellLines
+ class Create
+ def initialize(params, current_user)
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute!
+ check_parameter
+ cell_line_material = find_cellline_material || create_cellline_material
+ cell_line_sample = create_cellline_sample(cell_line_material)
+
+ CollectionsCellline.create(
+ collection: Collection.find(@params[:collection_id]),
+ cellline_sample_id: cell_line_sample.id,
+ )
+ CollectionsCellline.create(
+ collection: all_collection_of_current_user,
+ cellline_sample_id: cell_line_sample.id,
+ )
+
+ @current_user.increment_counter('celllines') # rubocop: disable Rails/SkipsModelValidations
+ cell_line_sample
+ end
+
+ def find_cellline_material
+ CelllineMaterial.find_by(
+ name: @params[:material_names],
+ source: @params[:source],
+ )
+ end
+
+ def create_cellline_material
+ CelllineMaterial.create(
+ name: @params[:material_names],
+ cell_type: @params[:cell_type],
+ organism: @params[:organism],
+ tissue: @params[:tissue],
+ mutation: @params[:mutation],
+ source: @params[:source],
+ disease: @params[:disease],
+ growth_medium: @params[:growth_medium],
+ biosafety_level: @params[:biosafety_level],
+ variant: @params[:variant],
+ optimal_growth_temp: @params[:optimal_growth_temp],
+ cryo_pres_medium: @params[:cryo_pres_medium],
+ gender: @params[:gender],
+ description: @params[:material_description],
+ )
+ end
+
+ def create_cellline_sample(material)
+ CelllineSample.create(
+ cellline_material: material,
+ creator: @current_user,
+ amount: @params[:amount],
+ unit: @params[:unit],
+ passage: @params[:passage],
+ contamination: @params[:contamination],
+ name: @params[:name],
+ description: @params[:description],
+ short_label: @params[:short_label],
+ )
+ end
+
+ def check_parameter
+ raise 'amount not valid' unless check_scalar_value(@params[:amount])
+ raise 'passage not valid' unless check_scalar_value(@params[:passage])
+ raise 'material name not valid' unless check_string_value(@params[:material_names])
+ raise 'source not valid' unless check_string_value(@params[:source])
+ raise 'unit not valid' unless check_string_value(@params[:unit])
+ end
+
+ def check_scalar_value(value)
+ value.instance_of?(Integer) && value >= 0
+ end
+
+ def check_string_value(value)
+ value.instance_of?(String) && !value.empty?
+ end
+
+ def all_collection_of_current_user
+ Collection.get_all_collection_for_user(@current_user.id)
+ end
+ end
+ end
+end
diff --git a/app/usecases/cell_lines/load.rb b/app/usecases/cell_lines/load.rb
new file mode 100644
index 0000000000..08d240cefe
--- /dev/null
+++ b/app/usecases/cell_lines/load.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Usecases
+ module CellLines
+ class Load
+ def initialize(id, current_user)
+ @current_user = current_user
+ @id = id
+ end
+
+ def execute!
+ raise 'user is not valid' unless @current_user
+ raise 'id not valid' unless @id.is_a?(Numeric) && @id.positive?
+
+ cell_line_sample = @current_user.cellline_samples.find_by(id: @id)
+
+ cell_line_sample = fetch_cell_lines_from_shared_sync if cell_line_sample.nil?
+
+ raise 'user has no access to object' unless cell_line_sample
+
+ cell_line_sample
+ end
+
+ def fetch_cell_lines_from_shared_sync
+ shared_or_synced_celllines = @current_user.shared_collections.map do |col|
+ col.cellline_samples.find_by(id: @id)
+ end
+ shared_or_synced_celllines.first
+ end
+ end
+ end
+end
diff --git a/app/usecases/cell_lines/update.rb b/app/usecases/cell_lines/update.rb
new file mode 100644
index 0000000000..c62ffce3fe
--- /dev/null
+++ b/app/usecases/cell_lines/update.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+module Usecases
+ module CellLines
+ class Update
+ def initialize(params, current_user)
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute!
+ check_parameter
+ @cell_line_sample = @current_user.cellline_samples.find_by(id: @params[:cell_line_sample_id])
+ @cell_line_sample ||= fetch_cell_lines_from_shared_sync
+ raise 'no cell line sample found ' unless @cell_line_sample
+
+ @cell_line_sample.cellline_material = find_material || create_new_material
+ update_sample_properties
+ update_material_properties(@cell_line_sample.cellline_material)
+ @cell_line_sample.save
+ @cell_line_sample
+ end
+
+ def find_material
+ CelllineMaterial.find_by(
+ name: @params[:material_names],
+ source: @params[:source],
+ )
+ end
+
+ def fetch_cell_lines_from_shared_sync
+ shared_or_synced_celllines = @current_user.shared_collections.map do |col|
+ sync_collection_user = col.sync_collections_users.find_by(
+ collection_id: col.id,
+ user_id: @current_user.id,
+ )
+ return [] if sync_collection_user.permission_level.zero?
+
+ col.cellline_samples.find_by(id: @params[:cell_line_sample_id])
+ end
+ shared_or_synced_celllines.first
+ end
+
+ def create_new_material
+ CelllineMaterial.create(
+ name: @params[:material_names],
+ growth_medium: @params[:growth_medium],
+ cell_type: @params[:cell_type],
+ organism: @params[:organism],
+ tissue: @params[:tissue],
+ disease: @params[:disease],
+ biosafety_level: @params[:biosafety_level],
+ variant: @params[:variant],
+ mutation: @params[:mutation],
+ optimal_growth_temp: @params[:optimal_growth_temp],
+ cryo_pres_medium: @params[:cryo_pres_medium],
+ gender: @params[:gender],
+ description: @params[:material_description],
+ source: @params[:source],
+ )
+ end
+
+ def update_sample_properties
+ @cell_line_sample.amount = @params[:amount]
+ @cell_line_sample.passage = @params[:passage]
+ @cell_line_sample.contamination = @params[:contamination]
+ @cell_line_sample.name = @params[:name]
+ @cell_line_sample.unit = @params[:unit]
+ @cell_line_sample.description = @params[:description]
+ end
+
+ def update_material_properties(material) # rubocop:disable Metrics/AbcSize
+ material.growth_medium = @params[:growth_medium]
+ material.cell_type = @params[:cell_type]
+ material.organism = @params[:organism]
+ material.tissue = @params[:tissue]
+ material.disease = @params[:disease]
+ material.mutation = @params[:mutation]
+ material.biosafety_level = @params[:biosafety_level]
+ material.variant = @params[:variant]
+ material.optimal_growth_temp = @params[:optimal_growth_temp]
+ material.cryo_pres_medium = @params[:cryo_pres_medium]
+ material.gender = @params[:gender]
+ material.description = @params[:material_description]
+
+ material.save
+ end
+
+ def check_parameter
+ raise 'amount not valid' unless check_scalar_value(@params[:amount])
+ raise 'passage not valid' unless check_scalar_value(@params[:passage])
+ raise 'unit not valid' unless check_string_value(@params[:unit])
+ raise 'source not valid' unless check_string_value(@params[:source])
+ raise 'material name not valid' unless check_names_value(@params[:material_names])
+ end
+
+ def check_scalar_value(value)
+ value.instance_of?(Integer) && value >= 0
+ end
+
+ def check_string_value(value)
+ value.instance_of?(String) && !value.empty?
+ end
+
+ def check_names_value(value)
+ value.instance_of?(String) && !value.empty?
+ end
+ end
+ end
+end
diff --git a/app/usecases/reactions/update_materials.rb b/app/usecases/reactions/update_materials.rb
index 98ba94eb11..7b544d8b11 100644
--- a/app/usecases/reactions/update_materials.rb
+++ b/app/usecases/reactions/update_materials.rb
@@ -96,6 +96,7 @@ def create_sub_sample(sample, fixed_label)
subsample.real_amount_value = sample.real_amount_value
subsample.real_amount_unit = sample.real_amount_unit
subsample.metrics = sample.metrics
+ subsample.dry_solvent = sample.dry_solvent
# add new data container
subsample.container = update_datamodel(sample.container) if sample.container
@@ -152,6 +153,7 @@ def update_existing_sample(sample, fixed_label)
existing_sample.short_label = sample.short_label if sample.short_label
existing_sample.short_label = fixed_label if fixed_label
existing_sample.name = sample.name if sample.name
+ existing_sample.dry_solvent = sample.dry_solvent
if r = existing_sample.residues[0]
r.assign_attributes sample.residues_attributes[0]
diff --git a/app/usecases/sample_tasks/create.rb b/app/usecases/sample_tasks/create.rb
index 5d0228b252..9ffdbdc452 100644
--- a/app/usecases/sample_tasks/create.rb
+++ b/app/usecases/sample_tasks/create.rb
@@ -24,7 +24,7 @@ def perform!
def default_description
description = "Scan Task from #{DateTime.current}"
- description += " for #{sample.showed_name}" if sample
+ description += " for #{sample.showed_name}" if sample && sample.showed_name.present?
description
end
diff --git a/app/usecases/search/advanced_search.rb b/app/usecases/search/advanced_search.rb
new file mode 100644
index 0000000000..e52021fb1d
--- /dev/null
+++ b/app/usecases/search/advanced_search.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+module Usecases
+ module Search
+ class AdvancedSearch
+ require_relative 'shared_methods'
+ attr_reader :collection_id, :params, :conditions, :user
+
+ def initialize(collection_id:, user:, params: {}, conditions: [])
+ @params = params
+ @collection_id = collection_id
+ @conditions = conditions
+ @user = user
+ @shared_methods = SharedMethods.new(params: @params, user: @user)
+
+ @elements = {
+ sample_ids: [],
+ reaction_ids: [],
+ wellplate_ids: [],
+ screen_ids: [],
+ research_plan_ids: [],
+ element_ids: [],
+ }
+ @user_samples = Sample.by_collection_id(@collection_id)
+ @user_reactions = Reaction.by_collection_id(@collection_id)
+ @user_wellplates = Wellplate.by_collection_id(@collection_id)
+ @user_screens = Screen.by_collection_id(@collection_id)
+ @user_research_plans = ResearchPlan.by_collection_id(@collection_id)
+ @user_elements = Labimotion::Element.by_collection_id(@collection_id)
+ end
+
+ def perform!
+ scope = @conditions[:model_name] == Literature ? basic_literature_scope : basic_scope
+ elements_by_scope(scope)
+ @shared_methods.serialization_by_elements_and_page(@elements, @conditions[:error])
+ end
+
+ private
+
+ def basic_scope
+ return '' if @conditions[:error] != ''
+
+ group_by_model_name = %w[ResearchPlan Wellplate].include?(@conditions[:model_name].to_s)
+
+ scope = @conditions[:model_name].by_collection_id(@collection_id.to_i)
+ .where(query_with_condition)
+ .joins(@conditions[:joins].join(' '))
+ scope = @shared_methods.order_by_molecule(scope) if @conditions[:model_name] == Sample
+ scope = scope.group("#{@conditions[:model_name].table_name}.id") if group_by_model_name
+ scope.pluck(:id)
+ end
+
+ def basic_literature_scope
+ return '' if @conditions[:error] != ''
+
+ @conditions[:model_name].where(query_with_condition)
+ .joins(@conditions[:joins].join(' '))
+ .pluck(:id)
+ end
+
+ def query_with_condition
+ filtered_query = @conditions[:query].gsub(/\A\ AND \s*/, '')
+ @conditions[:value].present? ? [filtered_query] + @conditions[:value] : filtered_query
+ end
+
+ def elements_by_scope(scope)
+ return if scope.blank?
+
+ if @conditions[:model_name] == Labimotion::Element
+ @elements[:element_ids] = scope
+ element_relations_element_ids
+ else
+ @elements[:"#{@conditions[:model_name].model_name.singular}_ids"] = scope
+ send(:"#{@conditions[:model_name].to_s.downcase}_relations_element_ids")
+ end
+ end
+
+ # rubocop:disable Metrics/AbcSize
+
+ def sample_relations_element_ids
+ @elements[:reaction_ids] = @user_reactions.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:wellplate_ids] = @user_wellplates.by_sample_ids(@elements[:sample_ids]).uniq.pluck(:id)
+ @elements[:screen_ids] = @user_screens.by_wellplate_ids(@elements[:wellplate_ids]).pluck(:id).uniq
+ @elements[:research_plan_ids] = @user_research_plans.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:element_ids] = @user_elements.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ end
+
+ def reaction_relations_element_ids
+ @elements[:sample_ids] = @user_samples.by_reaction_ids(@elements[:reaction_ids]).pluck(:id).uniq
+ @elements[:wellplate_ids] = @user_wellplates.by_sample_ids(@elements[:sample_ids]).uniq.pluck(:id)
+ @elements[:screen_ids] = @user_screens.by_wellplate_ids(@elements[:wellplate_ids]).pluck(:id).uniq
+ @elements[:research_plan_ids] = @user_research_plans.by_reaction_ids(@elements[:reaction_ids]).pluck(:id).uniq
+ end
+
+ def wellplate_relations_element_ids
+ @elements[:screen_ids] = @user_screens.by_wellplate_ids(@elements[:wellplate_ids]).uniq.pluck(:id)
+ @elements[:sample_ids] = @user_samples.by_wellplate_ids(@elements[:wellplate_ids]).uniq.pluck(:id)
+ @elements[:reaction_ids] = @user_reactions.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:research_plan_ids] = ResearchPlansWellplate.get_research_plans(@elements[:wellplate_ids]).uniq
+ end
+
+ def screen_relations_element_ids
+ @elements[:wellplate_ids] = @user_wellplates.by_screen_ids(@elements[:screen_ids]).uniq.pluck(:id)
+ @elements[:sample_ids] = @user_samples.by_wellplate_ids(@elements[:wellplate_ids]).uniq.pluck(:id)
+
+ return if @elements[:sample_ids].blank?
+
+ @elements[:reaction_ids] = @user_reactions.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:research_plan_ids] = @user_research_plans.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:element_ids] = @user_elements.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ end
+
+ def researchplan_relations_element_ids
+ sample_ids = ResearchPlan.sample_ids_by_research_plan_ids(@elements[:research_plan_ids])
+ reaction_ids = ResearchPlan.reaction_ids_by_research_plan_ids(@elements[:research_plan_ids])
+ @elements[:sample_ids] = sample_ids.map(&:sample_id).uniq
+ @elements[:reaction_ids] = reaction_ids.map(&:reaction_id).uniq
+ @elements[:wellplate_ids] = ResearchPlansWellplate.get_wellplates(@elements[:research_plan_ids]).uniq
+ @elements[:screen_ids] = @user_screens.by_wellplate_ids(@elements[:wellplate_ids]).pluck(:id).uniq
+ @elements[:element_ids] = @user_elements.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ end
+
+ def literature_relations_element_ids
+ @elements[:sample_ids] = @user_samples.by_literature_ids(@elements[:literature_ids]).pluck(:id).uniq
+ @elements[:reaction_ids] = @user_reactions.by_literature_ids(@elements[:literature_ids]).uniq.pluck(:id)
+ @elements[:research_plan_ids] =
+ @user_research_plans.by_literature_ids(@elements[:literature_ids]).pluck(:id).uniq
+ end
+
+ def element_relations_element_ids
+ sample_ids = Labimotion::ElementsSample.where(element_id: @elements[:element_ids]).pluck(:sample_id)
+ @elements[:sample_ids] = @user_samples.where(id: sample_ids).uniq.pluck(:id)
+ end
+ # rubocop:enable Metrics/AbcSize
+ end
+ end
+end
diff --git a/app/usecases/search/by_ids.rb b/app/usecases/search/by_ids.rb
new file mode 100644
index 0000000000..6d7dd6344e
--- /dev/null
+++ b/app/usecases/search/by_ids.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+module Usecases
+ module Search
+ class ByIds
+ require_relative 'shared_methods'
+ attr_reader :collection_id, :params, :user
+
+ def initialize(collection_id:, user:, params: {})
+ @params = params
+ @filter_params = @params[:selection][:list_filter_params]
+ @id_params = @params[:selection][:id_params]
+ @collection_id = collection_id
+ @user = user
+ @shared_methods = SharedMethods.new(params: @params, user: @user)
+
+ @model_name = model_name(@id_params)
+ if @filter_params
+ @from = @filter_params[:from_date]
+ @to = @filter_params[:to_date]
+ @by_created_at = @filter_params[:filter_created_at] || false
+ end
+ @total_elements = @id_params[:total_elements]
+ @result = {}
+ end
+
+ def perform!
+ scope = basic_scope
+ scope = search_filter_scope(scope)
+ serialize_result_by_ids(scope)
+ end
+
+ private
+
+ def model_name(id_params)
+ id_params[:model_name] == 'element' ? Labimotion::Element : id_params[:model_name].camelize.constantize
+ end
+
+ def basic_scope
+ if @model_name == Sample
+ search_by_ids_for_sample(ids_by_params)
+ else
+ search_by_ids(ids_by_params)
+ end
+ end
+
+ def search_by_ids_for_sample(ids)
+ scope =
+ @model_name.includes_for_list_display
+ .by_collection_id(@collection_id.to_i)
+ .where(id: ids)
+ scope = scope.product_only if @filter_params.present? && @filter_params[:product_only]
+ order_by_samples_filter(scope, ids)
+ end
+
+ def order_by_samples_filter(scope, ids)
+ scope =
+ if @params[:molecule_sort]
+ @shared_methods.order_by_molecule(scope)
+ else
+ scope.order('samples.updated_at ASC')
+ end
+ scope = scope.page(@params[:page]).per(@params[:page_size]) if ids.size > @params[:page_size].to_i
+ scope
+ end
+
+ def search_by_ids(ids)
+ scope =
+ @model_name.by_collection_id(@collection_id.to_i)
+ .where(id: ids)
+ scope = scope.page(@params[:page]).per(@params[:page_size]) if ids.size > @params[:page_size].to_i
+ scope
+ end
+
+ def ids_by_params
+ return @id_params[:ids] if !@id_params[:with_filter] || @filter_params.present? || @params[:molecule_sort]
+
+ start_number =
+ if @params[:page].to_i > @shared_methods.pages(@id_params[:total_elements], @params[:per_page].to_i)
+ 0
+ else
+ @params[:page_size].to_i * (@params[:page].to_i - 1)
+ end
+ @id_params[:ids][start_number, start_number + @params[:page_size].to_i]
+ end
+
+ def search_filter_scope(scope)
+ return scope if @filter_params.blank? && !@from && !@to
+
+ timezone = @from ? Time.zone.at(@from.to_time) : Time.zone.at(@to.to_time) + 1.day
+ created_or_updated_at = @by_created_at ? 'created_at' : 'updated_at'
+ scope = scope.where("#{@id_params[:model_name].pluralize}.#{created_or_updated_at} >= ?", timezone)
+ @total_elements = scope.size
+
+ scope
+ end
+
+ def serialize_result_by_ids(scope)
+ pages = @shared_methods.pages(@total_elements, @params[:page_size].to_i)
+ page = @params[:page] > pages ? 1 : @params[:page]
+ scope = scope.page(page).per(@params[:page_size]) if page != @params[:page] || @filter_params.present?
+ serialized_scope = serialized_scope_for_result_by_id(scope)
+
+ @result[@id_params[:model_name].pluralize] = {
+ elements: serialized_scope,
+ ids: @id_params[:ids],
+ page: page,
+ perPage: @params[:page_size],
+ pages: pages,
+ totalElements: @total_elements,
+ }
+ @result
+ end
+
+ def serialized_scope_for_result_by_id(scope)
+ serialized_scope = []
+ scope.map do |s|
+ serialized_scope =
+ if @model_name == Sample
+ serialized_result_by_id_for_sample(s, serialized_scope)
+ else
+ serialized_result_by_id(s, serialized_scope)
+ end
+ end
+ serialized_scope.sort_by! { |object| @id_params['ids'].index object[:id] }
+ end
+
+ def serialized_result_by_id_for_sample(sample, serialized_scope)
+ detail_levels = ElementDetailLevelCalculator.new(user: @user, element: sample).detail_levels
+ serialized = Entities::SampleEntity.represent(
+ sample,
+ detail_levels: detail_levels,
+ displayed_in_list: true,
+ ).serializable_hash
+ serialized_scope.push(serialized)
+ end
+
+ def serialized_result_by_id(element, serialized_scope)
+ entities =
+ @model_name == Labimotion::Element ? Labimotion::ElementEntity : "Entities::#{@model_name}Entity".constantize
+ serialized =
+ entities.represent(element, displayed_in_list: true).serializable_hash
+ serialized_scope.push(serialized)
+ end
+ end
+ end
+end
diff --git a/app/usecases/search/conditions_for_advanced_search.rb b/app/usecases/search/conditions_for_advanced_search.rb
new file mode 100644
index 0000000000..669699782a
--- /dev/null
+++ b/app/usecases/search/conditions_for_advanced_search.rb
@@ -0,0 +1,360 @@
+# frozen_string_literal: true
+
+# rubocop:disable Metrics/ClassLength
+
+module Usecases
+ module Search
+ class ConditionsForAdvancedSearch
+ attr_reader :params, :detail_levels
+
+ def initialize(detail_levels: {}, params: {})
+ @params = params
+ @detail_levels = detail_levels
+
+ @table = ''
+ @field_table = ''
+ @match = ''
+ @conditions = {
+ joins: [], field: '', condition_table: '', first_condition: '',
+ additional_condition: '', words: '', model_name: '', value: [],
+ query: '', error: ''
+ }
+ @table_or_tab_types = {
+ generics: false, chemicals: false, analyses: false, measurements: false, literatures: false
+ }
+ end
+
+ def filter!
+ @params.each_with_index do |filter, i|
+ @conditions[:error] = "Your search for #{filter['field']['column']} is not allowed"
+ next unless table_or_detail_level_is_not_allowed(filter)
+
+ @conditions[:error] = ''
+ basic_conditions_by_filter(filter)
+ table_or_tab_types
+ special_and_generic_conditions_by_filter(filter, i)
+
+ @conditions[:query] = "#{@conditions[:query]} #{filter['link']} (#{conditions}) "
+ @conditions[:value] += @conditions[:words] if @conditions[:field].present?
+ end
+ @conditions
+ end
+
+ private
+
+ def basic_conditions_by_filter(filter)
+ @table = filter['table']
+ @field_table = filter['field']['table']
+ @conditions[:model_name] = model_name(@table)
+ @match = filter['value'] == 'true' ? '=' : filter['match']
+ @conditions[:condition_table] = "#{@table}."
+ @conditions[:first_condition] = ''
+ @conditions[:additional_condition] = ''
+ @conditions[:field] = filter['field']['column']
+ @conditions[:words] = sanitize_words(filter)
+
+ return unless @table == 'elements' && filter['element_id'] != 0
+
+ @conditions[:additional_condition] = "AND element_klass_id = #{filter['element_id']}"
+ end
+
+ def model_name(table)
+ table == 'elements' ? Labimotion::Element : table.singularize.camelize.constantize
+ end
+
+ def special_and_generic_conditions_by_filter(filter, number)
+ if @table_or_tab_types[:generics]
+ generic_field_options(filter, number)
+ elsif @table_or_tab_types[:chemicals]
+ chemicals_tab_options(filter)
+ elsif @table_or_tab_types[:analyses]
+ analyses_tab_options(filter)
+ elsif @table_or_tab_types[:measurements]
+ measurements_tab_options(filter)
+ elsif @table_or_tab_types[:literatures]
+ literatures_tab_options(filter)
+ else
+ special_non_generic_field_options(filter)
+ end
+ end
+
+ # rubocop:disable Metrics/CyclomaticComplexity
+ def table_or_tab_types
+ @table_or_tab_types[:generics] = (@field_table.present? && @field_table == 'segments') ||
+ (@table == 'elements' && %w[name short_label].exclude?(@conditions[:field]))
+ @table_or_tab_types[:chemicals] = @field_table.present? && @field_table == 'chemicals'
+ @table_or_tab_types[:analyses] = @field_table.present? && @field_table == 'containers'
+ @table_or_tab_types[:measurements] = @field_table.present? && @field_table == 'measurements'
+ @table_or_tab_types[:literatures] = @table.present? && @table == 'literatures'
+ end
+ # rubocop:enable Metrics/CyclomaticComplexity
+
+ def conditions
+ condition =
+ if @conditions[:field].blank?
+ "#{@conditions[:first_condition]}#{@conditions[:additional_condition]}"
+ else
+ "#{@conditions[:first_condition]}#{@conditions[:condition_table]}#{@conditions[:field]} #{@match} ?
+ #{@conditions[:additional_condition]}"
+ end
+
+ @conditions[:words] = [@conditions[:words].join("\n")] if @conditions[:words].size > 1 && @match == '='
+
+ @conditions[:words].collect { condition }.join(' OR ')
+ end
+
+ def table_or_detail_level_is_not_allowed(filter)
+ filter['field']['table'] = filter['field']['table'] || filter['table']
+ filter['field']['column'] = filter['field']['column'] || filter['field']['field']
+ adv_field = filter['field'].to_h.merge(@detail_levels).symbolize_keys
+ whitelisted_table(**adv_field) && filter_with_detail_level(**adv_field)
+ end
+
+ def whitelisted_table(table:, column:, **_)
+ tables = %w[elements segments chemicals containers measurements molecules literals literatures]
+ return true if tables.include?(table)
+
+ API::WL_TABLES.key?(table) && API::WL_TABLES[table].include?(column)
+ end
+
+ # desc: return true if the detail level allow to access the column
+ def filter_with_detail_level(table:, column:, sample_detail_level:, reaction_detail_level:, **_)
+ # TODO: filter according to columns
+
+ return true unless table.in?(%w[samples reactions])
+ return true if table == 'samples' && (sample_detail_level.positive? || column == 'external_label')
+ return true if table == 'reactions' && reaction_detail_level > -1
+
+ false
+ end
+
+ def duration_interval_by_unit(unit)
+ case unit
+ when 'Minute(s)' then 60
+ when 'Second(s)' then 1
+ when 'Week(s)' then 604_800
+ when 'Day(s)' then 86_400
+ else
+ 3600
+ end
+ end
+
+ def sanitize_float_fields(filter)
+ fields = %w[
+ boiling_point melting_point density molarity_value target_amount_value purity
+ temperature duration molecular_mass
+ ]
+ fields.include?(filter['field']['column']) && filter['field']['table'] != 'segments'
+ end
+
+ def sanitize_words(filter)
+ return [filter['value']] if filter['value'] == 'true'
+ return [filter['smiles']] if filter['field']['column'] == 'solvent'
+ return [filter['value'].to_f] if sanitize_float_fields(filter)
+
+ no_sanitizing_matches = ['=', '>=']
+ sanitize = no_sanitizing_matches.exclude?(filter['match'])
+ words = filter['value'].split(/(\r)?\n/).map!(&:strip)
+ words = words.map { |e| "%#{ActiveRecord::Base.send(:sanitize_sql_like, e)}%" } if sanitize
+ words
+ end
+
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
+
+ def special_non_generic_field_options(filter)
+ case filter['field']['column']
+ when 'body'
+ prop = "element_#{filter['field']['opt']}"
+ key = filter['field']['opt']
+ element_join = "CROSS JOIN jsonb_array_elements(body) AS #{prop}"
+ if @conditions[:joins].exclude?(element_join)
+ @conditions[:joins] << element_join
+ @conditions[:joins] << "CROSS JOIN jsonb_array_elements(#{prop} -> 'value' -> '#{key}') AS #{key}"
+ end
+ if filter['field']['opt'] == 'rows'
+ @conditions[:field] = 'rows::TEXT'
+ @conditions[:additional_condition] = "AND (#{prop} ->> 'type')::TEXT = 'table'"
+ else
+ @conditions[:field] = "(regexp_replace(#{key} ->> 'insert', '\r|\n', '', 'g'))::TEXT"
+ end
+ @conditions[:condition_table] = ''
+ when 'content'
+ @conditions[:joins] <<
+ "INNER JOIN private_notes ON private_notes.noteable_type = '#{@conditions[:model_name]}'
+ AND private_notes.noteable_id = #{@table}.id"
+ @conditions[:condition_table] = 'private_notes.'
+ when 'temperature'
+ @conditions[:field] = "(#{@table}.temperature ->> 'userText')::FLOAT"
+ @conditions[:first_condition] = "(#{@table}.temperature ->> 'userText')::TEXT != ''"
+ @conditions[:first_condition] += " AND (#{@table}.temperature ->> 'valueUnit')::TEXT != '' AND "
+ @conditions[:additional_condition] = "AND (#{@table}.temperature ->> 'valueUnit')::TEXT = '#{filter['unit']}'"
+ @conditions[:condition_table] = ''
+ when 'duration'
+ @conditions[:field] =
+ "(EXTRACT(epoch FROM #{@table}.duration::interval)/#{duration_interval_by_unit(filter['unit'])})::INT"
+ @conditions[:first_condition] = "#{@table}.duration IS NOT NULL AND #{@table}.duration != '' AND "
+ @conditions[:condition_table] = ''
+ when 'target_amount_value'
+ @conditions[:additional_condition] = "AND #{@table}.target_amount_unit = '#{filter['unit']}'"
+ when 'readout_titles'
+ @conditions[:joins] << 'CROSS JOIN jsonb_array_elements(readout_titles) AS titles'
+ @conditions[:field] = "REPLACE(titles::TEXT, '\"', '')"
+ @conditions[:condition_table] = ''
+ when 'purification', 'dangerous_products'
+ @conditions[:field] = "(#{@table}.#{filter['field']['column']})::TEXT"
+ @conditions[:condition_table] = ''
+ when 'iupac_name'
+ @conditions[:field] = "#{filter['field']['table']}.#{filter['field']['column']}"
+ @conditions[:additional_condition] =
+ "OR #{filter['field']['table']}.sum_formular ILIKE '#{@conditions[:words][0]}'"
+ @conditions[:condition_table] = ''
+ when 'xref'
+ @conditions[:field] = "xref ->> '#{filter['field']['opt']}'"
+ if filter['unit'].present?
+ @conditions[:field] = "xref -> '#{filter['field']['opt']}' ->> 'value'"
+ @conditions[:additional_condition] =
+ "AND (#{@table}.xref -> '#{filter['field']['opt']}' ->> 'unit')::TEXT = '#{filter['unit']}'"
+ end
+ when 'stereo'
+ @conditions[:field] = "stereo ->> '#{filter['field']['opt']}'"
+ when 'solvent'
+ cross_join_empty = @conditions[:joins].exclude?('CROSS JOIN jsonb_array_elements(solvent) AS prop_solvent')
+ @conditions[:joins] << 'CROSS JOIN jsonb_array_elements(solvent) AS prop_solvent' if cross_join_empty
+ @conditions[:field] = "(prop_solvent ->> '#{filter['field']['opt']}')::TEXT"
+ @conditions[:condition_table] = ''
+ when 'boiling_point', 'melting_point'
+ range = filter['value'].split.split('-').flatten
+ field = "#{@table}.#{filter['field']['column']}"
+ @match = '!='
+ @conditions[:words][0] = '(,)'
+ @conditions[:additional_condition] =
+ "AND #{field} <@ '[#{range.first.squish.to_f}, #{range.last.squish.to_f}]'::numrange"
+ when 'plain_text_description', 'plain_text_observation'
+ @conditions[:field] = "(regexp_replace(#{@table}.#{filter['field']['column']}, '\r|\n', '', 'g'))::TEXT"
+ @conditions[:condition_table] = ''
+ end
+ end
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
+
+ # rubocop:disable Metrics/AbcSize
+
+ def generic_field_options(filter, number)
+ key = filter['field']['key']
+ prop = "prop_#{key}_#{number}"
+ segments_alias = "segments_#{filter['field']['element_id']}"
+ element_table = @table == 'elements' ? 'elements' : segments_alias
+ segments_join =
+ "INNER JOIN segments AS #{segments_alias} ON #{segments_alias}.element_type = '#{@conditions[:model_name]}'"
+ segments_join += " AND #{segments_alias}.element_id = #{@table}.id
+ AND #{segments_alias}.segment_klass_id = #{filter['field']['element_id']}"
+ segments_join_condition = element_table == segments_alias && @conditions[:joins].exclude?(segments_join)
+
+ @conditions[:joins] << segments_join if segments_join_condition
+ @conditions[:joins] <<
+ "CROSS JOIN jsonb_array_elements(#{element_table}.properties -> 'layers' -> '#{key}' -> 'fields') AS #{prop}"
+
+ if filter['sub_values'].present?
+ generic_sub_field_options(filter['sub_values'], prop, filter)
+ else
+ @conditions[:field] = "(#{prop} ->> 'value')::TEXT"
+ @conditions[:additional_condition] = "AND (#{prop} ->> 'field')::TEXT = '#{filter['field']['column']}'"
+ end
+
+ @conditions[:condition_table] = ''
+ end
+
+ def generic_sub_field_options(sub_values, prop, filter)
+ @conditions[:field] = ''
+ @conditions[:additional_condition] = "(#{prop} ->> 'field')::TEXT = '#{filter['field']['column']}'"
+
+ sub_values.first.each_with_index do |(key, value), j|
+ next if value == ''
+
+ prop_sub = "#{prop}_sub_#{j}"
+ sub_value = "%#{value}%"
+ unit = ''
+ sub_match = 'ILIKE'
+ sub_fields = filter['field']['type'] == 'table' ? 'sub_values' : 'sub_fields'
+ if value['value'].present?
+ sub_value = value['value'].tr(',', '.')
+ search_field = "replace((#{prop_sub} -> '#{key}' ->> 'value_system')::TEXT, '°', '')"
+ unit = " AND #{search_field} = '#{value['value_system'].delete('°')}'"
+ sub_match = '>='
+ end
+
+ @conditions[:joins] << "CROSS JOIN jsonb_array_elements(#{prop} -> '#{sub_fields}') AS #{prop_sub}"
+
+ if filter['field']['type'] == 'table'
+ @conditions[:additional_condition] +=
+ " AND (#{prop_sub} ->> '#{key}')::TEXT #{sub_match} '#{sub_value}'#{unit}"
+ else
+ @conditions[:additional_condition] += " AND (#{prop_sub} ->> 'id')::TEXT = '#{key}'
+ AND (#{prop_sub} ->> 'value')::TEXT ILIKE '%#{value}%'"
+ end
+ end
+ end
+
+ def chemicals_tab_options(filter)
+ prop = "prop_#{@field_table}"
+ @conditions[:condition_table] = ''
+
+ if @conditions[:joins].exclude?('INNER JOIN chemicals ON chemicals.sample_id = samples.id')
+ @conditions[:joins] << "INNER JOIN #{@field_table} ON #{@field_table}.sample_id = #{@table}.id"
+ @conditions[:joins] << "CROSS JOIN jsonb_array_elements(#{@field_table}.chemical_data) AS #{prop}"
+ end
+
+ if filter['sub_values'].present?
+ filter['sub_values'].first.each_with_index do |(key, value), j|
+ first_and = j.zero? ? '' : ' AND'
+ @conditions[:field] = ''
+ @conditions[:additional_condition] += "#{first_and} (#{prop} ->> '#{key}')::TEXT ILIKE '#{value}'"
+ end
+ elsif filter['unit'].present?
+ @conditions[:field] = "(#{prop} -> '#{filter['field']['column']}' ->> 'value')::FLOAT"
+ @conditions[:words][0] = filter['value'].to_f
+ unit = %w[mg g].include?(filter['unit']) ? filter['unit'] : 'μg'
+ @conditions[:additional_condition] = "AND #{prop} -> '#{filter['field']['column']}' ->> 'unit' = '#{unit}'"
+ else
+ @conditions[:field] = "(#{prop} ->> '#{filter['field']['column']}')::TEXT"
+ end
+ end
+ # rubocop:enable Metrics/AbcSize
+
+ def analyses_tab_options(filter)
+ prop = "prop_#{@field_table}"
+ @conditions[:condition_table] = ''
+ field_table_inner_join =
+ "INNER JOIN #{@field_table} AS #{prop} ON #{prop}.containable_type = '#{@conditions[:model_name]}'
+ AND #{prop}.containable_id = #{@table}.id"
+
+ if @conditions[:joins].exclude?(field_table_inner_join)
+ @conditions[:joins] << field_table_inner_join
+ @conditions[:joins] << "INNER JOIN #{@field_table} AS analysis ON analysis.parent_id = #{prop}.id"
+ @conditions[:joins] << "INNER JOIN #{@field_table} AS children ON children.parent_id = analysis.id"
+ end
+
+ @conditions[:field] =
+ if %w[name description plain_text_content].include?(filter['field']['column'])
+ "children.#{filter['field']['column']}"
+ else
+ "children.extended_metadata -> '#{filter['field']['column']}'"
+ end
+ end
+
+ def measurements_tab_options(filter)
+ @conditions[:condition_table] = ''
+ @conditions[:field] = "#{@field_table}.#{filter['field']['column']}"
+ field_table_inner_join = "INNER JOIN #{@field_table} ON #{@field_table}.sample_id = #{@table}.id"
+ @conditions[:joins] << field_table_inner_join if @conditions[:joins].exclude?(field_table_inner_join)
+ end
+
+ def literatures_tab_options(filter)
+ @conditions[:condition_table] = ''
+ @conditions[:field] = "#{@field_table}.#{filter['field']['column']}"
+ field_table_inner_join = 'INNER JOIN literals ON literals.literature_id = literatures.id'
+ @conditions[:joins] << field_table_inner_join if @conditions[:joins].exclude?(field_table_inner_join)
+ end
+ end
+ end
+end
+# rubocop:enable Metrics/ClassLength
diff --git a/app/usecases/search/shared_methods.rb b/app/usecases/search/shared_methods.rb
new file mode 100644
index 0000000000..f4c4b71439
--- /dev/null
+++ b/app/usecases/search/shared_methods.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+class SharedMethods
+ attr_reader :params, :user
+
+ def initialize(user:, params: {})
+ @params = params
+ @user = user
+ @result = {}
+ end
+
+ def order_by_molecule(scope)
+ scope.includes(:molecule)
+ .joins(:molecule)
+ .order(Arel.sql("LENGTH(SUBSTRING(molecules.sum_formular, 'C\\d+'))"))
+ .order('molecules.sum_formular')
+ end
+
+ def pages(total_elements, per_page)
+ total_elements.fdiv(per_page).ceil
+ end
+
+ def serialization_by_elements_and_page(elements, error)
+ elements.each do |element|
+ if element.first == :element_ids
+ serialize_generic_elements(element, error)
+ else
+ paginated_ids = Kaminari.paginate_array(element.last).page(@params[:page]).per(@params[:per_page])
+ @result[element.first.to_s.gsub('_ids', '').pluralize] = {
+ elements: serialized_elements(element, paginated_ids),
+ ids: element.last,
+ page: @params[:page],
+ perPage: @params[:per_page],
+ pages: pages(element.last.size, @params[:per_page]),
+ totalElements: element.last.size,
+ error: error,
+ }
+ end
+ end
+ @result
+ end
+
+ def serialized_elements(element, paginated_ids)
+ if element.first == :sample_ids
+ serialize_sample(paginated_ids)
+ else
+ serialize_by_element(element, paginated_ids)
+ end
+ end
+
+ def serialize_sample(paginated_ids)
+ serialized_sample_array = []
+ Sample.includes_for_list_display
+ .where(id: paginated_ids)
+ .order(Arel.sql("position(','||id::text||',' in ',#{paginated_ids.join(',')},')"))
+ .each do |sample|
+ detail_levels = ElementDetailLevelCalculator.new(user: @user, element: sample).detail_levels
+ serialized_sample = Entities::SampleEntity.represent(
+ sample,
+ detail_levels: detail_levels,
+ displayed_in_list: true,
+ ).serializable_hash
+ serialized_sample_array.push(serialized_sample)
+ end
+ serialized_sample_array
+ end
+
+ def serialize_generic_elements(element, error)
+ klasses = Labimotion::ElementKlass.where(is_active: true, is_generic: true)
+ klasses.each do |klass|
+ element_ids_for_klass = Labimotion::Element.where(id: element.last, element_klass_id: klass.id).pluck(:id)
+ paginated_element_ids = Kaminari.paginate_array(element_ids_for_klass)
+ .page(@params[:page]).per(@params[:per_page])
+ serialized_elements = Labimotion::Element.find(paginated_element_ids).map do |generic_element|
+ Labimotion::ElementEntity.represent(generic_element, displayed_in_list: true).serializable_hash
+ end
+
+ @result["#{klass.name}s"] = {
+ elements: serialized_elements,
+ ids: element_ids_for_klass,
+ page: @page,
+ perPage: @page_size,
+ pages: pages(element_ids_for_klass.size, @params[:per_page]),
+ totalElements: element_ids_for_klass.size,
+ error: error,
+ }
+ end
+ end
+
+ def serialize_by_element(element, paginated_ids)
+ model_name = element.first.to_s.gsub('_ids', '').camelize
+ entities = "Entities::#{model_name}Entity".constantize
+
+ model_name.constantize.find(paginated_ids).map do |model|
+ entities.represent(model, displayed_in_list: true).serializable_hash
+ end
+ end
+end
diff --git a/app/usecases/search/structure_search.rb b/app/usecases/search/structure_search.rb
new file mode 100644
index 0000000000..467a6834e7
--- /dev/null
+++ b/app/usecases/search/structure_search.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Usecases
+ module Search
+ class StructureSearch
+ require_relative 'shared_methods'
+ attr_reader :collection_id, :params, :user, :detail_levels
+
+ def initialize(collection_id:, user:, params: {}, detail_levels: {})
+ @params = params
+ @collection_id = collection_id
+ @user = user
+ @detail_levels = detail_levels
+ @shared_methods = SharedMethods.new(params: @params, user: @user)
+
+ @elements = {
+ sample_ids: [],
+ reaction_ids: [],
+ wellplate_ids: [],
+ screen_ids: [],
+ research_plan_ids: [],
+ element_ids: [],
+ }
+ @user_samples = Sample.by_collection_id(@collection_id)
+ @user_reactions = Reaction.by_collection_id(@collection_id)
+ @user_wellplates = Wellplate.by_collection_id(@collection_id)
+ @user_screens = Screen.by_collection_id(@collection_id)
+ @user_research_plans = ResearchPlan.by_collection_id(@collection_id)
+ @user_elements = Labimotion::Element.by_collection_id(@collection_id)
+ end
+
+ def perform!
+ scope = basic_scope
+ elements_by_scope(scope)
+ @shared_methods.serialization_by_elements_and_page(@elements, '')
+ end
+
+ private
+
+ def basic_scope
+ not_permitted = @dl_s && @dl_s < 1
+ return Sample.none if not_permitted
+
+ molfile = Fingerprint.standardized_molfile(@params[:selection][:molfile])
+ threshold = @params[:selection][:tanimoto_threshold]
+
+ # TODO: implement this: http://pubs.acs.org/doi/abs/10.1021/ci600358f
+ scope =
+ if @params[:selection][:search_type] == 'similar'
+ Sample.by_collection_id(@collection_id).search_by_fingerprint_sim(molfile, threshold)
+ else
+ Sample.by_collection_id(@collection_id).search_by_fingerprint_sub(molfile)
+ end
+ scope = @shared_methods.order_by_molecule(scope)
+ scope.pluck(:id)
+ end
+
+ def elements_by_scope(scope)
+ return if scope.blank?
+
+ @elements[:sample_ids] = scope
+ sample_relations_element_ids
+ end
+
+ # rubocop:disable Metrics/AbcSize
+
+ def sample_relations_element_ids
+ @elements[:reaction_ids] = @user_reactions.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:wellplate_ids] = @user_wellplates.by_sample_ids(@elements[:sample_ids]).uniq.pluck(:id)
+ @elements[:screen_ids] = @user_screens.by_wellplate_ids(@elements[:wellplate_ids]).pluck(:id).uniq
+ @elements[:research_plan_ids] = @user_research_plans.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ @elements[:element_ids] = @user_elements.by_sample_ids(@elements[:sample_ids]).pluck(:id).uniq
+ end
+ # rubocop:enable Metrics/AbcSize
+ end
+ end
+end
diff --git a/app/usecases/sharing/share_with_user.rb b/app/usecases/sharing/share_with_user.rb
index cc67a56fe1..e5771848a0 100644
--- a/app/usecases/sharing/share_with_user.rb
+++ b/app/usecases/sharing/share_with_user.rb
@@ -9,8 +9,8 @@ def initialize(**params)
@current_user_id = @collection_attributes[:shared_by_id]
end
- def execute!
- ActiveRecord::Base.transaction do
+ def execute! # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
+ ActiveRecord::Base.transaction do # rubocop:disable Metrics/BlockLength
c = Collection.create(@collection_attributes)
sample_ids = @params.fetch(:sample_ids, [])
reaction_ids = @params.fetch(:reaction_ids, [])
@@ -18,6 +18,7 @@ def execute!
screen_ids = @params.fetch(:screen_ids, [])
research_plan_ids = @params.fetch(:research_plan_ids, [])
element_ids = @params.fetch(:element_ids, [])
+ cell_line_ids = @params.fetch(:cell_line_ids, [])
# Reactions and Wellplates have associated Samples
associated_sample_ids = Sample.associated_by_user_id_and_reaction_ids(@current_user_id, reaction_ids).map(&:id) + Sample.associated_by_user_id_and_wellplate_ids(@current_user_id, wellplate_ids).map(&:id)
@@ -60,9 +61,13 @@ def execute!
CollectionsResearchPlan.create(collection_id: c.id, research_plan_id: research_plan_id)
end
+ cell_line_ids.each do |cell_line_id|
+ CollectionsCellline.create(collection_id: c.id, cellline_sample_id: cell_line_id)
+ end
+
element_ids.each do |k, ids|
ids.each do |element_id|
- CollectionsElement.create(collection_id: c.id, element_id: element_id, element_type: k)
+ Labimotion::CollectionsElement.create(collection_id: c.id, element_id: element_id, element_type: k)
end
end
diff --git a/app/usecases/sharing/share_with_users.rb b/app/usecases/sharing/share_with_users.rb
index f3a0c81413..b27e302e23 100644
--- a/app/usecases/sharing/share_with_users.rb
+++ b/app/usecases/sharing/share_with_users.rb
@@ -19,6 +19,7 @@ def execute!
wellplate_ids: @params.fetch(:wellplate_ids, []),
screen_ids: @params.fetch(:screen_ids, []),
research_plan_ids: @params.fetch(:research_plan_ids, []),
+ cell_line_ids: @params.fetch(:cell_line_ids, []),
element_ids: @params.fetch(:element_ids, [])
).execute!
end
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index a650b8a61a..8cdca389b2 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -7,22 +7,7 @@
= render "devise/shared/omniauth"
%hr
- %h3 Log in with registered account
- = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
- .form-group.field
- = f.label :login, "Email or name abbreviation(case-sensitive)"
- %br/
- = f.text_field :login, autofocus: true, class: 'form-control'
- .form-group.field
- = f.label :password
- %br/
- = f.password_field :password, autocomplete: "off", class: 'form-control'
- - if devise_mapping.rememberable?
- .form-group.field
- = f.check_box :remember_me
- = f.label :remember_me
- .form-group.actions
- = f.submit "Log in", class: 'btn btn-primary'
+ = render "devise/shared/dblogin"
= render "devise/shared/links"
- = link_to "Back", root_path
\ No newline at end of file
+ = link_to "Back", root_path
diff --git a/app/views/devise/shared/_affiliations.html.haml b/app/views/devise/shared/_affiliations.html.haml
index 2ffec3e78f..70cc723246 100644
--- a/app/views/devise/shared/_affiliations.html.haml
+++ b/app/views/devise/shared/_affiliations.html.haml
@@ -16,7 +16,7 @@
= f.text_field :department, autofocus: true, class: 'form-control',
id: 'department-select'
.form-group.field
- = f.label "Group"
+ = f.label "Working group"
%br/
= f.text_field :group, autofocus: true, class: 'form-control',
id: 'group-select'
diff --git a/app/views/devise/shared/_dblogin.html.haml b/app/views/devise/shared/_dblogin.html.haml
new file mode 100644
index 0000000000..b7e875ddc2
--- /dev/null
+++ b/app/views/devise/shared/_dblogin.html.haml
@@ -0,0 +1,19 @@
+- if !(resource.extra_rules['disable_db_login'] == true)
+ %h3 Log in with registered account
+
+- if !(resource.extra_rules['disable_db_login'] == true)
+ = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
+ .form-group.field
+ = f.label :login, "Email or name abbreviation(case-sensitive)"
+ %br/
+ = f.text_field :login, autofocus: true, class: 'form-control'
+ .form-group.field
+ = f.label :password
+ %br/
+ = f.password_field :password, autocomplete: "off", class: 'form-control'
+ - if devise_mapping.rememberable?
+ .form-group.field
+ = f.check_box :remember_me
+ = f.label :remember_me
+ .form-group.actions
+ = f.submit "Log in", class: 'btn btn-primary'
diff --git a/app/views/devise/shared/_links.html.haml b/app/views/devise/shared/_links.html.haml
index d7625af933..bbb1745d95 100644
--- a/app/views/devise/shared/_links.html.haml
+++ b/app/views/devise/shared/_links.html.haml
@@ -1,10 +1,10 @@
- if controller_name != 'sessions'
= link_to "Log in", new_session_path(resource_name)
%br/
-- if devise_mapping.registerable? && controller_name != 'registrations'
+- if devise_mapping.registerable? && controller_name != 'registrations' && !(resource.extra_rules['disable_signup'] == true)
= link_to "Sign up", new_registration_path(resource_name)
%br/
-- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
+- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' && !(resource.extra_rules['disable_signup'] == true)
= link_to "Forgot your password?", new_password_path(resource_name)
%br/
- if devise_mapping.confirmable? && controller_name != 'confirmations'
@@ -12,4 +12,4 @@
%br/
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name)
- %br/
\ No newline at end of file
+ %br/
diff --git a/app/views/pages/affiliations.haml b/app/views/pages/affiliations.haml
index f1fcff101b..57e6672caa 100644
--- a/app/views/pages/affiliations.haml
+++ b/app/views/pages/affiliations.haml
@@ -25,7 +25,7 @@
%th.col-xs-1 Country
%th.col-xs-3 Organization
%th.col-xs-2 Department
- %th.col-xs-2 Group
+ %th.col-xs-2 Working group
%th.col-xs-1 from
%th.col-xs-1 to
%th.col-xs-1
diff --git a/app/views/pages/gda.haml b/app/views/pages/gda.haml
new file mode 100644
index 0000000000..11462fa337
--- /dev/null
+++ b/app/views/pages/gda.haml
@@ -0,0 +1 @@
+#GenericDatasetsAdmin
\ No newline at end of file
diff --git a/app/views/pages/gea.haml b/app/views/pages/gea.haml
new file mode 100644
index 0000000000..f8ee2036bd
--- /dev/null
+++ b/app/views/pages/gea.haml
@@ -0,0 +1 @@
+#GenericElementsAdmin
\ No newline at end of file
diff --git a/app/views/pages/gsa.haml b/app/views/pages/gsa.haml
new file mode 100644
index 0000000000..8b4a9c6d54
--- /dev/null
+++ b/app/views/pages/gsa.haml
@@ -0,0 +1 @@
+#GenericSegmentsAdmin
\ No newline at end of file
diff --git a/app/views/pages/settings.haml b/app/views/pages/settings.haml
index 7af13be42a..23abc4168a 100644
--- a/app/views/pages/settings.haml
+++ b/app/views/pages/settings.haml
@@ -18,7 +18,7 @@
maxlength: 3,
class: 'form-control',
id: 'reaction-name-prefix',
- oninput: 'showExampleLabel();'
+ oninput: 'showExampleLabel()'
.form-group
= f.label 'Counter starts at', class: 'col-sm-2 col-sm-offset-2 control-label'
.col-sm-2
@@ -27,7 +27,7 @@
min: 0,
class: 'form-control',
id: 'reactions-count',
- oninput: 'showExampleLabel();'
+ oninput: 'showExampleLabel()'
= hidden_field_tag :name_abbreviation, current_user.name_abbreviation
%div
.col-sm-4.col-sm-offset-2
@@ -36,6 +36,8 @@
.col-sm-4.col-sm-offset-2
= f.submit "Update user settings", class: "btn btn-primary"
+ #InventoryLabelSettings
+
.panel.panel-default
.panel-heading
%h3.panel-title
@@ -83,5 +85,8 @@
#UserCounter
- = link_to "Back", root_path
+ = link_to(root_path) do
+ %button.btn.btn-primary.primary-button{ style: 'margin-left: 30px; margin-bottom: 20px;' } Back
+
+ %script{:src => asset_path('pages.js')}
diff --git a/app/views/users/registrations/new.html.haml b/app/views/users/registrations/new.html.haml
index 8f948d1665..3d358a535d 100644
--- a/app/views/users/registrations/new.html.haml
+++ b/app/views/users/registrations/new.html.haml
@@ -13,14 +13,14 @@
= f.email_field :email, autofocus: true, class: 'form-control', required: true, readonly: !resource.password_required?
- if resource.password_required?
.form-group.field
- = f.label :password
+ = f.label :password, 'Password *'
- if @validatable
%em
(#{@minimum_password_length} characters minimum)
%br/
= f.password_field :password, autocomplete: "off", class: 'form-control'
.form-group.field
- = f.label :password_confirmation
+ = f.label :password_confirmation, 'Password confirmation *'
%br/
= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control'
.form-group.field
@@ -48,4 +48,4 @@
= f.submit "Sign up", class: 'btn btn-primary'
= render "devise/shared/links"
- = link_to "Back", root_path
\ No newline at end of file
+ = link_to "Back", root_path
diff --git a/bin/run_mail_collector b/bin/run_mail_collector
new file mode 100644
index 0000000000..82d2a6b161
--- /dev/null
+++ b/bin/run_mail_collector
@@ -0,0 +1,5 @@
+#!/usr/bin/env ruby
+
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
+CollectDataFromMailJob.perform_now
+
diff --git a/config/application.rb b/config/application.rb
index 0df45abdb7..5a6760fc3c 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -64,6 +64,9 @@ class Application < Rails::Application
end
config.root_url = uri&.to_s
+ # path of public-asset file for chemspectra data_types
+ config.path_spectra_data_type = Rails.public_path.join('data_type.json').to_s.freeze
+
# tmp assets fix
sprite_file = Rails.public_path.join('sprite.png')
sprite_source = Rails.public_path.join('assets', 'ketcherails', 'sprite*.png')
diff --git a/config/deploy.rb b/config/deploy.rb
index 0ccdcff8cc..951d40abf0 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -35,7 +35,6 @@
'config/database.yml',
'config/storage.yml',
'config/user_props.yml',
- # 'config/datacollectors.yml',
'config/secrets.yml',
# 'config/spectra.yml',
'.env'
diff --git a/config/environment.rb b/config/environment.rb
index 426333bb46..21d7b65457 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,5 +1,6 @@
# Load the Rails application.
require_relative 'application'
+require 'labimotion'
# Initialize the Rails application.
Rails.application.initialize!
diff --git a/config/initializers/delayed_job_config.rb b/config/initializers/delayed_job_config.rb
index ddff927f15..1579c61812 100644
--- a/config/initializers/delayed_job_config.rb
+++ b/config/initializers/delayed_job_config.rb
@@ -48,9 +48,6 @@
cron_config ||= "#{rand(0..59)} #{rand(20..23)} * * #{rand(6..7)}"
RefreshElementTagJob.set(cron: cron_config).perform_later
Delayed::Job.where("handler like ?", "%ChemrepoIdJob%").destroy_all
- cron_config = ENV['CRON_CONFIG_CHEM_REPO_ID'].presence
- cron_config ||= "#{rand(0..59)} #{rand(17..19)} * * #{rand(6..7)}"
- ChemrepoIdJob.set(cron: cron_config ).perform_later
end
rescue PG::ConnectionBad, ActiveRecord::NoDatabaseError => e
puts e.message
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 8bbdc1f4d6..6d244b0788 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -256,6 +256,7 @@
auth_config.dig('orcid', 'client_id'),
auth_config.dig('orcid', 'client_secret'),
icon: auth_config.dig('orcid', 'icon'),
+ label: auth_config.dig('orcid', 'label') || 'ORCID',
member: auth_config.dig('orcid', 'member'),
sandbox: auth_config.dig('orcid', 'sandbox'),
scope: auth_config.dig('orcid', 'sandbox')
@@ -271,7 +272,6 @@
redirect_uri: auth_config.dig('chemotion_orcid', 'redirect_uri'),
strategy_class: OmniAuth::Strategies::ChemotionORCID
end
-
if auth_config.key?('shibboleth') && auth_config.dig('shibboleth', 'enable') == true
config.omniauth :shibboleth, {
request_type: 'header',
@@ -282,15 +282,15 @@
last_name: auth_config.dig('shibboleth', 'last_name') || 'sn',
},
icon: auth_config.dig('shibboleth', 'icon'),
+ label: auth_config.dig('shibboleth', 'label') || 'Shibboleth',
}
end
-
if auth_config.key?('github') && auth_config.dig('github', 'enable') == true
config.omniauth :github,
auth_config.dig('github', 'client_id'), auth_config.dig('github', 'client_secret'),
- scope: 'user,public_repo', icon: auth_config.dig('github', 'icon')
+ scope: 'user,public_repo', icon: auth_config.dig('github', 'icon'),
+ label: auth_config.dig('github', 'label') || 'GitHub'
end
-
if auth_config.key?('openid_connect') && auth_config.dig('openid_connect', 'enable') == true
options = {
port: 443,
@@ -308,7 +308,8 @@
response_type: :code,
discovery: true,
client_options: options,
- icon: auth_config.dig('openid_connect', 'icon')
+ icon: auth_config.dig('openid_connect', 'icon'),
+ label: auth_config.dig('openid_connect', 'label') || 'OpenID Connect'
end
end
diff --git a/config/initializers/eln_features.rb b/config/initializers/eln_features.rb
index b4836159d1..c9440aba8c 100644
--- a/config/initializers/eln_features.rb
+++ b/config/initializers/eln_features.rb
@@ -9,7 +9,7 @@
# config.eln_features.merge(ActiveRecord::Base.connection.table_exists?('matrices') ? Matrice.pluck(:name, :id).to_h : {})
Matrice.gen_matrices_json if ActiveRecord::Base.connection.table_exists?('matrices')
- ElementKlass.gen_klasses_json if ActiveRecord::Base.connection.table_exists?('element_klasses')
+ Labimotion::ElementKlass.gen_klasses_json if ActiveRecord::Base.connection.table_exists?('element_klasses')
rescue PG::ConnectionBad, ActiveRecord::NoDatabaseError => e
puts e.message
end
diff --git a/config/initializers/radar.rb b/config/initializers/radar.rb
index 3c1c62ddc2..e67230083d 100644
--- a/config/initializers/radar.rb
+++ b/config/initializers/radar.rb
@@ -16,7 +16,6 @@
config.radar.softwareVersion = radar_config[:softwareVersion]
end
rescue StandardError => e
- puts e.message
Rails.application.configure do
config.radar = nil
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 915e7237ea..abbb9d71b7 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -33,7 +33,8 @@ en:
hello: "Hello world"
time:
formats:
- eln_timestamp: '%d.%m.%Y, %H:%M:%S'
+ eln_timestamp: "%d.%m.%Y, %H:%M:%S %z"
+ eln_iso8601: "%Y-%m-%dT%H:%M:%S%z"
activerecord:
errors:
models:
diff --git a/config/profile_default.yml.example b/config/profile_default.yml.example
index 5320c14776..0a533148ee 100644
--- a/config/profile_default.yml.example
+++ b/config/profile_default.yml.example
@@ -6,6 +6,7 @@ development:
:wellplate: 3
:screen: 4
:research_plan: 5
+ :cell_line: -1000
:layout_detail_research_plan:
:research_plan:
1
@@ -37,6 +38,8 @@ development:
4
:green_chemistry:
5
+ :variations:
+ 6
:layout_detail_wellplate:
:properties:
1
@@ -60,6 +63,7 @@ production:
:wellplate: 3
:screen: 4
:research_plan: 5
+ :cell_line: -1000
:layout_detail_research_plan:
:research_plan:
1
@@ -91,6 +95,8 @@ production:
4
:green_chemistry:
5
+ :variations:
+ 6
:layout_detail_wellplate:
:properties:
1
@@ -114,6 +120,7 @@ test:
:wellplate: 3
:screen: 4
:research_plan: 5
+ :cell_line: -1000
:layout_detail_research_plan:
:research_plan:
1
@@ -145,6 +152,8 @@ test:
4
:green_chemistry:
5
+ :variations:
+ 6
:layout_detail_wellplate:
:properties:
1
diff --git a/config/routes.rb b/config/routes.rb
index 917a9cf970..dab76aa370 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,8 +1,10 @@
+# rubocop:disable Metrics/BlockLength, Layout/LineLength, Style/FrozenStringLiteralComment
+#
Rails.application.routes.draw do
- post "/graphql", to: "graphql#execute" unless Rails.env.production?
+ post '/graphql', to: 'graphql#execute' unless Rails.env.production?
if ENV['DEVISE_DISABLED_SIGN_UP'].presence == 'true'
- devise_for :users, controllers: { registrations: 'users/registrations' }, skip: [:registrations]
+ devise_for :users, controllers: { registrations: 'users/registrations', omniauth_callbacks: 'users/omniauth' }, skip: [:registrations]
as :user do
get 'sign_in' => 'devise/sessions#new'
get 'users/sign_up' => 'devise/sessions#new', as: 'new_user_registration'
@@ -14,15 +16,14 @@
devise_for :users, controllers: { registrations: 'users/registrations', omniauth_callbacks: 'users/omniauth' }
end
- authenticated :user, lambda {|u| u.type == "Admin"} do
+ authenticated :user, ->(u) { u.type == 'Admin' } do
root to: 'pages#admin', as: :admin_root
get 'admin', to: 'pages#admin'
get 'mydb/*any', to: 'pages#admin'
get 'mydb', to: 'pages#admin'
end
-
- authenticated :user, lambda {|u| u.type == "Group"} do
+ authenticated :user, ->(u) { u.type == 'Group' } do
root to: 'pages#cnc', as: :group_root
get 'group', to: 'pages#cnc'
get 'mydb/*any', to: 'pages#cnc'
@@ -47,6 +48,9 @@
get 'mydb', to: 'pages#welcome'
get 'molecule_moderator', to: 'pages#molecule_moderator'
get 'converter_admin', to: 'pages#converter_admin'
+ get 'generic_elements_admin', to: 'pages#gea'
+ get 'generic_segments_admin', to: 'pages#gsa'
+ get 'generic_datasets_admin', to: 'pages#gda'
end
# Standalone page for ChemScanner
@@ -80,3 +84,5 @@
get 'test', to: 'pages#test'
end
+
+# rubocop: enable Metrics/BlockLength, Layout/LineLength, Style/FrozenStringLiteralComment
diff --git a/config/webpack/custom.js b/config/webpack/custom.js
index b98d8fa3b0..f3a05f7281 100644
--- a/config/webpack/custom.js
+++ b/config/webpack/custom.js
@@ -10,14 +10,18 @@ module.exports = {
util: require.resolve('util/'),
querystring: require.resolve('querystring-es3'),
stream: false,
- 'process/browser': require.resolve('process/browser')
- }
+ 'process/browser': require.resolve('process/browser'),
+ },
},
plugins: [
new webpack.DefinePlugin({
'process.version': JSON.stringify(process.version),
- 'process.env.SENTRY_FRONTEND_DSN': JSON.stringify(process.env.SENTRY_FRONTEND_DSN),
- 'process.env.SENTRY_FRONTEND_SAMPLE_RATE': JSON.stringify(process.env.SENTRY_FRONTEND_SAMPLE_RATE)
+ 'process.env.SENTRY_FRONTEND_DSN': JSON.stringify(
+ process.env.SENTRY_FRONTEND_DSN
+ ),
+ 'process.env.SENTRY_FRONTEND_SAMPLE_RATE': JSON.stringify(
+ process.env.SENTRY_FRONTEND_SAMPLE_RATE
+ ),
}),
new webpack.ProvidePlugin({
process: 'process/browser',
@@ -27,8 +31,8 @@ module.exports = {
rules: [
{
test: /\.md$/,
- use: 'raw-loader'
- }
- ]
- }
+ use: 'raw-loader',
+ },
+ ],
+ },
};
diff --git a/db/migrate/20210318133000_generic_datasets.rb b/db/migrate/20210318133000_generic_datasets.rb
index f3a824e3b9..379d352ef0 100644
--- a/db/migrate/20210318133000_generic_datasets.rb
+++ b/db/migrate/20210318133000_generic_datasets.rb
@@ -28,7 +28,7 @@ def self.up
end
end
Matrice.create(name: 'genericDataset', enabled: false, label: 'genericDataset', include_ids: [], exclude_ids: []) if Matrice.find_by(name: 'genericDataset').nil?
- DatasetKlass.init_seeds
+ Labimotion::DatasetKlass.init_seeds
end
def self.down
diff --git a/db/migrate/20210610105014_generic_elements_revision_migration.rb b/db/migrate/20210610105014_generic_elements_revision_migration.rb
index af2c24f851..a68d53a47f 100644
--- a/db/migrate/20210610105014_generic_elements_revision_migration.rb
+++ b/db/migrate/20210610105014_generic_elements_revision_migration.rb
@@ -4,11 +4,11 @@
class GenericElementsRevisionMigration < ActiveRecord::Migration[4.2]
# ElementKlass
class ElementKlass < ActiveRecord::Base
- ElementKlass.reset_column_information
+ Labimotion::ElementKlass.reset_column_information
end
# Element
class Element < ActiveRecord::Base
- Element.reset_column_information
+ Labimotion::Element.reset_column_information
end
def self.up
@@ -37,7 +37,7 @@ def self.up
properties_release: klass.properties_template,
released_at: klass.released_at
}
- ElementKlassesRevision.create(attributes)
+ Labimotion::ElementKlassesRevision.create(attributes)
end
Element.find_each do |el|
@@ -70,7 +70,7 @@ def self.up
name: el.name,
properties: el.properties
}
- ElementsRevision.create(attributes)
+ Labimotion::ElementsRevision.create(attributes)
end
end
diff --git a/db/migrate/20210621155000_generic_datasets_revision_migration.rb b/db/migrate/20210621155000_generic_datasets_revision_migration.rb
index 9a07871a3a..bebe6d4c14 100644
--- a/db/migrate/20210621155000_generic_datasets_revision_migration.rb
+++ b/db/migrate/20210621155000_generic_datasets_revision_migration.rb
@@ -2,17 +2,8 @@
# Create generic datasets revision migration
class GenericDatasetsRevisionMigration < ActiveRecord::Migration[4.2]
- # DatasetKlass
- class DatasetKlass < ActiveRecord::Base
- DatasetKlass.reset_column_information
- end
- # Dataset
- class Dataset < ActiveRecord::Base
- Dataset.reset_column_information
- end
-
def self.up
- DatasetKlass.find_each do |klass|
+ Labimotion::DatasetKlass.find_each do |klass|
uuid = SecureRandom.uuid
properties = klass.properties_template || { uuid: uuid, layers: {}, select_options: {} }
properties['uuid'] = uuid
@@ -36,10 +27,10 @@ def self.up
properties_release: klass.properties_template,
released_at: klass.released_at
}
- DatasetKlassesRevision.create(attributes)
+ Labimotion::DatasetKlassesRevision.create(attributes)
end
- Dataset.find_each do |el|
+ Labimotion::Dataset.find_each do |el|
klass = DatasetKlass.find_by(id: el.dataset_klass_id)
if klass.nil?
el.destroy!
@@ -68,7 +59,7 @@ def self.up
deleted_at: el.deleted_at,
properties: el.properties
}
- DatasetsRevision.create(attributes)
+ Labimotion::DatasetsRevision.create(attributes)
end
end
diff --git a/db/migrate/20210727145003_generic_workflow_migration.rb b/db/migrate/20210727145003_generic_workflow_migration.rb
new file mode 100644
index 0000000000..6f26705b71
--- /dev/null
+++ b/db/migrate/20210727145003_generic_workflow_migration.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+# Create generic workflow migration
+class GenericWorkflowMigration < ActiveRecord::Migration[6.1]
+ def change
+ add_column :elements, :properties_release, :jsonb, null: true unless column_exists? :elements, :properties_release
+ add_column :segments, :properties_release, :jsonb, null: true unless column_exists? :segments, :properties_release
+ add_column :datasets, :properties_release, :jsonb, null: true unless column_exists? :datasets, :properties_release
+ add_column :elements_revisions, :properties_release, :jsonb, null: true unless column_exists? :elements_revisions, :properties_release
+ add_column :segments_revisions, :properties_release, :jsonb, null: true unless column_exists? :segments_revisions, :properties_release
+ add_column :datasets_revisions, :properties_release, :jsonb, null: true unless column_exists? :datasets_revisions, :properties_release
+
+ %w[Labimotion::ElementKlass Labimotion::SegmentKlass Labimotion::ElementKlassesRevision Labimotion::SegmentKlassesRevision].each do |klasses|
+ klasses.constantize.find_each do |klass|
+ properties_release = klass.properties_release
+ (properties_release['layers'] || {}).keys.each do |key|
+ properties_release['layers'][key]['layer'] = properties_release['layers'][key]['key']
+ properties_release['layers'][key]['wf'] = false if properties_release['layers'][key]['wf'].nil?
+ end
+ klass.update_columns(properties_release: properties_release)
+ end
+ end
+
+ %w[Labimotion::Element Labimotion::Segment Labimotion::Dataset Labimotion::ElementsRevision Labimotion::SegmentsRevision Labimotion::DatasetsRevision].each do |els|
+ els.constantize.find_each do |el|
+ properties = el.properties
+ (properties['layers'] || {}).keys.each do |key|
+ properties['layers'][key]['layer'] = properties['layers'][key]['key']
+ properties['layers'][key]['wf'] = false if properties['layers'][key]['wf'].nil?
+ end
+ klass = Labimotion::ElementKlassesRevision.find_by(uuid: el.klass_uuid) if %w[Labimotion::Element Labimotion::ElementsRevision].include?(els)
+ klass = Labimotion::SegmentKlassesRevision.find_by(uuid: el.klass_uuid) if %w[Labimotion::Segment Labimotion::SegmentsRevision].include?(els)
+ klass = Labimotion::DatasetKlassesRevision.find_by(uuid: el.klass_uuid) if %w[Labimotion::Dataset Labimotion::DatasetsRevision].include?(els)
+ properties_release = klass.present? ? klass.properties_release : properties
+ el.update_columns(properties: properties, properties_release: properties_release)
+ end
+ end
+ end
+end
diff --git a/db/migrate/20210820165003_generic_elements_to_element.rb b/db/migrate/20210820165003_generic_elements_to_element.rb
new file mode 100644
index 0000000000..ffa0c69d24
--- /dev/null
+++ b/db/migrate/20210820165003_generic_elements_to_element.rb
@@ -0,0 +1,16 @@
+class GenericElementsToElement < ActiveRecord::Migration[5.2]
+ def change
+ unless table_exists? :elements_elements
+ create_table :elements_elements do |t|
+ t.integer :element_id
+ t.integer :parent_id
+ t.integer :created_by
+ t.datetime :created_at
+ t.datetime :updated_at
+ t.datetime :deleted_at
+ t.index :element_id
+ t.index :parent_id
+ end
+ end
+ end
+end
diff --git a/db/migrate/20211105111420_add_dry_solvent_to_samples.rb b/db/migrate/20211105111420_add_dry_solvent_to_samples.rb
new file mode 100644
index 0000000000..8ec4d32164
--- /dev/null
+++ b/db/migrate/20211105111420_add_dry_solvent_to_samples.rb
@@ -0,0 +1,5 @@
+class AddDrySolventToSamples < ActiveRecord::Migration[5.2]
+ def change
+ add_column :samples, :dry_solvent, :boolean, default: false
+ end
+end
diff --git a/db/migrate/20220127000608_create_comments.rb b/db/migrate/20220127000608_create_comments.rb
new file mode 100644
index 0000000000..b06c60e572
--- /dev/null
+++ b/db/migrate/20220127000608_create_comments.rb
@@ -0,0 +1,19 @@
+class CreateComments < ActiveRecord::Migration[5.2]
+ def change
+ create_table :comments do |t|
+ t.string :content
+ t.integer :created_by, null: false
+ t.string :section
+ t.string :status, default: "Pending"
+ t.string :submitter
+ t.string :resolver_name
+ t.integer :commentable_id
+ t.string :commentable_type
+
+ t.timestamps
+ end
+ add_index :comments, :created_by, name: "index_comments_on_user"
+ add_index :comments, :section, name: "index_comments_on_section"
+ add_index :comments, [:commentable_type, :commentable_id]
+ end
+end
diff --git a/db/migrate/20220317004217_add_comment_channel.rb b/db/migrate/20220317004217_add_comment_channel.rb
new file mode 100644
index 0000000000..7d3cf5675c
--- /dev/null
+++ b/db/migrate/20220317004217_add_comment_channel.rb
@@ -0,0 +1,27 @@
+class AddCommentChannel < ActiveRecord::Migration[5.2]
+ def change
+ channel = Channel.find_by(subject: Channel::COMMENT_ON_MY_COLLECTION)
+ if channel.nil?
+ attributes = {
+ subject: Channel::COMMENT_ON_MY_COLLECTION,
+ channel_type: 8,
+ msg_template: JSON.parse('{"data": "%{commented_by} has commented on a collection: %{collection_name}.",
+ "action":"CollectionActions.fetchSyncInCollectionRoots"}')
+ }
+
+ Channel.create(attributes)
+ end
+
+ channel = Channel.find_by(subject: Channel::COMMENT_RESOLVED)
+ if channel.nil?
+ attributes = {
+ subject: Channel::COMMENT_RESOLVED,
+ channel_type: 8,
+ msg_template: JSON.parse('{"data": "%{resolved_by} has marked your comment as resolved.",
+ "action":"CollectionActions.fetchSyncInCollectionRoots"}')
+ }
+
+ Channel.create(attributes)
+ end
+ end
+end
diff --git a/db/migrate/20220406094235_add_tabs_segment_to_collection.rb b/db/migrate/20220406094235_add_tabs_segment_to_collection.rb
new file mode 100644
index 0000000000..07ea6229b7
--- /dev/null
+++ b/db/migrate/20220406094235_add_tabs_segment_to_collection.rb
@@ -0,0 +1,5 @@
+class AddTabsSegmentToCollection < ActiveRecord::Migration[5.2]
+ def change
+ add_column :collections, :tabs_segment, :jsonb, default: {}
+ end
+end
diff --git a/db/migrate/20220712100010_add_segment_klass_identifier.rb b/db/migrate/20220712100010_add_segment_klass_identifier.rb
new file mode 100644
index 0000000000..292d06b0e3
--- /dev/null
+++ b/db/migrate/20220712100010_add_segment_klass_identifier.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# Add column identifier into segment_klasses
+class AddSegmentKlassIdentifier < ActiveRecord::Migration[5.2]
+ def self.up
+ execute 'CREATE EXTENSION IF NOT EXISTS pgcrypto;'
+ add_column :segment_klasses, :identifier, :string unless column_exists? :segment_klasses, :identifier
+ add_column :segment_klasses, :sync_time, :datetime unless column_exists? :segment_klasses, :sync_time
+ add_column :dataset_klasses, :identifier, :string unless column_exists? :dataset_klasses, :identifier
+ add_column :dataset_klasses, :sync_time, :datetime unless column_exists? :dataset_klasses, :sync_time
+ add_column :element_klasses, :identifier, :string unless column_exists? :element_klasses, :identifier
+ add_column :element_klasses, :sync_time, :datetime unless column_exists? :element_klasses, :sync_time
+ end
+
+ def self.down
+ remove_column :segment_klasses, :identifier if column_exists? :segment_klasses, :identifier
+ remove_column :segment_klasses, :sync_time if column_exists? :segment_klasses, :sync_time
+ remove_column :dataset_klasses, :identifier if column_exists? :dataset_klasses, :identifier
+ remove_column :dataset_klasses, :sync_time if column_exists? :dataset_klasses, :sync_time
+ remove_column :element_klasses, :identifier if column_exists? :element_klasses, :identifier
+ remove_column :element_klasses, :sync_time if column_exists? :element_klasses, :sync_time
+ end
+end
diff --git a/db/migrate/20220926103002_omniauth_providers.rb b/db/migrate/20220926103002_omniauth_providers.rb
index 5d7ae52caf..cd9861c86e 100644
--- a/db/migrate/20220926103002_omniauth_providers.rb
+++ b/db/migrate/20220926103002_omniauth_providers.rb
@@ -4,12 +4,15 @@ def change
User.where.not(omniauth_provider: '').find_each do |u|
next if u.omniauth_provider.blank? || u.omniauth_uid.blank?
- providers = {}
- providers[u.omniauth_provider] = u.omniauth_uid
- u.update_columns(providers: providers)
+
+ if u.omniauth_provider.present? && u.omniauth_uid.present?
+ providers = {}
+ providers[u.omniauth_provider] = u.omniauth_uid
+ u.update_columns(providers: providers) if providers && providers.is_a?(Hash)
+ end
end
remove_column :users, :omniauth_provider if column_exists? :users, :omniauth_provider
remove_column :users, :omniauth_uid if column_exists? :users, :omniauth_uid
end
- end
\ No newline at end of file
+ end
diff --git a/db/migrate/20221128073938_add_sort_indexes_to_reactions.rb b/db/migrate/20221128073938_add_sort_indexes_to_reactions.rb
new file mode 100644
index 0000000000..611d155fd8
--- /dev/null
+++ b/db/migrate/20221128073938_add_sort_indexes_to_reactions.rb
@@ -0,0 +1,6 @@
+class AddSortIndexesToReactions < ActiveRecord::Migration[5.2]
+ def change
+ add_index :reactions, :rinchi_short_key, order: { rinchi_short_key: :desc }
+ add_index :reactions, :rxno, order: { rxno: :desc }
+ end
+end
diff --git a/db/migrate/20230213102539_create_third_party_apps.rb b/db/migrate/20230213102539_create_third_party_apps.rb
index 0e6a4ef234..beb9dcad2a 100644
--- a/db/migrate/20230213102539_create_third_party_apps.rb
+++ b/db/migrate/20230213102539_create_third_party_apps.rb
@@ -1,9 +1,9 @@
class CreateThirdPartyApps < ActiveRecord::Migration[6.1]
def change
create_table :third_party_apps do |t|
- t.string :IPAddress
- t.string :name
+ t.string :url
+ t.string :name, null: false, index: { unique: true }, limit: 100
t.timestamps
end
end
-end
+end
\ No newline at end of file
diff --git a/db/migrate/20230320132646_add_variations_to_reactions.rb b/db/migrate/20230320132646_add_variations_to_reactions.rb
new file mode 100644
index 0000000000..7a4473e873
--- /dev/null
+++ b/db/migrate/20230320132646_add_variations_to_reactions.rb
@@ -0,0 +1,5 @@
+class AddVariationsToReactions < ActiveRecord::Migration[6.1]
+ def change
+ add_column :reactions, :variations, :jsonb, default: []
+ end
+end
diff --git a/db/migrate/20230420121233_matrice_comment.rb b/db/migrate/20230420121233_matrice_comment.rb
new file mode 100644
index 0000000000..e9c0ee5dd3
--- /dev/null
+++ b/db/migrate/20230420121233_matrice_comment.rb
@@ -0,0 +1,12 @@
+class MatriceComment < ActiveRecord::Migration[6.1]
+ def change
+ Matrice.create(
+ name: 'commentActivation',
+ enabled: false,
+ label: 'commentActivation',
+ include_ids: [],
+ exclude_ids: [],
+ configs: {}
+ )
+ end
+end
diff --git a/db/migrate/20230522075503_create_cellline_models.rb b/db/migrate/20230522075503_create_cellline_models.rb
new file mode 100644
index 0000000000..33c4907cc9
--- /dev/null
+++ b/db/migrate/20230522075503_create_cellline_models.rb
@@ -0,0 +1,46 @@
+class CreateCelllineModels < ActiveRecord::Migration[6.1]
+ def change
+ create_table :cellline_materials do |t|
+ t.string :name
+ t.string :source
+ t.string :cell_type
+ t.jsonb :organism
+ t.jsonb :tissue
+ t.jsonb :disease
+ t.string :growth_medium
+ t.string :biosafety_level
+ t.string :variant
+ t.string :mutation
+ t.float :optimal_growth_temp
+ t.string :cryo_pres_medium
+ t.string :gender
+ t.string :description
+ t.timestamp :deleted_at
+ t.timestamps
+ end
+
+ create_table :cellline_samples do |t|
+ t.bigint :cellline_material_id
+ t.bigint :cellline_sample_id
+ t.integer :amount, limit: 8
+ t.string :unit
+ t.integer :passage
+ t.string :contamination
+ t.string :name
+ t.string :description
+ t.bigint :user_id
+ t.timestamp :deleted_at
+ t.timestamps
+ t.string :short_label
+ end
+
+ create_table :collections_celllines do |t|
+ t.integer "collection_id"
+ t.integer "cellline_sample_id"
+ t.datetime "deleted_at"
+ end
+
+ add_column :collections, :celllinesample_detail_level, :int, :default => 10
+ add_column :sync_collections_users, :celllinesample_detail_level, :int, :default => 10
+ end
+end
diff --git a/db/migrate/20230531142756_add_samples_import_channel.rb b/db/migrate/20230531142756_add_samples_import_channel.rb
new file mode 100644
index 0000000000..9275e296bd
--- /dev/null
+++ b/db/migrate/20230531142756_add_samples_import_channel.rb
@@ -0,0 +1,11 @@
+class AddSamplesImportChannel < ActiveRecord::Migration[6.1]
+ def change
+ channel = Channel.find_or_create_by(subject: Channel::IMPORT_SAMPLES_NOTIFICATION)
+ attributes = {
+ subject: Channel::IMPORT_SAMPLES_NOTIFICATION,
+ channel_type: 8,
+ msg_template: JSON.parse('{"data": "%{message}", "action":"CollectionActions.fetchUnsharedCollectionRoots"}')
+ }
+ channel.update(attributes) if channel
+ end
+end
diff --git a/db/migrate/20230613063121_update_comment_channel.rb b/db/migrate/20230613063121_update_comment_channel.rb
new file mode 100644
index 0000000000..67705ba9e7
--- /dev/null
+++ b/db/migrate/20230613063121_update_comment_channel.rb
@@ -0,0 +1,23 @@
+class UpdateCommentChannel < ActiveRecord::Migration[6.1]
+ def change
+ channel = Channel.find_by(subject: Channel::COMMENT_ON_MY_COLLECTION)
+
+ attributes = {
+ msg_template:
+ JSON.parse('{"data": "%s has made a new comment on %s, %s",
+ "action":"CollectionActions.fetchSyncInCollectionRoots"}'),
+ }
+
+ channel.update(attributes) if channel
+
+ channel = Channel.find_by(subject: Channel::COMMENT_RESOLVED)
+ attributes = {
+ msg_template: JSON.parse('{
+ "data": "%s has marked your comment as resolved on %s, %s",
+ "action": "CollectionActions.fetchSyncInCollectionRoots"
+ }'),
+ }
+
+ channel.update(attributes) if channel
+ end
+end
diff --git a/db/migrate/20230630123412_add_additonal_plain_text_field_for_description_fields.rb b/db/migrate/20230630123412_add_additonal_plain_text_field_for_description_fields.rb
new file mode 100644
index 0000000000..f518ac2e91
--- /dev/null
+++ b/db/migrate/20230630123412_add_additonal_plain_text_field_for_description_fields.rb
@@ -0,0 +1,8 @@
+class AddAdditonalPlainTextFieldForDescriptionFields < ActiveRecord::Migration[6.1]
+ def change
+ add_column :reactions, :plain_text_description, :text
+ add_column :reactions, :plain_text_observation, :text
+ add_column :screens, :plain_text_description, :text
+ add_column :wellplates, :plain_text_description, :text
+ end
+end
diff --git a/db/migrate/20230630125148_cell_cline_data_migration.rb b/db/migrate/20230630125148_cell_cline_data_migration.rb
new file mode 100644
index 0000000000..e833557e7c
--- /dev/null
+++ b/db/migrate/20230630125148_cell_cline_data_migration.rb
@@ -0,0 +1,13 @@
+class CellClineDataMigration < ActiveRecord::Migration[6.1]
+ def up
+ User.all.each do |user|
+ user.counters['celllines']="0"
+ user.update_column(:counters, user.counters)
+ end
+
+ Profile.all.each do |profile|
+ profile.data['layout']['cell_line']=-1000 if profile.data['layout']
+ profile.save
+ end
+ end
+end
diff --git a/db/migrate/20230630140647_fill_new_plain_text_description_fields.rb b/db/migrate/20230630140647_fill_new_plain_text_description_fields.rb
new file mode 100644
index 0000000000..58b52ecbda
--- /dev/null
+++ b/db/migrate/20230630140647_fill_new_plain_text_description_fields.rb
@@ -0,0 +1,27 @@
+class FillNewPlainTextDescriptionFields < ActiveRecord::Migration[6.1]
+ def up
+ Reaction.where.not(description: nil).or(Reaction.where.not(observation: nil)).each do | reaction |
+ description = Chemotion::QuillToPlainText.new.convert(reaction.description)
+ observation = Chemotion::QuillToPlainText.new.convert(reaction.observation)
+ reaction.update_columns(plain_text_description: description, plain_text_observation: observation)
+ end
+ Screen.where.not(description: nil).each do | screen |
+ screen.update_columns(plain_text_description: Chemotion::QuillToPlainText.new.convert(screen.description))
+ end
+ Wellplate.where.not(description: nil).each do | wellplate |
+ wellplate.update_columns(plain_text_description: Chemotion::QuillToPlainText.new.convert(wellplate.description))
+ end
+ end
+
+ def down
+ Reaction.where.not(description: nil).or(Reaction.where.not(observation: nil)).each do | reaction |
+ reaction.update_columns(plain_text_description: nil, plain_text_observation: nil)
+ end
+ Screen.where.not(description: nil).each do | screen |
+ screen.update_columns(plain_text_description: nil)
+ end
+ Wellplate.where.not(description: nil).each do | wellplate |
+ wellplate.update_columns(plain_text_description: nil)
+ end
+ end
+end
diff --git a/db/migrate/20230714100005_add_generic_updated_by.rb b/db/migrate/20230714100005_add_generic_updated_by.rb
new file mode 100644
index 0000000000..194f09eb06
--- /dev/null
+++ b/db/migrate/20230714100005_add_generic_updated_by.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+# Add column identifier into segment_klasses
+class AddGenericUpdatedBy < ActiveRecord::Migration[6.1]
+ def self.up
+ add_column :segment_klasses, :updated_by, :integer unless column_exists? :segment_klasses, :updated_by
+ add_column :segment_klasses, :released_by, :integer unless column_exists? :segment_klasses, :released_by
+ add_column :segment_klasses, :sync_by, :integer unless column_exists? :segment_klasses, :sync_by
+ add_column :segment_klasses, :admin_ids, :jsonb, default: {} unless column_exists? :segment_klasses, :admin_ids
+ add_column :segment_klasses, :user_ids, :jsonb, default: {} unless column_exists? :segment_klasses, :user_ids
+ add_column :segment_klasses, :version, :string unless column_exists? :segment_klasses, :version
+ add_column :segment_klasses_revisions, :version, :string unless column_exists? :segment_klasses_revisions, :version
+ add_column :dataset_klasses, :updated_by, :integer unless column_exists? :dataset_klasses, :updated_by
+ add_column :dataset_klasses, :released_by, :integer unless column_exists? :dataset_klasses, :released_by
+ add_column :dataset_klasses, :sync_by, :integer unless column_exists? :dataset_klasses, :sync_by
+ add_column :dataset_klasses, :admin_ids, :jsonb, default: {} unless column_exists? :dataset_klasses, :admin_ids
+ add_column :dataset_klasses, :user_ids, :jsonb, default: {} unless column_exists? :dataset_klasses, :user_ids
+ add_column :dataset_klasses, :version, :string unless column_exists? :dataset_klasses, :version
+ add_column :dataset_klasses_revisions, :version, :string unless column_exists? :dataset_klasses_revisions, :version
+ add_column :element_klasses, :updated_by, :integer unless column_exists? :element_klasses, :updated_by
+ add_column :element_klasses, :released_by, :integer unless column_exists? :element_klasses, :released_by
+ add_column :element_klasses, :sync_by, :integer unless column_exists? :element_klasses, :sync_by
+ add_column :element_klasses, :admin_ids, :jsonb, default: {} unless column_exists? :element_klasses, :admin_ids
+ add_column :element_klasses, :user_ids, :jsonb, default: {} unless column_exists? :element_klasses, :user_ids
+ add_column :element_klasses, :version, :string unless column_exists? :element_klasses, :version
+ add_column :element_klasses_revisions, :version, :string unless column_exists? :element_klasses_revisions, :version
+ end
+
+ def self.down
+ remove_column :segment_klasses, :updated_by if column_exists? :segment_klasses, :updated_by
+ remove_column :segment_klasses, :released_by if column_exists? :segment_klasses, :released_by
+ remove_column :segment_klasses, :sync_by if column_exists? :segment_klasses, :sync_by
+ remove_column :segment_klasses, :admin_ids if column_exists? :segment_klasses, :admin_ids
+ remove_column :segment_klasses, :user_ids if column_exists? :segment_klasses, :user_ids
+ remove_column :segment_klasses, :version if column_exists? :segment_klasses, :version
+ remove_column :segment_klasses_revisions, :version if column_exists? :segment_klasses_revisions, :version
+ remove_column :dataset_klasses, :updated_by if column_exists? :dataset_klasses, :updated_by
+ remove_column :dataset_klasses, :released_by if column_exists? :dataset_klasses, :released_by
+ remove_column :dataset_klasses, :sync_by if column_exists? :dataset_klasses, :sync_by
+ remove_column :dataset_klasses, :admin_ids if column_exists? :dataset_klasses, :admin_ids
+ remove_column :dataset_klasses, :user_ids if column_exists? :dataset_klasses, :user_ids
+ remove_column :dataset_klasses, :version if column_exists? :dataset_klasses, :version
+ remove_column :dataset_klasses_revisions, :version if column_exists? :dataset_klasses_revisions, :version
+ remove_column :element_klasses, :updated_by if column_exists? :element_klasses, :updated_by
+ remove_column :element_klasses, :released_by if column_exists? :element_klasses, :released_by
+ remove_column :element_klasses, :sync_by if column_exists? :element_klasses, :sync_by
+ remove_column :element_klasses, :admin_ids if column_exists? :element_klasses, :admin_ids
+ remove_column :element_klasses, :user_ids if column_exists? :element_klasses, :user_ids
+ remove_column :element_klasses, :version if column_exists? :element_klasses, :version
+ remove_column :element_klasses_revisions, :version if column_exists? :element_klasses_revisions, :version
+
+ end
+end
diff --git a/db/migrate/20230804100000_att_com_state.rb b/db/migrate/20230804100000_att_com_state.rb
new file mode 100644
index 0000000000..8f6d4295e9
--- /dev/null
+++ b/db/migrate/20230804100000_att_com_state.rb
@@ -0,0 +1,9 @@
+class AttComState < ActiveRecord::Migration[6.1]
+ def self.up
+ add_column :attachments, :con_state, :integer unless column_exists? :attachments, :con_state
+ end
+
+ def self.down
+ remove_column :attachments, :con_state if column_exists? :attachments, :con_state
+ end
+end
diff --git a/db/migrate/20230810100000_labimotion_class.rb b/db/migrate/20230810100000_labimotion_class.rb
new file mode 100644
index 0000000000..17f3ebed6d
--- /dev/null
+++ b/db/migrate/20230810100000_labimotion_class.rb
@@ -0,0 +1,6 @@
+class LabimotionClass < ActiveRecord::Migration[6.1]
+ def change
+ Container.where(containable_type: 'Element').find_each { |c| c.update_column(:containable_type, 'Labimotion::Element') }
+ ElementTag.where(taggable_type: 'Element').find_each { |c| c.update_column(:taggable_type, 'Labimotion::Element') }
+ end
+end
diff --git a/db/migrate/20230814110512_add_plain_text_content_to_containers.rb b/db/migrate/20230814110512_add_plain_text_content_to_containers.rb
new file mode 100644
index 0000000000..f9a6efd7ad
--- /dev/null
+++ b/db/migrate/20230814110512_add_plain_text_content_to_containers.rb
@@ -0,0 +1,5 @@
+class AddPlainTextContentToContainers < ActiveRecord::Migration[6.1]
+ def change
+ add_column :containers, :plain_text_content, :text
+ end
+end
diff --git a/db/migrate/20230814121455_fill_new_plain_text_content_field_at_containers.rb b/db/migrate/20230814121455_fill_new_plain_text_content_field_at_containers.rb
new file mode 100644
index 0000000000..a86d013740
--- /dev/null
+++ b/db/migrate/20230814121455_fill_new_plain_text_content_field_at_containers.rb
@@ -0,0 +1,14 @@
+class FillNewPlainTextContentFieldAtContainers < ActiveRecord::Migration[6.1]
+ def up
+ Container.where(container_type: 'analysis').where('extended_metadata::TEXT LIKE ?', '%content%').each do | container |
+ content = Chemotion::QuillToPlainText.new.convert(container.extended_metadata['content'])
+ container.update_columns(plain_text_content: content)
+ end
+ end
+
+ def down
+ Container.where(container_type: 'analysis').where('extended_metadata::TEXT LIKE ?', '%content%').each do | container |
+ container.update_columns(plain_text_content: nil)
+ end
+ end
+end
diff --git a/db/migrate/20230927073354_create_vessel_templates.rb b/db/migrate/20230927073354_create_vessel_templates.rb
new file mode 100644
index 0000000000..6391be1f7f
--- /dev/null
+++ b/db/migrate/20230927073354_create_vessel_templates.rb
@@ -0,0 +1,16 @@
+class CreateVesselTemplates < ActiveRecord::Migration[6.1]
+ def change
+ create_table :vessel_templates, id: :uuid do |t|
+ t.string :name
+ t.string :details
+ t.string :material_details
+ t.string :material_type
+ t.string :vessel_type
+ t.integer :volume_amount
+ t.string :volume_unit
+
+ t.timestamps
+ t.datetime :deleted_at, index: true
+ end
+ end
+end
diff --git a/db/migrate/20230927073410_create_vessels.rb b/db/migrate/20230927073410_create_vessels.rb
new file mode 100644
index 0000000000..111a3f9030
--- /dev/null
+++ b/db/migrate/20230927073410_create_vessels.rb
@@ -0,0 +1,15 @@
+class CreateVessels < ActiveRecord::Migration[6.1]
+ def change
+ create_table :vessels, id: :uuid do |t|
+ t.belongs_to :vessel_template, type: :uuid, index: true
+ t.belongs_to :user, index: true
+
+ t.string :name
+ t.string :description
+ t.string :short_label
+
+ t.timestamps
+ t.datetime :deleted_at, index: true
+ end
+ end
+end
diff --git a/db/migrate/20230927073435_create_collections_vessels.rb b/db/migrate/20230927073435_create_collections_vessels.rb
new file mode 100644
index 0000000000..934fff931d
--- /dev/null
+++ b/db/migrate/20230927073435_create_collections_vessels.rb
@@ -0,0 +1,13 @@
+class CreateCollectionsVessels < ActiveRecord::Migration[6.1]
+ def change
+ create_table :collections_vessels, id: :uuid do |t|
+ t.belongs_to :collection, index: true
+ t.belongs_to :vessel, type: :uuid, index: true
+
+ t.timestamps
+ t.datetime :deleted_at, index: true
+
+ t.index %i[vessel_id collection_id], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20231106000000_cellline_element_init.rb b/db/migrate/20231106000000_cellline_element_init.rb
new file mode 100644
index 0000000000..82d28590c4
--- /dev/null
+++ b/db/migrate/20231106000000_cellline_element_init.rb
@@ -0,0 +1,10 @@
+class CelllineElementInit < ActiveRecord::Migration[6.1]
+ class ElementKlass < ActiveRecord::Base
+ end
+
+ def self.up
+ klass = ElementKlass.find_or_create_by(name: "cell_line")
+ attributes = { label: "cell_line".titleize, desc: "ELN #{"cell_line".titleize}", icon_name: "icon-#{"cell_line"}", klass_prefix: '', properties_template: {}, is_generic: false, place: 5 }
+ klass&.update(attributes)
+ end
+end
diff --git a/db/migrate/20231218191658_create_inventories.rb b/db/migrate/20231218191658_create_inventories.rb
new file mode 100644
index 0000000000..2136324449
--- /dev/null
+++ b/db/migrate/20231218191658_create_inventories.rb
@@ -0,0 +1,11 @@
+class CreateInventories < ActiveRecord::Migration[6.1]
+ def change
+ create_table :inventories do |t|
+ t.string :prefix, null: false
+ t.string :name, null: false
+ t.integer :counter, default: 0
+ t.timestamps
+ end
+ add_index :inventories, :prefix, unique: true
+ end
+end
\ No newline at end of file
diff --git a/db/migrate/20231218191929_add_inventories_to_collections.rb b/db/migrate/20231218191929_add_inventories_to_collections.rb
new file mode 100644
index 0000000000..79a179710a
--- /dev/null
+++ b/db/migrate/20231218191929_add_inventories_to_collections.rb
@@ -0,0 +1,5 @@
+class AddInventoriesToCollections < ActiveRecord::Migration[6.1]
+ def change
+ add_reference :collections, :inventory, foreign_key: true
+ end
+end
diff --git a/db/migrate/20231219151632_add_weight_to_vessel_templates.rb b/db/migrate/20231219151632_add_weight_to_vessel_templates.rb
new file mode 100644
index 0000000000..e612771a17
--- /dev/null
+++ b/db/migrate/20231219151632_add_weight_to_vessel_templates.rb
@@ -0,0 +1,6 @@
+class AddWeightToVesselTemplates < ActiveRecord::Migration[6.1]
+ def change
+ add_column :vessel_templates, :weight_amount, :float
+ add_column :vessel_templates, :weight_unit, :string
+ end
+end
diff --git a/db/migrate/20231219152154_add_bar_and_qr_code_to_vessels.rb b/db/migrate/20231219152154_add_bar_and_qr_code_to_vessels.rb
new file mode 100644
index 0000000000..90358f6027
--- /dev/null
+++ b/db/migrate/20231219152154_add_bar_and_qr_code_to_vessels.rb
@@ -0,0 +1,6 @@
+class AddBarAndQrCodeToVessels < ActiveRecord::Migration[6.1]
+ def change
+ add_column :vessels, :bar_code, :string
+ add_column :vessels, :qr_code, :string
+ end
+end
diff --git a/db/migrate/20231219162631_change_volume_amount_to_float_in_vessel_templates.rb b/db/migrate/20231219162631_change_volume_amount_to_float_in_vessel_templates.rb
new file mode 100644
index 0000000000..20018bcfa8
--- /dev/null
+++ b/db/migrate/20231219162631_change_volume_amount_to_float_in_vessel_templates.rb
@@ -0,0 +1,9 @@
+class ChangeVolumeAmountToFloatInVesselTemplates < ActiveRecord::Migration[6.1]
+ def up
+ change_column :vessel_templates, :volume_amount, :float
+ end
+
+ def down
+ change_column :vessel_templates, :volume_amount, :integer
+ end
+end
diff --git a/db/migrate/20240129134421_rename_inbox_folders.rb b/db/migrate/20240129134421_rename_inbox_folders.rb
new file mode 100644
index 0000000000..2c24238424
--- /dev/null
+++ b/db/migrate/20240129134421_rename_inbox_folders.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class RenameInboxFolders < ActiveRecord::Migration[6.1]
+ def change
+ Container.where("container_type ilike 'sender_%'")
+ .find_each do |inbox|
+ device_name = device_name_from_container(inbox)
+ next unless device_name
+
+ inbox.update_columns(name: device_name)
+ end
+ end
+
+ private
+
+ def device_id_from_container(container)
+ container.container_type.split('_').last.to_i
+ end
+
+ def device_name_from_container(container)
+ device_id = device_id_from_container(container)
+ Device.find(device_id)&.name
+ rescue ActiveRecord::RecordNotFound
+ nil
+ end
+end
diff --git a/db/reagent_seeds.json b/db/reagent_seeds.json
index 140f4b7122..fb2e97a06e 100644
--- a/db/reagent_seeds.json
+++ b/db/reagent_seeds.json
@@ -1796,6 +1796,7 @@
"Silver(I) Trifluoromethanethiolate": "[S-]C(F)(F)F.[Ag+]",
"Silver(II) picolinate": "O=C([O-])C1=NC=CC=C1.O=C([O-])C2=NC=CC=C2.[Ag+2]",
"Silver(II) Pyridine-2-carboxylate": "O=C(C1=NC=CC=C1)[O-].O=C(C2=NC=CC=C2)[O-].[Ag+2]",
+ "Sodium bicarbonate": "C(=O)(O)[O-].[Na+]",
"Sodium (Trihydroxy)phenylborate": "O[B-](O)(O)C1=CC=CC=C1.[Na+]",
"Sodium amide": "[Na+].[NH2-]",
"NaNH2": "[Na+].[NH2-]",
@@ -1992,6 +1993,7 @@
"Tetramethylammonium Sulfate": "C[N+](C)(C)C.C[N+](C)(C)C.O=S([O-])([O-])=O",
"Tetramethylammonium Tetrafluoroborate": "C[N+](C)(C)C.F[B-](F)(F)F",
"Tetramethylammonium Triacetoxyborohydride": "C[N+](C)(C)C.O=C(O[BH-](OC(C)=O)OC(C)=O)C",
+ "Tetramethylethylenediamine (TMEDA)": "CN(C)CCN(C)C",
"Tetramethylgermane": "C[Ge](C)(C)C",
"Tetramethylsilane": "C[Si](C)(C)C",
"TMS": "C[Si](C)(C)C",
diff --git a/db/schema.rb b/db/schema.rb
index b0cf93befb..749f22b55f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,11 +10,12 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2023_05_03_090936) do
+ActiveRecord::Schema.define(version: 2024_01_29_134421) do
# These are extensions that must be enabled in order to support this database
enable_extension "hstore"
enable_extension "pg_trgm"
+ enable_extension "pgcrypto"
enable_extension "plpgsql"
enable_extension "uuid-ossp"
@@ -70,6 +71,7 @@
t.string "aasm_state"
t.bigint "filesize"
t.jsonb "attachment_data"
+ t.integer "con_state"
t.index ["attachable_type", "attachable_id"], name: "index_attachments_on_attachable_type_and_attachable_id"
t.index ["identifier"], name: "index_attachments_on_identifier", unique: true
end
@@ -110,6 +112,42 @@
t.index ["user_id"], name: "index_calendar_entry_notifications_on_user_id"
end
+ create_table "cellline_materials", force: :cascade do |t|
+ t.string "name"
+ t.string "source"
+ t.string "cell_type"
+ t.jsonb "organism"
+ t.jsonb "tissue"
+ t.jsonb "disease"
+ t.string "growth_medium"
+ t.string "biosafety_level"
+ t.string "variant"
+ t.string "mutation"
+ t.float "optimal_growth_temp"
+ t.string "cryo_pres_medium"
+ t.string "gender"
+ t.string "description"
+ t.datetime "deleted_at"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ end
+
+ create_table "cellline_samples", force: :cascade do |t|
+ t.bigint "cellline_material_id"
+ t.bigint "cellline_sample_id"
+ t.bigint "amount"
+ t.string "unit"
+ t.integer "passage"
+ t.string "contamination"
+ t.string "name"
+ t.string "description"
+ t.bigint "user_id"
+ t.datetime "deleted_at"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.string "short_label"
+ end
+
create_table "channels", id: :serial, force: :cascade do |t|
t.string "subject"
t.jsonb "msg_template"
@@ -153,11 +191,21 @@
t.boolean "is_synchronized", default: false, null: false
t.integer "researchplan_detail_level", default: 10
t.integer "element_detail_level", default: 10
+ t.jsonb "tabs_segment", default: {}
+ t.integer "celllinesample_detail_level", default: 10
+ t.bigint "inventory_id"
t.index ["ancestry"], name: "index_collections_on_ancestry"
t.index ["deleted_at"], name: "index_collections_on_deleted_at"
+ t.index ["inventory_id"], name: "index_collections_on_inventory_id"
t.index ["user_id"], name: "index_collections_on_user_id"
end
+ create_table "collections_celllines", force: :cascade do |t|
+ t.integer "collection_id"
+ t.integer "cellline_sample_id"
+ t.datetime "deleted_at"
+ end
+
create_table "collections_elements", id: :serial, force: :cascade do |t|
t.integer "collection_id"
t.integer "element_id"
@@ -203,6 +251,18 @@
t.index ["screen_id", "collection_id"], name: "index_collections_screens_on_screen_id_and_collection_id", unique: true
end
+ create_table "collections_vessels", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.bigint "collection_id"
+ t.uuid "vessel_id"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.datetime "deleted_at"
+ t.index ["collection_id"], name: "index_collections_vessels_on_collection_id"
+ t.index ["deleted_at"], name: "index_collections_vessels_on_deleted_at"
+ t.index ["vessel_id", "collection_id"], name: "index_collections_vessels_on_vessel_id_and_collection_id", unique: true
+ t.index ["vessel_id"], name: "index_collections_vessels_on_vessel_id"
+ end
+
create_table "collections_wellplates", id: :serial, force: :cascade do |t|
t.integer "collection_id"
t.integer "wellplate_id"
@@ -218,6 +278,22 @@
t.datetime "updated_at", null: false
end
+ create_table "comments", force: :cascade do |t|
+ t.string "content"
+ t.integer "created_by", null: false
+ t.string "section"
+ t.string "status", default: "Pending"
+ t.string "submitter"
+ t.string "resolver_name"
+ t.integer "commentable_id"
+ t.string "commentable_type"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["commentable_type", "commentable_id"], name: "index_comments_on_commentable_type_and_commentable_id"
+ t.index ["created_by"], name: "index_comments_on_user"
+ t.index ["section"], name: "index_comments_on_section"
+ end
+
create_table "computed_props", id: :serial, force: :cascade do |t|
t.integer "molecule_id"
t.float "max_potential", default: 0.0
@@ -260,6 +336,7 @@
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "parent_id"
+ t.text "plain_text_content"
t.index ["containable_type", "containable_id"], name: "index_containers_on_containable"
end
@@ -277,6 +354,14 @@
t.string "uuid"
t.jsonb "properties_release", default: {}
t.datetime "released_at"
+ t.string "identifier"
+ t.datetime "sync_time"
+ t.integer "updated_by"
+ t.integer "released_by"
+ t.integer "sync_by"
+ t.jsonb "admin_ids", default: {}
+ t.jsonb "user_ids", default: {}
+ t.string "version"
end
create_table "dataset_klasses_revisions", id: :serial, force: :cascade do |t|
@@ -289,6 +374,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
+ t.string "version"
t.index ["dataset_klass_id"], name: "index_dataset_klasses_revisions_on_dataset_klass_id"
end
@@ -302,6 +388,7 @@
t.string "uuid"
t.string "klass_uuid"
t.datetime "deleted_at"
+ t.jsonb "properties_release"
end
create_table "datasets_revisions", id: :serial, force: :cascade do |t|
@@ -313,6 +400,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
+ t.jsonb "properties_release"
t.index ["dataset_id"], name: "index_datasets_revisions_on_dataset_id"
end
@@ -377,6 +465,14 @@
t.string "uuid"
t.jsonb "properties_release", default: {}
t.datetime "released_at"
+ t.string "identifier"
+ t.datetime "sync_time"
+ t.integer "updated_by"
+ t.integer "released_by"
+ t.integer "sync_by"
+ t.jsonb "admin_ids", default: {}
+ t.jsonb "user_ids", default: {}
+ t.string "version"
end
create_table "element_klasses_revisions", id: :serial, force: :cascade do |t|
@@ -389,6 +485,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
+ t.string "version"
t.index ["element_klass_id"], name: "index_element_klasses_revisions_on_element_klass_id"
end
@@ -422,6 +519,18 @@
t.datetime "deleted_at"
t.string "uuid"
t.string "klass_uuid"
+ t.jsonb "properties_release"
+ end
+
+ create_table "elements_elements", force: :cascade do |t|
+ t.integer "element_id"
+ t.integer "parent_id"
+ t.integer "created_by"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.datetime "deleted_at"
+ t.index ["element_id"], name: "index_elements_elements_on_element_id"
+ t.index ["parent_id"], name: "index_elements_elements_on_parent_id"
end
create_table "elements_revisions", id: :serial, force: :cascade do |t|
@@ -434,6 +543,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
+ t.jsonb "properties_release"
t.index ["element_id"], name: "index_elements_revisions_on_element_id"
end
@@ -488,6 +598,15 @@
t.time "deleted_at"
end
+ create_table "inventories", force: :cascade do |t|
+ t.string "prefix", null: false
+ t.string "name", null: false
+ t.integer "counter", default: 0
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.index ["prefix"], name: "index_inventories_on_prefix", unique: true
+ end
+
create_table "ketcherails_amino_acids", id: :serial, force: :cascade do |t|
t.integer "moderated_by"
t.integer "suggested_by"
@@ -804,9 +923,14 @@
t.string "duration"
t.string "rxno"
t.string "conditions"
+ t.jsonb "variations", default: []
+ t.text "plain_text_description"
+ t.text "plain_text_observation"
t.index ["deleted_at"], name: "index_reactions_on_deleted_at"
+ t.index ["rinchi_short_key"], name: "index_reactions_on_rinchi_short_key", order: :desc
t.index ["rinchi_web_key"], name: "index_reactions_on_rinchi_web_key"
t.index ["role"], name: "index_reactions_on_role"
+ t.index ["rxno"], name: "index_reactions_on_rxno", order: :desc
end
create_table "reactions_samples", id: :serial, force: :cascade do |t|
@@ -1006,6 +1130,7 @@
t.float "molecular_mass"
t.string "sum_formula"
t.jsonb "solvent"
+ t.boolean "dry_solvent", default: false
t.boolean "inventory_sample", default: false
t.index ["deleted_at"], name: "index_samples_on_deleted_at"
t.index ["identifier"], name: "index_samples_on_identifier"
@@ -1046,6 +1171,7 @@
t.datetime "updated_at", null: false
t.datetime "deleted_at"
t.jsonb "component_graph_data", default: {}
+ t.text "plain_text_description"
t.index ["deleted_at"], name: "index_screens_on_deleted_at"
end
@@ -1072,6 +1198,14 @@
t.string "uuid"
t.jsonb "properties_release", default: {}
t.datetime "released_at"
+ t.string "identifier"
+ t.datetime "sync_time"
+ t.integer "updated_by"
+ t.integer "released_by"
+ t.integer "sync_by"
+ t.jsonb "admin_ids", default: {}
+ t.jsonb "user_ids", default: {}
+ t.string "version"
end
create_table "segment_klasses_revisions", id: :serial, force: :cascade do |t|
@@ -1084,6 +1218,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
+ t.string "version"
t.index ["segment_klass_id"], name: "index_segment_klasses_revisions_on_segment_klass_id"
end
@@ -1098,6 +1233,7 @@
t.datetime "deleted_at"
t.string "uuid"
t.string "klass_uuid"
+ t.jsonb "properties_release"
end
create_table "segments_revisions", id: :serial, force: :cascade do |t|
@@ -1109,6 +1245,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "deleted_at"
+ t.jsonb "properties_release"
t.index ["segment_id"], name: "index_segments_revisions_on_segment_id"
end
@@ -1135,6 +1272,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.integer "element_detail_level", default: 10
+ t.integer "celllinesample_detail_level", default: 10
t.index ["collection_id"], name: "index_sync_collections_users_on_collection_id"
t.index ["shared_by_id", "user_id", "fake_ancestry"], name: "index_sync_collections_users_on_shared_by_id"
t.index ["user_id", "fake_ancestry"], name: "index_sync_collections_users_on_user_id_and_fake_ancestry"
@@ -1153,6 +1291,14 @@
t.index ["user_id"], name: "index_text_templates_on_user_id"
end
+ create_table "third_party_apps", force: :cascade do |t|
+ t.string "url"
+ t.string "name", limit: 100, null: false
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.index ["name"], name: "index_third_party_apps_on_name", unique: true
+ end
+
create_table "user_affiliations", id: :serial, force: :cascade do |t|
t.integer "user_id"
t.integer "affiliation_id"
@@ -1209,6 +1355,7 @@
t.boolean "account_active"
t.integer "matrix", default: 0
t.jsonb "providers"
+ t.jsonb "inventory_labels", default: {}
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["deleted_at"], name: "index_users_on_deleted_at"
t.index ["email"], name: "index_users_on_email", unique: true
@@ -1236,6 +1383,38 @@
t.index ["user_id"], name: "index_users_groups_on_user_id"
end
+ create_table "vessel_templates", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.string "name"
+ t.string "details"
+ t.string "material_details"
+ t.string "material_type"
+ t.string "vessel_type"
+ t.float "volume_amount"
+ t.string "volume_unit"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.datetime "deleted_at"
+ t.float "weight_amount"
+ t.string "weight_unit"
+ t.index ["deleted_at"], name: "index_vessel_templates_on_deleted_at"
+ end
+
+ create_table "vessels", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.uuid "vessel_template_id"
+ t.bigint "user_id"
+ t.string "name"
+ t.string "description"
+ t.string "short_label"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.datetime "deleted_at"
+ t.string "bar_code"
+ t.string "qr_code"
+ t.index ["deleted_at"], name: "index_vessels_on_deleted_at"
+ t.index ["user_id"], name: "index_vessels_on_user_id"
+ t.index ["vessel_template_id"], name: "index_vessels_on_vessel_template_id"
+ end
+
create_table "wellplates", id: :serial, force: :cascade do |t|
t.string "name"
t.integer "size"
@@ -1245,6 +1424,7 @@
t.datetime "deleted_at"
t.string "short_label"
t.jsonb "readout_titles", default: ["Readout"]
+ t.text "plain_text_description"
t.index ["deleted_at"], name: "index_wellplates_on_deleted_at"
end
@@ -1265,6 +1445,7 @@
t.index ["wellplate_id"], name: "index_wells_on_wellplate_id"
end
+ add_foreign_key "collections", "inventories"
add_foreign_key "literals", "literatures"
add_foreign_key "report_templates", "attachments"
add_foreign_key "sample_tasks", "samples"
@@ -1366,6 +1547,7 @@
)
and sync_cols.user_id in (select user_ids(in_user_id))
) all_cols;
+
return query select coalesce(i_detail_level_sample,0) detail_level_sample, coalesce(i_detail_level_wellplate,0) detail_level_wellplate;
end;$function$
SQL
@@ -1391,6 +1573,7 @@
begin
select channel_type into i_channel_type
from channels where id = in_channel_id;
+
case i_channel_type
when 9 then
insert into notifications (message_id, user_id, created_at,updated_at)
@@ -1468,6 +1651,7 @@
if (TG_OP='INSERT') then
PERFORM generate_users_matrix(null);
end if;
+
if (TG_OP='UPDATE') then
if new.enabled <> old.enabled or new.deleted_at <> new.deleted_at then
PERFORM generate_users_matrix(null);
@@ -1486,8 +1670,8 @@
RETURNS TABLE(literatures text)
LANGUAGE sql
AS $function$
- select string_agg(l2.id::text, ',') as literatures from literals l , literatures l2
- where l.literature_id = l2.id
+ select string_agg(l2.id::text, ',') as literatures from literals l , literatures l2
+ where l.literature_id = l2.id
and l.element_type = $1 and l.element_id = $2
$function$
SQL
diff --git a/db/seeds/development/vessels.seed.rb b/db/seeds/development/vessels.seed.rb
new file mode 100644
index 0000000000..edfb7aae88
--- /dev/null
+++ b/db/seeds/development/vessels.seed.rb
@@ -0,0 +1,188 @@
+# frozen_string_literal: true
+
+require 'faker'
+
+def create_vessels_and_vessel_templates
+ # source: https://www.obrnutafaza.hr/pdf/scilabware/
+ vessel_names = ['BRAND Petri dish',
+ 'Lids for wide neck flask',
+ 'Culture flask closures',
+ 'MBL pipette',
+ 'One mark class AS works certified pipette',
+ 'One mark class B pipette',
+ 'Two mark class B pipette',
+ 'Two mark class AS pipette',
+ 'Graduated type 1 class AS works certified pipette',
+ 'Graduated type 1 class AS pipette',
+ 'Graduated type 1 class B pipette',
+ 'Graduated type 2 class as works certified pipette',
+ 'Graduated type 2 class AS pipette',
+ 'Graduated type 2 class B pipette',
+ 'Graduated type 3 class B pipette',
+ 'Graduated serological type 4 class B pipette',
+ 'Graduated class B pipette',
+ 'Weighing pipette',
+ 'Dropping pipette',
+ 'Soxhlet extractor',
+ 'Large capacity soxhlet extractor',
+ 'Plain body extractor',
+ 'Soxhlet complete assemblies extractor',
+ 'Liquid-liquid heavy phase small capacity extractor',
+ 'liquid-liquid heavy phase large capacity extractor',
+ 'Paper thimbles extractor',
+ 'Round Bottom flask',
+ 'Narrow-neck flask',
+ 'Erlenmeyer flask',
+ 'Millipore Vacuum Filtering Side-Arm flask',
+ 'Baffled Erlenmeyer flask',
+ 'Large knob top desiccators',
+ 'Volumetric class A amber works certified DIN/ISO/USP tolerances flask',
+ 'Wide-mouth dewar flasks',
+ 'Test Tube',
+ 'Graduated Cylinder',
+ 'Desiccator',
+ 'Volumetric flask',
+ 'Conical narrow neck flask',
+ 'Conical wide neck flask',
+ 'Conical cylindrical flask',
+ 'Fernbach culture flask',
+ 'Conical graduated with ground socket flask',
+ 'Conical with ground socket flask',
+ 'Distillation flask',
+ 'Büchner plain side-arm flask',
+ 'Büchner with screwthread connector flask',
+ 'Büchner plain side-arm and ground socket flask',
+ 'Büchner with screwthread connector and ground socket flask',
+ 'Iodine flask',
+ 'Kjeldahl with plain neck flask',
+ 'Flat bottom short neck flask',
+ 'Flat bottom medium neck flask',
+ 'Florentine flask',
+ 'Pear shaped single neck flask',
+ 'Pear shaped two neck flask',
+ 'Pear shaped three neck flask',
+ 'Pear shaped distillation flask',
+ 'Pear shaped Claisen-Vigreux flask',
+ 'Round bottom short neck flask',
+ 'Round bottom medium neck flask',
+ 'Round bottom two neck flask',
+ 'Small capacity with septum side neck flask',
+ 'Round bottom three vertical necks flask',
+ 'Roux culture off-set neck flask',
+ 'Reaction wide neck flat flange flask',
+ 'Reaction jacketed flask',
+ 'Culture vessel flask',
+ 'Large beaker',
+ 'Corning® beaker',
+ 'Low form heavy duty beaker',
+ 'Tall form beaker',
+ 'Conical form beaker',
+ 'Jacketed beaker',
+ 'straight sided printed graduations beaker',
+ 'Tapered moulded graduations beaker',
+ 'Straight sided printed graduations PMP beaker',
+ 'Straight sided PTFE beaker',
+ 'Air condenser',
+ 'Allihn with ground cone condenser',
+ 'Allihn with ground cone and socket condenser',
+ 'Coil with ground cone condenser',
+ 'Coil with ground cone and socket condenser',
+ 'Coil reversible condenser',
+ 'Twin-coil condenser',
+ 'Multi-coil large scale condenser',
+ 'Jacketed coil condenser',
+ 'Cold finger condenser',
+ 'Double surface Davies condenser',
+ 'Ether condenser',
+ 'Inland Revenue condenser',
+ 'Liebig with ground cone and socket condenser',
+ 'With spout class A works certified cylinder',
+ 'With spout class A cylinder',
+ 'Blue graduations class B cylinder',
+ 'White graduations class B cylinder',
+ 'Tall form heavy duty rim class B cylinder',
+ 'Squat form heavy duty rim class B cylinder',
+ 'With plastic stopper and detachable foot class B complete cylinder',
+ 'With plastic stopper hexagonal foot blue graduations class B cylinder',
+ 'With glass stopper hexagonal foot white graduations class B cylinder',
+ 'Moulded graduations class B cylinder',
+ 'Printed graduations class A PMP (TPX) cylinder',
+ 'Printed graduations class B PMP (TPX) cylinder']
+
+ # All current ORD available materials
+ # https://github.com/open-reaction-database/ord-schema/blob/main/proto/reaction.proto#L452
+ vessel_materials = ['Glass',
+ 'Polypropylene',
+ 'Plastic',
+ 'Metal',
+ 'Quartz',
+ 'Brown Glass',
+ 'Pfa',
+ 'Ptfe',
+ 'Borosilicate Glass',
+ 'Polymethlypentene',
+ 'Polyethylene']
+
+ # All current ORD available ord_vessel_types
+ # https://github.com/open-reaction-database/ord-schema/blob/main/proto/reaction.proto#L414
+ ord_vessel_types = ['Round Bottom Flask',
+ 'Vial',
+ 'Well Plate',
+ 'Microwave Vial',
+ 'Tube',
+ 'Continuous Stirred Tank Reactor',
+ 'Packed Bed Reactor',
+ 'Nmr Tube',
+ 'Pressure Flask',
+ 'Pressure Reactor',
+ 'Electrochemical Cell',
+ 'Schlenk Flask',
+ 'Schlenk Tube',
+ 'Multineck Flask',
+ 'Coil',
+ 'Cuvette',
+ 'Beaker',
+ 'Erlenmeyer Flask']
+
+ small_vessel_sizes = [1, 5, 10, 20, 30, 35, 40, 45, 50, 60, 100]
+ large_vessel_sizes = [150, 200, 250, 300, 350, 400, 450, 500, 550, 1000, 2000, 10_000, 20_000, 30_000]
+
+ weight_amounts = [20, 50, 100, 150, 200, 500, 1000, 1500]
+
+ ActiveRecord::Base.transaction do
+ vessel_names.each_with_index do |vessel_name, index|
+ next if VesselTemplate.find_by(name: vessel_name)
+
+ User.where(type: 'Person').find_each do |person|
+ vessel_template = VesselTemplate.create!(
+ name: vessel_name,
+ details: Faker::Science.element_subcategory,
+ material_details: Faker::Science.tool,
+ material_type: vessel_materials.sample,
+ vessel_type: ord_vessel_types.sample,
+ volume_amount: index < 21 ? small_vessel_sizes.sample : large_vessel_sizes.sample,
+ volume_unit: 'ml',
+ weight_amount: weight_amounts.sample,
+ weight_unit: 'g'
+ )
+
+ description = "A #{vessel_template.vessel_type} with size " \
+ "#{vessel_template.volume_amount} #{vessel_template.volume_unit}."
+
+ vessel = Vessel.create!(
+ vessel_template: vessel_template,
+ name: Faker::Commerce.product_name,
+ user_id: person.id,
+ description: description,
+ bar_code: SecureRandom.hex(8),
+ qr_code: SecureRandom.hex(10),
+ short_label: "#{person.name_abbreviation}-#{Faker::Name.first_name}",
+ )
+
+ CollectionsVessel.create!(vessel: vessel, collection: person.collections.first) if person.collections.any?
+ end
+ end
+ end
+end
+
+create_vessels_and_vessel_templates
diff --git a/db/seeds/shared/admin.seed.rb b/db/seeds/shared/admin.seed.rb
index 522783b448..615564fef2 100644
--- a/db/seeds/shared/admin.seed.rb
+++ b/db/seeds/shared/admin.seed.rb
@@ -10,3 +10,5 @@
user = User.find_by(type: 'Admin', name_abbreviation: 'ADM') || User.create!(attributes)
user.update!(account_active: true)
user.update!(confirmed_at: DateTime.now)
+
+Admin.find_each(&:has_profile)
diff --git a/lib/analyses/converter.rb b/lib/analyses/converter.rb
deleted file mode 100644
index 7d7458be13..0000000000
--- a/lib/analyses/converter.rb
+++ /dev/null
@@ -1,295 +0,0 @@
-# frozen_string_literal: true
-
-require 'net/http'
-require 'uri'
-require 'json'
-require 'date'
-
-# rubocop: disable Metrics/AbcSize
-# rubocop: disable Metrics/MethodLength
-# rubocop: disable Metrics/ClassLength
-# rubocop: disable Metrics/CyclomaticComplexity
-
-module Analyses
- class Converter
- def self.logger
- @@converter_logger ||= Logger.new(Rails.root.join('log/converter.log')) # rubocop:disable Style/ClassVars
- end
-
- def self.uri(api_name)
- url = Rails.configuration.converter.url
- "#{url}#{api_name}"
- end
-
- def self.timeout
- Rails.configuration.try(:converter).try(:timeout) || 30
- end
-
- def self.extname
- '.jdx'
- end
-
- def self.client_id
- Rails.configuration.converter.profile || ''
- end
-
- def self.secret_key
- Rails.configuration.converter.secret_key || ''
- end
-
- def self.auth
- { username: client_id, password: secret_key }
- end
-
- def self.date_time
- DateTime.now.strftime('%Q')
- end
-
- def self.signature(jbody)
- md5 = Digest::MD5.new
- md5.update jbody
- mdhex = md5.hexdigest
- mdall = mdhex << secret_key
- @signature = Digest::SHA1.hexdigest mdall
- end
-
- def self.header(opt = {})
- opt || {}
- end
-
- def self.vor_conv(id)
- conf = Rails.configuration.try(:converter).try(:url)
- oa = Attachment.find(id)
- folder = Rails.root.join('tmp/uploads/converter')
- FileUtils.mkdir_p(folder)
- return nil if conf.nil? || oa.nil?
-
- { a: oa, f: folder }
- end
-
- def self.collect_metadata(zip_file)
- dsr = []
- ols = nil
- zip_file.each do |entry|
- next unless entry.name == 'metadata/converter.json'
-
- metadata = entry.get_input_stream.read.force_encoding('UTF-8')
- jdata = JSON.parse(metadata)
-
- ols = jdata['ols']
- matches = jdata['matches']
- matches&.each do |match|
- idf = match['identifier']
- idr = match['result']
- if idf&.class == Hash && idr&.class == Hash && !idf['outputLayer'].nil? && !idf['outputKey'].nil? && !idr['value'].nil? # rubocop:disable Layout/LineLength
- dsr.push(layer: idf['outputLayer'], field: idf['outputKey'], value: idr['value'])
- end
- end
- end
- { d: dsr, o: ols }
- end
-
- def self.handle_response(oat, response)
- dsr = []
- ols = nil
-
- begin
- tmp_file = Tempfile.new(encoding: 'ascii-8bit')
- tmp_file.write(response.parsed_response)
- tmp_file.rewind
-
- name = response&.headers && response&.headers['content-disposition']&.split('=')&.last
- filename = oat.filename
- name = "#{File.basename(filename, '.*')}.zip" if name.nil?
-
- att = Attachment.new(
- filename: name,
- file_path: tmp_file.path,
- ## content_type: file[:type],
- attachable_id: oat.attachable_id,
- attachable_type: 'Container',
- created_by: oat.created_by,
- created_for: oat.created_for,
- )
- # att.attachment_attacher.attach(tmp_file)
-
- if att.valid?
- # att.attachment_attacher.create_derivatives
- att.save!
- end
-
- Zip::File.open(tmp_file.path) do |zip_file|
- res = Analyses::Converter.collect_metadata(zip_file) if name.split('.')&.last == 'zip'
- ols = res[:o] unless res&.dig(:o).nil?
- dsr.push(res[:d]) unless res&.dig(:d).nil?
- end
- dsr.flatten!
- if dsr.length.positive? && name.split('.')&.last == 'zip'
- Analyses::Converter.ts('write', att.attachable_id, ols: ols, info: dsr)
- end
- rescue StandardError => e
- raise e
- ensure
- tmp_file&.close
- # tempfile&.unlink
- end
- end
-
- def self.process(data)
- response = nil
- begin
- ofile = Rails.root.join(data[:f], data[:a].filename)
- FileUtils.cp(data[:a].attachment_url, ofile)
- File.open(ofile, 'r') do |f|
- body = { file: f }
- response = HTTParty.post(
- uri('conversions'),
- basic_auth: auth,
- body: body,
- timeout: timeout,
- )
- end
- if response.ok?
- Analyses::Converter.handle_response(data[:a], response)
- else
- Analyses::Converter.logger.error ["Converter Response Error: id: [#{data[:a]&.id}], filename: [#{data[:a]&.filename}], response: #{response}"].join($INPUT_RECORD_SEPARATOR)
- end
- response
- rescue StandardError => e
- raise e
- ensure
- FileUtils.rm_f(ofile)
- end
- end
-
- def self.jcamp_converter(id)
- resp = nil
- begin
- data = Analyses::Converter.vor_conv(id)
- return if data.nil?
-
- resp = Analyses::Converter.process(data)
- resp&.success? ? 'done' : 'failure'
- rescue StandardError => e
- Analyses::Converter.logger.error ["jcamp_converter fail: #{id}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
- ensure
- resp&.success? ? 'done' : 'failure'
- end
- end
-
- def self.generate_ds(att_id)
- dsr_info = Analyses::Converter.fetch_dsr(att_id)
- begin
- return unless dsr_info && dsr_info[:info]&.length&.positive?
-
- dataset = Analyses::Converter.build_ds(att_id, dsr_info[:ols])
- Analyses::Converter.update_ds(dataset, dsr_info[:info])
- rescue StandardError => e
- Analyses::Converter.logger.error ["Att ID: #{att_id}, OLS: #{dsr_info[:ols]}", "DSR: #{dsr_info[:info]}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
- ensure
- Analyses::Converter.clean_dsr(att_id)
- end
- end
-
- def self.build_ds(att_id, ols)
- cds = Container.find_by(id: att_id)
- dataset = Dataset.find_by(element_type: 'Container', element_id: cds.id)
- return dataset unless dataset.nil?
-
- klass = DatasetKlass.find_by(ols_term_id: ols)
- return if klass.nil?
-
- uuid = SecureRandom.uuid
- props = klass.properties_release
- props['uuid'] = uuid
- props['eln'] = Chemotion::Application.config.version
- props['klass'] = 'Dataset'
- Dataset.create!(
- uuid: uuid,
- dataset_klass_id: klass.id,
- element_type: 'Container',
- element_id: cds.id,
- properties: props,
- # properties_release: klass.properties_release,
- klass_uuid: klass.uuid,
- )
- end
-
- def self.update_ds(dataset, dsr)
- layers = dataset.properties['layers'] || {}
- new_prop = dataset.properties
- dsr.each do |ds|
- layer = layers[ds[:layer]]
- fields = layer['fields'].select { |f| f['field'] == ds[:field] }
- fi = fields&.first
- idx = layer['fields'].find_index(fi)
- fi['value'] = ds[:value]
- new_prop['layers'][ds[:layer]]['fields'][idx] = fi
- end
- dataset.properties = new_prop
- dataset.save!
- end
-
- def self.ts(method, identifier, params = nil)
- Rails.cache.send(method, "#{Analyses::Converter.new.class.name}#{identifier}", params)
- end
-
- def self.fetch_dsr(att_id)
- Analyses::Converter.ts('read', att_id)
- end
-
- def self.clean_dsr(att_id)
- Analyses::Converter.ts('delete', att_id)
- end
-
- def self.fetch_options
- options = { basic_auth: auth, timeout: timeout }
- response = HTTParty.get(uri('options'), options)
- response.parsed_response if response.code == 200
- end
-
- def self.delete_profile(id)
- options = { basic_auth: auth, timeout: timeout }
- response = HTTParty.delete("#{uri('profiles')}/#{id}}", options)
- response.parsed_response if response.code == 200
- end
-
- def self.create_profile(data)
- options = { basic_auth: auth, timeout: timeout, body: data.to_json, headers: { 'Content-Type' => 'application/json' } }
- response = HTTParty.post(uri('profiles'), options)
- response.parsed_response if response.code == 201
- end
-
- def self.update_profile(data)
- options = { basic_auth: auth, timeout: timeout, body: data.to_json, headers: { 'Content-Type' => 'application/json' } }
- response = HTTParty.put("#{uri('profiles')}/#{data[:id]}", options)
- response.parsed_response if response.code == 200
- end
-
- def self.fetch_profiles
- options = { basic_auth: auth, timeout: timeout }
- response = HTTParty.get(uri('profiles'), options)
- response.parsed_response if response.code == 200
- end
-
- def self.create_tables(tmpfile)
- res = {}
- File.open(tmpfile.path, 'r') do |file|
- body = { file: file }
- response = HTTParty.post(
- uri('tables'),
- basic_auth: auth,
- body: body,
- timeout: timeout,
- )
- res = response.parsed_response
- end
- res
- end
- end
-end
-
-# rubocop: enable Metrics/AbcSize
-# rubocop: enable Metrics/MethodLength
-# rubocop: enable Metrics/ClassLength
-# rubocop: enable Metrics/CyclomaticComplexity
diff --git a/lib/chemotion/chemicals_service.rb b/lib/chemotion/chemicals_service.rb
index dd9084b849..54f5bde6fa 100644
--- a/lib/chemotion/chemicals_service.rb
+++ b/lib/chemotion/chemicals_service.rb
@@ -91,19 +91,22 @@ def self.health_section(product_number)
.children[1].children[1].children[1]
end
- def self.construct_h_statements(h_phrases)
- h_phrases_hash = JSON.parse(File.read('./public/json/hazardPhrases.json'))
+ def self.construct_h_statements(h_phrases, vendor = nil)
h_statements = {}
- h_phrases.each do |element|
+ h_phrases_hash = JSON.parse(File.read('./public/json/hazardPhrases.json'))
+
+ h_array = vendor == 'merck' ? h_phrases[1].split(/\s[+-]\s/) : h_phrases
+ h_array.each do |element|
h_phrases_hash.map { |k, v| k == element ? h_statements[k] = " #{v}" : nil }
end
h_statements
end
- def self.construct_p_statements(p_phrases)
- p_phrases_hash = JSON.parse(File.read('./public/json/precautionaryPhrases.json'))
+ def self.construct_p_statements(p_phrases, vendor = nil)
p_statements = {}
- p_phrases.each do |element|
+ p_phrases_hash = JSON.parse(File.read('./public/json/precautionaryPhrases.json'))
+ p_array = vendor == 'merck' ? p_phrases[2].split(/\s[+-]\s/) : p_phrases
+ p_array.each do |element|
p_phrases_hash.map { |k, v| k == element ? p_statements[k] = " #{v}" : nil }
end
p_statements
@@ -136,33 +139,14 @@ def self.safety_section(product_link)
.xpath("//*[contains(@class, '#{search_string}')]")
end
- def self.construct_h_statements_merck(safety_array)
- h_statements = {}
- h_array = safety_array[1].split(/\s[+-]\s/)
- h_phrases_hash = JSON.parse(File.read('./public/json/hazardPhrases.json'))
- h_array.each do |element|
- h_phrases_hash.map { |k, v| k == element ? h_statements[k] = " #{v}" : nil }
- end
- h_statements
- end
-
- def self.construct_p_statements_merck(safety_array)
- p_statements = {}
- p_phrases_hash = JSON.parse(File.read('./public/json/precautionaryPhrases.json'))
- p_array = safety_array[2].split(/\s[+-]\s/)
- p_array.each do |element|
- p_phrases_hash.map { |k, v| k == element ? p_statements[k] = " #{v}" : nil }
- end
- p_statements
- end
-
def self.safety_phrases_merck(product_link)
safety_section = safety_section(product_link)
safety_array = safety_section.children.reject { |i| i.text.empty? }.map(&:text)
pictograms = safety_array[0].split(',')
- { 'h_statements' => construct_h_statements_merck(safety_array),
- 'p_statements' => construct_p_statements_merck(safety_array),
- 'pictograms' => pictograms }
+ verified_pictograms = pictograms.select { |pictogram| pictograms_hash.value?(pictogram) }
+ { 'h_statements' => construct_h_statements(safety_array, 'merck'),
+ 'p_statements' => construct_p_statements(safety_array, 'merck'),
+ 'pictograms' => verified_pictograms }
rescue StandardError
'Could not find H and P phrases'
end
diff --git a/lib/chemotion/jcamp.rb b/lib/chemotion/jcamp.rb
index d4020be6c2..aee9e7e983 100644
--- a/lib/chemotion/jcamp.rb
+++ b/lib/chemotion/jcamp.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+# rubocop:disable Metrics/BlockLength
+
require 'net/http'
# Chemotion module
@@ -114,9 +116,22 @@ def self.build_body(
cyclic_volta: params[:cyclicvolta],
jcamp_idx: params[:curve_idx],
simulatenmr: params[:simulatenmr],
+ data_type_mapping: read_data_type_mapping,
+ axes_units: params[:axes_units],
+ detector: params[:detector],
}
end
+ def self.read_data_type_mapping
+ file_path = Rails.configuration.path_spectra_data_type
+ begin
+ return File.read(file_path) if File.exist?(file_path)
+ rescue Errno::EACCES
+ error!('read file error', 500)
+ end
+ ''
+ end
+
def self.stub_http(
file_path, mol_path, is_regen = false, params = {}
)
@@ -199,6 +214,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
@@ -403,3 +455,5 @@ def self.jcamp_from_nmrium(path)
end
end
end
+
+# rubocop:enable Metrics/BlockLength
diff --git a/lib/chemotion/meta_schmooze/meta_schmooze.rb b/lib/chemotion/meta_schmooze/meta_schmooze.rb
new file mode 100644
index 0000000000..6daca898f7
--- /dev/null
+++ b/lib/chemotion/meta_schmooze/meta_schmooze.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'schmooze'
+
+module Chemotion
+ class MetaSchmooze
+ attr_reader :schmooze_klass, :root, :env, :schmooze_methods, :schmooze_dependencies
+
+ def initialize(schmooze_methods: {}, schmooze_dependencies: {}, var: {}, root: __dir__, env: {})
+ @root = root
+ @env = env
+ @schmooze_methods = schmooze_methods
+ @schmooze_dependencies = schmooze_dependencies
+ compose_schmooze_class
+ compose_schmooze_methods(var)
+ end
+
+ # rubocop:disable Style/OptionalBooleanParameter
+ def execute(method, var = {}, recompose_all = false)
+ if recompose_all
+ compose_schmooze_methods(var)
+ elsif var.present?
+ var.each { |method_name, v| recompose_schmooze_method(method_name, v) }
+ end
+ schmooze_klass.new(root, env).send(method)
+ end
+ # rubocop:enable Style/OptionalBooleanParameter
+
+ def recompose_schmooze_method(method_name, var = nil)
+ script = schmooze_methods[method_name]
+ compose_schmooze_method(method_name, script, var)
+ end
+
+ def respond_to_missing?(method, include_private = false)
+ super
+ end
+
+ def method_missing(method_name, arg = nil)
+ var = {}
+ var[method_name] = arg
+ execute(method_name, var)
+ end
+
+ private
+
+ def compose_schmooze_class
+ @schmooze_klass = Class.new(Schmooze::Base) do
+ # dependencies schmooze_dependencies
+ end
+ @schmooze_klass.send(:dependencies, schmooze_dependencies)
+ end
+
+ def compose_schmooze_methods(var = {})
+ schmooze_methods.each do |method_name, script|
+ compose_schmooze_method(method_name, script, var[method_name])
+ end
+ end
+
+ def compose_schmooze_method(method_name, script, var = nil)
+ case script
+ when String
+ schmooze_klass.send(:method, method_name, script)
+ when Proc
+ schmooze_klass.send(:method, method_name, script[var])
+ end
+ end
+
+ def parse_input(delta_ops)
+ return '[]' if delta_ops.blank? || delta_ops == "{\"ops\":[{\"insert\":\"\"}]}"
+
+ delta_ops = JSON.parse delta_ops if delta_ops.is_a?(String)
+ delta_ops = case delta_ops.class.name
+ when 'Array'
+ delta_ops.to_json
+ when 'Hash', 'ActiveSupport::HashWithIndifferentAccess'
+ delta_ops.fetch('ops', []).to_json
+ else
+ '[]'
+ end
+ (delta_ops == "[{\"insert\":\"\"}]" && '[]') || delta_ops
+ end
+ end
+end
diff --git a/lib/chemotion/quill_to_html.rb b/lib/chemotion/quill_to_html.rb
index 54164a59b7..d02e5e6aa8 100644
--- a/lib/chemotion/quill_to_html.rb
+++ b/lib/chemotion/quill_to_html.rb
@@ -1,79 +1,19 @@
+# frozen_string_literal: true
+
require 'schmooze'
+require 'meta_schmooze'
module Chemotion
- class MetaSchmooze
- attr_reader :schmooze_klass, :root, :env, :schmooze_methods, :schmooze_dependencies
-
- def initialize(schmooze_methods: {}, schmooze_dependencies: {}, var: {}, root: __dir__, env: {})
- @root = root
- @env = env
- @schmooze_methods = schmooze_methods
- @schmooze_dependencies = schmooze_dependencies
- compose_schmooze_class
- compose_schmooze_methods(var)
- end
-
- def execute(method, var = {}, recompose_all = false)
- if recompose_all
- compose_schmooze_methods(var)
- elsif var.present?
- var.each { |method_name, v| recompose_schmooze_method(method_name, v) }
- end
- schmooze_klass.new(root, env).send(method)
- end
-
- def recompose_schmooze_method(method_name, var = nil)
- script = schmooze_methods[method_name]
- compose_schmooze_method(method_name, script, var)
- end
-
- def method_missing(method_name, arg = nil )
- var = {}
- var[method_name] = arg
- execute(method_name, var)
- end
-
- private
- def compose_schmooze_class
- @schmooze_klass = Class.new(Schmooze::Base) do
- # dependencies schmooze_dependencies
- end
- @schmooze_klass.send(:dependencies, schmooze_dependencies)
- end
-
- def compose_schmooze_methods(var = {})
- schmooze_methods.each do |method_name, script|
- compose_schmooze_method(method_name, script, var[method_name])
- end
- end
-
- def compose_schmooze_method(method_name, script, var = nil)
- if script.is_a?(String)
- schmooze_klass.send('method', method_name, script)
- elsif script.is_a?(Proc)
- schmooze_klass.send('method', method_name, script[var])
- end
- end
- end
-
class QuillToHtml < MetaSchmooze
def initialize(schmooze_methods: {}, schmooze_dependencies: {}, root: Rails.root.to_s, env: {}, var: {})
+ super
@root = root
@env = env
- @schmooze_dependencies = schmooze_dependencies.merge( delta: 'quill-delta-to-html')
+ @schmooze_dependencies = schmooze_dependencies.merge(delta: 'quill-delta-to-html')
@schmooze_methods = schmooze_methods.merge(
- convert: lambda_convert = -> (delta_ops = []) {
- delta_ops = JSON.parse delta_ops if delta_ops.is_a?(String)
- delta_ops = case delta_ops.class.name
- when 'Array'
- delta_ops.to_json
- when 'Hash'
- delta_ops.fetch('ops',[]).to_json
- else
- '[]'
- end
- return "function(){ var converter = new delta(#{delta_ops}, {}); return converter.convert(); } "
- }
+ convert: lambda { |delta_ops = []|
+ return "function(){ var converter = new delta(#{parse_input(delta_ops)}, {}); return converter.convert(); } "
+ },
)
compose_schmooze_class
compose_schmooze_methods(var)
diff --git a/lib/chemotion/quill_to_plain_text.rb b/lib/chemotion/quill_to_plain_text.rb
new file mode 100644
index 0000000000..00f3a9fc83
--- /dev/null
+++ b/lib/chemotion/quill_to_plain_text.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'schmooze'
+require 'meta_schmooze'
+
+module Chemotion
+ class QuillToPlainText < MetaSchmooze
+ def initialize(schmooze_methods: {}, schmooze_dependencies: {}, root: Rails.root.to_s, env: {}, var: {})
+ super
+ @root = root
+ @env = env
+ @schmooze_dependencies = schmooze_dependencies.merge(delta: 'quill-delta-to-plaintext')
+ @schmooze_methods = schmooze_methods.merge(
+ convert: lambda { |delta_ops = []|
+ "function(){ return delta(#{parse_input(delta_ops)}); } "
+ },
+ )
+ compose_schmooze_class
+ compose_schmooze_methods(var)
+ end
+ end
+end
diff --git a/lib/datacollector/collector_helper.rb b/lib/datacollector/collector_helper.rb
index c4a2a3e2d4..253f9109bf 100644
--- a/lib/datacollector/collector_helper.rb
+++ b/lib/datacollector/collector_helper.rb
@@ -1,20 +1,22 @@
+# frozen_string_literal: true
+
class CollectorHelper
attr_reader :sender, :sender_container, :recipient
def initialize(from, cc = nil)
- if from.is_a?(Device) && cc.is_a?(User)
+ if (from.is_a?(Device) && cc.is_a?(User)) || (from.is_a?(User) && from == cc)
@sender = from
@recipient = cc
prepare_containers
elsif cc
@sender = Device.find_by email: from
- @sender = Device.find_by email: from.downcase unless @sender
+ @sender ||= Device.find_by email: from.downcase
@recipient = User.find_by email: cc
- @recipient = User.find_by email: cc.downcase unless @recipient
+ @recipient ||= User.find_by email: cc.downcase
prepare_containers if @sender && @recipient
else
@sender = User.find_by email: from
- @sender = User.find_by email: from.downcase unless @sender
+ @sender ||= User.find_by email: from.downcase
@recipient = @sender
prepare_containers if @sender
end
@@ -26,19 +28,21 @@ def sender_recipient_known?
def prepare_new_dataset(subject)
return nil unless sender_recipient_known?
+
Container.create(
name: subject,
container_type: 'dataset',
- parent: @sender_container
+ parent: @sender_container,
)
end
def prepare_dataset(subject)
return nil unless sender_recipient_known?
+
Container.where(
name: subject,
container_type: 'dataset',
- parent: @sender_container
+ parent: @sender_container,
).first_or_create
end
@@ -65,14 +69,14 @@ def prepare_containers
unless @recipient.container
@recipient.container = Container.create(
name: 'inbox',
- container_type: 'root'
+ container_type: 'root',
)
end
- sender_box_id = 'sender_box_' + @sender.id.to_s
+ sender_box_id = "sender_box_#{@sender.id}"
@sender_container = Container.where(
- name: @sender.first_name,
+ name: @sender.name,
container_type: sender_box_id,
- parent_id: @recipient.container.id
+ parent_id: @recipient.container.id,
).first_or_create
end
end
diff --git a/lib/datacollector/collector_helper_set.rb b/lib/datacollector/collector_helper_set.rb
new file mode 100644
index 0000000000..0ffefc25fe
--- /dev/null
+++ b/lib/datacollector/collector_helper_set.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class CollectorHelperSet
+ attr_reader :helper_set
+
+ def initialize(from, cc_list)
+ @helper_set = []
+ cc_list.each do |cc|
+ h = CollectorHelper.new(from, cc)
+ @helper_set.push(h) if h.sender_recipient_known?
+ end
+ end
+
+ def sender_recipient_known?
+ @helper_set.length.positive?
+ end
+end
diff --git a/lib/datacollector/datacollector_file.rb b/lib/datacollector/datacollector_file.rb
index fc9795a0c0..d42075ae0e 100644
--- a/lib/datacollector/datacollector_file.rb
+++ b/lib/datacollector/datacollector_file.rb
@@ -19,7 +19,7 @@ def delete
def attach(device)
att = Attachment.new(
filename: @name,
- file_data: IO.binread(@path),
+ file_data: File.binread(@path),
content_type: MimeMagic.by_path(@name)&.type,
created_by: device.id,
created_for: recipient.id,
@@ -52,7 +52,7 @@ def attach_remote(device)
def add_attach_to_container(device, attach, _ = false)
helper = CollectorHelper.new(device, recipient)
- dataset = helper.prepare_dataset(Time.now.strftime('%Y-%m-%d'))
+ dataset = helper.prepare_dataset(Time.zone.now.strftime('%Y-%m-%d'))
attach.update!(attachable: dataset)
# add notifications
diff --git a/lib/datacollector/datacollector_folder.rb b/lib/datacollector/datacollector_folder.rb
index e9d973d2b4..bd45980918 100644
--- a/lib/datacollector/datacollector_folder.rb
+++ b/lib/datacollector/datacollector_folder.rb
@@ -47,7 +47,7 @@ def zip_files(tmpzip)
def register_new_data(device, tmpzip)
att = Attachment.new(
- filename: @name + '.zip',
+ filename: "#{@name}.zip",
created_by: device.id,
created_for: recipient.id,
content_type: 'application/zip',
diff --git a/lib/datacollector/dc_logger.rb b/lib/datacollector/dc_logger.rb
index b82ea9b02e..002546de9c 100644
--- a/lib/datacollector/dc_logger.rb
+++ b/lib/datacollector/dc_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DCLogger
def self.log
@@fw_logger ||= Logger.new("#{Rails.root}/log/datacollector.log")
diff --git a/lib/datacollector/fcollector.rb b/lib/datacollector/fcollector.rb
index 2c9c3ed671..1c774690b8 100644
--- a/lib/datacollector/fcollector.rb
+++ b/lib/datacollector/fcollector.rb
@@ -63,7 +63,7 @@ def execute(use_sftp)
inspect_folder(device)
@sftp = nil
end
- rescue => e
+ rescue StandardError => e
log_error("#{e.message} >>> #{device.info}\n#{e.backtrace.join('\n')}")
end
end
@@ -77,7 +77,7 @@ def execute(use_sftp)
private
def devices(use_sftp)
- sql = <<~SQL
+ sql = <<~SQL.squish
profiles."data"->>'method' = '#{self.class::FCOLL}watcher#{use_sftp ? 'sftp' : 'local'}'
SQL
Device.joins(:profile).where(sql).includes(:profile)
diff --git a/lib/datacollector/filecollector.rb b/lib/datacollector/filecollector.rb
index d64f41bbac..c9088530d9 100644
--- a/lib/datacollector/filecollector.rb
+++ b/lib/datacollector/filecollector.rb
@@ -7,7 +7,6 @@ class Filecollector < Fcollector
private
# rubocop:disable Metrics/AbcSize
- # rubocop:disable Metrics/MethodLength
def inspect_folder(device)
directory = device.profile.data['method_params']['dir']
@@ -15,7 +14,7 @@ def inspect_folder(device)
@current_collector = DatacollectorFile.new(new_file_p, @sftp)
error = CollectorError.find_by error_code: CollectorHelper.hash(
@current_collector.path,
- @sftp
+ @sftp,
)
begin
stored = false
@@ -31,10 +30,10 @@ def inspect_folder(device)
@current_collector.delete
log_info("Recipient unknown. File deleted! >>> #{device.info}")
end
- rescue => e
+ rescue StandardError => e
if stored
CollectorHelper.write_error(
- CollectorHelper.hash(@current_collector.path, @sftp)
+ CollectorHelper.hash(@current_collector.path, @sftp),
)
end
log_error("#{e.message} >>> #{device.info}\n#{e.backtrace.join('\n')}")
@@ -53,15 +52,13 @@ def new_files(monitored_folder_p)
File.join(monitored_folder_p, f.name)
end
else
- new_files_p = Dir.glob(File.join(monitored_folder_p, '*')).reject { |e|
+ new_files_p = Dir.glob(File.join(monitored_folder_p, '*')).reject do |e|
File.directory?(e)
- }
+ end
end
new_files_p.delete_if do |f|
f.end_with?('.filepart', '.part')
end
new_files_p
end
-
- # rubocop:enable Metrics/MethodLength
end
diff --git a/lib/datacollector/foldercollector.rb b/lib/datacollector/foldercollector.rb
index a9bcb1f35e..4c78cee117 100644
--- a/lib/datacollector/foldercollector.rb
+++ b/lib/datacollector/foldercollector.rb
@@ -9,22 +9,20 @@ class Foldercollector < Fcollector
private
def sleep_seconds(device)
- 30 || Rails.configuration.datacollectors.services &&
- (Rails.configuration.datacollectors.services.find { |e|
+ 30 || (Rails.configuration.datacollectors.services &&
+ (Rails.configuration.datacollectors.services.find do |e|
e[:name] == device.profile.data['method']
- } || {})[:watcher_sleep]
+ end || {})[:watcher_sleep])
end
def modification_time_diff(device, folder_p)
- time_now = Time.now
- time_diff =
- case device.profile.data['method']
- when 'folderwatcherlocal' then time_now - File.mtime(folder_p)
- when 'folderwatchersftp' then
- time_now - (Time.at @sftp.file.open(folder_p).stat.attributes[:mtime])
- else 30
- end
- time_diff
+ time_now = Time.zone.now
+ case device.profile.data['method']
+ when 'folderwatcherlocal' then time_now - File.mtime(folder_p)
+ when 'folderwatchersftp'
+ time_now - (Time.zone.at @sftp.file.open(folder_p).stat.attributes[:mtime])
+ else 30
+ end
end
# rubocop:disable Metrics/CyclomaticComplexity
@@ -45,7 +43,7 @@ def inspect_folder(device)
@current_collector.files = list_files
error = CollectorError.find_by error_code: CollectorHelper.hash(
@current_collector.path,
- @sftp
+ @sftp,
)
begin
stored = false
@@ -66,10 +64,10 @@ def inspect_folder(device)
@current_collector.delete
log_info("Recipient unknown. Folder deleted! >>> #{device.info}")
end
- rescue => e
+ rescue StandardError => e
if stored
CollectorHelper.write_error(
- CollectorHelper.hash(@current_collector.path, @sftp)
+ CollectorHelper.hash(@current_collector.path, @sftp),
)
end
log_error("#{e.message} >>> #{device.info}\n#{e.backtrace.join('\n')}")
@@ -89,9 +87,9 @@ def list_files
)
all_files.map!(&:name)
else
- all_files = Dir.entries(@current_collector.path).reject { |e|
+ all_files = Dir.entries(@current_collector.path).reject do |e|
File.directory?(File.join(@current_collector.path, e))
- }
+ end
end
all_files.delete_if do |f|
f.end_with?('..', '.', '.filepart', '.part')
@@ -106,9 +104,9 @@ def new_folders(monitored_folder_p)
)
new_folders_p.map! { |dir| File.join(monitored_folder_p, dir.name) }
else
- new_folders_p = Dir.glob(File.join(monitored_folder_p, '*')).select { |e|
+ new_folders_p = Dir.glob(File.join(monitored_folder_p, '*')).select do |e|
File.directory?(e)
- }
+ end
end
new_folders_p
end
diff --git a/lib/datacollector/mailcollector.rb b/lib/datacollector/mailcollector.rb
index 25ae8d9d9b..b6933c06b2 100644
--- a/lib/datacollector/mailcollector.rb
+++ b/lib/datacollector/mailcollector.rb
@@ -1,8 +1,9 @@
+# frozen_string_literal: true
+
require 'net/imap'
require 'mail'
class Mailcollector
-
def initialize
raise 'No datacollector configuration!' unless Rails.configuration.datacollectors
@@ -21,15 +22,17 @@ def execute
if response['name'] == 'OK'
log_info('Login...')
imap.select('INBOX')
- imap.search(['NOT', 'SEEN']).each do |message_id|
+ imap.search(%w[NOT SEEN]).each do |message_id|
handle_new_mail(message_id, imap)
+ rescue StandardError => e
+ log_error e.message
end
imap.close
else
- log_error('Cannot login ' + @server)
+ log_error("Cannot login #{@server}")
raise
end
- rescue => e
+ rescue StandardError => e
log_error 'mail collector execute error:'
log_error e.backtrace.join('\n')
raise
@@ -44,117 +47,107 @@ def handle_new_mail(message_id, imap)
envelope = imap.fetch(message_id, 'ENVELOPE')[0].attr['ENVELOPE']
raw_message = imap.fetch(message_id, 'RFC822').first.attr['RFC822']
message = Mail.read_from_string raw_message
- helper = create_helper(envelope)
- log_info 'Mail from ' + message.from.to_s
- unless helper
- log_info message.from.to_s + ' Email format incorrect or sender unknown!'
- return nil
- end
- unless helper.sender
- log_info message.from.to_s + ' Sender unknown!'
+ helper_set = create_helper_set(envelope)
+ log_info "Mail from #{message.from}"
+ unless helper_set
+ log_info "#{message.from} Email format incorrect or sender unknown!"
return nil
end
- unless helper.recipient
- log_info message.from.to_s + ' Recipient unknown!'
- return nil
- end
- if message.attachments
- handle_new_message(message, helper)
- log_info message.from.to_s + ' Data stored!'
- else
- log_info message.from.to_s + ' No data!'
+ helper_set.helper_set.each do |helper|
+ unless helper.sender
+ log_info "#{message.from} Sender unknown!"
+ return nil
+ end
+ unless helper.recipient
+ log_info "#{message.from} Recipient unknown!"
+ return nil
+ end
+ if message.attachments
+ handle_new_message(message, helper)
+ log_info "#{message.from} Data stored!"
+ else
+ log_info "#{message.from} No data!"
+ end
+ imap.store(message_id, '+FLAGS', [:Deleted])
+ log_info "#{message.from} Email processed!"
end
- imap.store(message_id, '+FLAGS', [:Deleted])
- log_info message.from.to_s + ' Email processed!'
- rescue => e
+ rescue StandardError => e
log_error 'Error on mailcollector handle_new_mail'
log_error e.backtrace.join('\n')
raise
end
def handle_new_message(message, helper)
- begin
- dataset = helper.prepare_new_dataset(message.subject)
- message.attachments.each do |attachment|
- tempfile = Tempfile.new('mail_attachment')
- tempfile.binmode
- tempfile.write(attachment.decoded)
- tempfile.rewind
- att = Attachment.new(
- filename: attachment.filename,
- created_by: helper.sender.id,
- created_for: helper.recipient.id,
- file_path: tempfile.path,
- )
+ dataset = helper.prepare_new_dataset(message.subject)
+ message.attachments.each do |attachment|
+ tempfile = Tempfile.new('mail_attachment')
+ tempfile.binmode
+ tempfile.write(attachment.decoded)
+ tempfile.rewind
+ att = Attachment.new(
+ filename: attachment.filename,
+ created_by: helper.sender.id,
+ created_for: helper.recipient.id,
+ file_path: tempfile.path,
+ )
- att.save!
- tempfile.close
- tempfile.unlink
- att.update!(attachable: dataset)
- end
- rescue => e
- log_error 'Error on mailcollector handle_new_message:'
- log_error e.backtrace.join('\n')
- raise
+ att.save!
+ tempfile.close
+ tempfile.unlink
+ att.update!(attachable: dataset)
end
+ rescue StandardError => e
+ log_error 'Error on mailcollector handle_new_message:'
+ log_error e.backtrace.join('\n')
+ raise
end
- def create_helper(envelope)
- helper = nil
- begin
- if (envelope.cc && envelope.cc.length == 1) && (envelope.to && envelope.to.length == 1)
- log_info 'Using CC method...'
- mail_to = envelope.to[0].mailbox.to_s + '@' + envelope.to[0].host.to_s
- if mail_to.casecmp(@mail_address).zero? ||
- (@aliases.any? { |s| s.casecmp(mail_to).zero? })
- helper = CollectorHelper.new(
- envelope.from[0].mailbox.to_s + '@' + envelope.from[0].host.to_s,
- envelope.cc[0].mailbox.to_s + '@' + envelope.cc[0].host.to_s
- )
- end
- elsif !envelope.cc && envelope.to && envelope.to.length == 2
- log_info 'Using To method...'
- mail_to_first = envelope.to[0].mailbox.to_s + '@' + envelope.to[0].host.to_s
- mail_to_second = envelope.to[1].mailbox.to_s + '@' + envelope.to[1].host.to_s
- if mail_to_first.casecmp(@mail_address).zero? ||
- (@aliases.any? { |s| s.casecmp(mail_to_first).zero? })
- helper = CollectorHelper.new(
- envelope.from[0].mailbox.to_s + '@' + envelope.from[0].host.to_s,
- mail_to_second
- )
- elsif mail_to_second.casecmp(@mail_address).zero? ||
- (@aliases.any? { |s| s.casecmp(mail_to_second).zero? })
- helper = CollectorHelper.new(
- envelope.from[0].mailbox.to_s + '@' + envelope.from[0].host.to_s,
- mail_to_first
- )
- end
- elsif !envelope.cc && envelope.to && envelope.to.length == 1
- log_info 'Using Sender = Recipient method...'
- mail_to = envelope.to[0].mailbox.to_s + '@' + envelope.to[0].host.to_s
- if mail_to.casecmp(@mail_address).zero? || (@aliases.any? { |s| s.casecmp(mail_to).zero? })
- helper = CollectorHelper.new(
- envelope.from[0].mailbox.to_s + '@' + envelope.from[0].host.to_s
- )
- end
- end
- rescue => e
- log_error 'Error on mailcollector create_helper:'
- log_error e.backtrace.join('\n')
- raise
+ def email_eln_email?(mail_to)
+ mail_to.casecmp(@mail_address).zero? ||
+ (@aliases.any? { |s| s.casecmp(mail_to).zero? })
+ end
+
+ def get_user(mail)
+ user = User.find_by email: mail
+ user ||= User.find_by email: mail.downcase
+ user
+ end
+
+ def create_helper_set(envelope)
+ # Check if from is User or Device
+ from = "#{envelope.from[0].mailbox}@#{envelope.from[0].host}"
+ from_user = get_user from
+ raise "#{from} not registered" if from_user.nil?
+
+ receiver = []
+ if from_user.is_a?(User) && (!from_user.is_a?(Device) && !from_user.is_a?(Admin))
+ receiver.push(from_user)
+ else # Concatenate all receiver (cc & to)
+ receiver.concat(envelope.cc) if envelope.cc
+ receiver.concat(envelope.to) if envelope.to
+ receiver = receiver.map { |m| "#{m.mailbox}@#{m.host}" }
+ .reject { |m| email_eln_email?(m) }
+ .map { |m| get_user(m) }
+ .select { |user| !user.nil? && !user.is_a?(Device) && !user.is_a?(Admin) }
end
- helper
+ return nil if receiver.empty?
+
+ CollectorHelperSet.new(from_user, receiver)
+ rescue StandardError => e
+ log_error 'Error on mailcollector create_helper:'
+ log_error e.backtrace.join('\n')
+ raise
end
def log_info(message)
- DCLogger.log.info(self.class.name) {
- ' >>> ' + message
- }
+ DCLogger.log.info(self.class.name) do
+ " >>> #{message}"
+ end
end
def log_error(message)
- DCLogger.log.error(self.class.name) {
- ' >>> ' + message
- }
+ DCLogger.log.error(self.class.name) do
+ " >>> #{message}"
+ end
end
end
diff --git a/lib/export/export_chemicals.rb b/lib/export/export_chemicals.rb
new file mode 100644
index 0000000000..8efd6514de
--- /dev/null
+++ b/lib/export/export_chemicals.rb
@@ -0,0 +1,176 @@
+# frozen_string_literal: true
+
+module Export
+ class ExportChemicals
+ CHEMICAL_FIELDS = %w[
+ chemical_sample_id cas status vendor order_number amount price person required_date
+ ordered_date required_by pictograms h_statements p_statements safety_sheet_link_merck
+ safety_sheet_link_thermofischer product_link_merck product_link_thermofischer
+ host_building host_room host_cabinet host_group owner borrowed_by current_building
+ current_room current_cabinet current_group disposal_info important_notes
+ ].freeze
+ MERCK_SDS_LINK = 'c."chemical_data"->0->\'merckProductInfo\'->\'sdsLink\''
+ ALFA_SDS_LINK = 'c."chemical_data"->0->\'alfaProductInfo\'->\'sdsLink\''
+ MERCK_PRODUCT_LINK = 'c."chemical_data"->0->\'merckProductInfo\'->\'productLink\''
+ ALFA_PRODUCT_LINK = 'c."chemical_data"->0->\'alfaProductInfo\'->\'productLink\''
+ SAFETY_SHEET_INFO = %w[safety_sheet_link product_link].freeze
+ CHEMICAL_QUERIES = {
+ status: ['c."chemical_data"->0->\'status\'', '"status"', nil],
+ vendor: ['c."chemical_data"->0->\'vendor\'', '"vendor"', nil],
+ person: ['c."chemical_data"->0->\'person\'', '"person"', nil],
+ price: ['c."chemical_data"->0->\'price\'', '"price"', nil],
+ amount: ['c."chemical_data"->0->\'amount\'', '"amount"', nil],
+ order_number: ['c."chemical_data"->0->\'order_number\'', '"order_number"', nil],
+ required_date: ['c."chemical_data"->0->\'required_date\'', '"required_date"', nil],
+ required_by: ['c."chemical_data"->0->\'required_by\'', '"required_by"', nil],
+ safety_sheet_link_merck: [MERCK_SDS_LINK, '"safety_sheet_link_merck"', nil],
+ safety_sheet_link_thermofischer: [ALFA_SDS_LINK, '"safety_sheet_link_thermofischer"', nil],
+ product_link_merck: [MERCK_PRODUCT_LINK, '"product_link_merck"', nil],
+ product_link_thermofischer: [ALFA_PRODUCT_LINK, '"product_link_thermofischer"', nil],
+ ordered_date: ['c."chemical_data"->0->\'ordered_date\'', '"ordered_date"', nil],
+ h_statements: ['c."chemical_data"->0->\'safetyPhrases\'->\'h_statements\'', '"h_statements"', nil],
+ p_statements: ['c."chemical_data"->0->\'safetyPhrases\'->\'p_statements\'', '"p_statements"', nil],
+ pictograms: ['c."chemical_data"->0->\'safetyPhrases\'->\'pictograms\'', '"pictograms"', nil],
+ host_building: ['c."chemical_data"->0->\'host_building\'', '"host_building"', nil],
+ host_room: ['c."chemical_data"->0->\'host_room\'', '"host_room"', nil],
+ host_cabinet: ['c."chemical_data"->0->\'host_cabinet\'', '"host_cabinet"', nil],
+ host_group: ['c."chemical_data"->0->\'host_group\'', '"host_group"', nil],
+ owner: ['c."chemical_data"->0->\'host_owner\'', '"owner"', nil],
+ current_building: ['c."chemical_data"->0->\'current_building\'', '"current_building"', nil],
+ current_room: ['c."chemical_data"->0->\'current_room\'', '"current_room"', nil],
+ current_cabinet: ['c."chemical_data"->0->\'current_cabinet\'', '"current_cabinet"', nil],
+ current_group: ['c."chemical_data"->0->\'current_group\'', '"current_group"', nil],
+ borrowed_by: ['c."chemical_data"->0->\'borrowed_by\'', '"borrowed_by"', nil],
+ disposal_info: ['c."chemical_data"->0->\'disposal_info\'', '"disposal_info"', nil],
+ important_notes: ['c."chemical_data"->0->\'important_notes\'', '"important_notes"', nil],
+ }.freeze
+
+ def self.build_chemical_column_query(selection, sel)
+ chemical_selections = []
+ sel[:chemicals].each do |col|
+ query = CHEMICAL_QUERIES[col.to_sym]
+ chemical_selections << ("#{query[2]} as #{query[1]}") if SAFETY_SHEET_INFO.include?(col)
+ chemical_selections << ("#{query[0]} as #{query[1]}")
+ end
+ gathered_selections = []
+ gathered_selections << selection
+ gathered_selections << chemical_selections
+ end
+
+ def self.format_chemical_results(result)
+ columns_index = { 'safety_sheet_link' => [], 'product_link' => [] }
+ result.columns.map.with_index do |column_name, index|
+ column_name, columns_index = construct_column_name(column_name, index, columns_index)
+ result.columns[index] = column_name # Replace the value in the array
+ end
+ format_chemical_results_row(result, columns_index)
+ end
+
+ def self.construct_column_name(column_name, index, columns_index)
+ format_chemical_column = ['p statements', 'h statements', 'amount', 'safety sheet link thermofischer',
+ 'safety sheet link merck', 'product link thermofischer', 'product link merck'].freeze
+ if column_name.is_a?(String) && CHEMICAL_FIELDS.include?(column_name)
+ column_name = column_name.tr('_', ' ')
+ construct_column_name_hash(columns_index, column_name, index) if format_chemical_column.include?(column_name)
+ else
+ column_name
+ end
+ [column_name, columns_index]
+ end
+
+ def self.construct_column_name_hash(columns_index, column_name, index)
+ case column_name
+ when 'p statements'
+ columns_index['p_statements'] = index
+ when 'h statements'
+ columns_index['h_statements'] = index
+ when 'amount'
+ columns_index['amount'] = index
+ when 'safety sheet link merck', 'safety sheet link thermofischer'
+ columns_index['safety_sheet_link'].push(index)
+ when 'product link merck', 'product link thermofischer'
+ columns_index['product_link'].push(index)
+ end
+ end
+
+ def self.format_chemical_results_row(result, columns_index)
+ indexes_to_delete = []
+ result.rows.map! do |row|
+ format_row(row, columns_index, indexes_to_delete)
+ end
+ return result if indexes_to_delete.empty?
+
+ merge_safety_sheets_columns_rows(result, indexes_to_delete, columns_index)
+ end
+
+ def self.format_row(row, columns_index, indexes_to_delete)
+ row.map.with_index do |value, index|
+ next value unless value.is_a?(String)
+
+ case index
+ when columns_index['p_statements'], columns_index['h_statements']
+ value = format_p_and_h_statements(value)
+ when columns_index['amount']
+ value = format_chemical_amount(value)
+ when columns_index['safety_sheet_link'][0]
+ value = format_link(value, row, columns_index['safety_sheet_link'][1], indexes_to_delete)
+ when columns_index['product_link'][0]
+ value = format_link(value, row, columns_index['product_link'][1], indexes_to_delete)
+ end
+ value.gsub(/[\[\]"]/, '')
+ end
+ end
+
+ def self.format_p_and_h_statements(value)
+ keys = JSON.parse(value).keys
+ keys.join('-')
+ end
+
+ def self.format_chemical_amount(value)
+ amount_value_unit = JSON.parse(value).values
+ sorted = amount_value_unit.sort_by { |element| [element.is_a?(Integer) || element.is_a?(Float) ? 0 : 1, element] }
+ sorted.join
+ end
+
+ def self.format_link(value, row, next_index, indexes_to_delete)
+ # binding.pry
+ if next_index && row[next_index].present?
+ value += "-#{row[next_index]}"
+ indexes_to_delete.push(next_index)
+ end
+ value
+ end
+
+ def self.merge_safety_sheets_columns_rows(result, indexes_to_delete, columns_index)
+ process_to_delete_indexes(result, indexes_to_delete)
+ process_merged_columns(result, columns_index) if indexes_to_delete.empty?
+ result
+ end
+
+ def self.process_to_delete_indexes(result, indexes_to_delete)
+ indexes_to_delete.sort.reverse_each do |index|
+ result.columns.delete_at(index)
+ result.rows.each { |row| row.delete_at(index) }
+ format_columns_name(result, index - 1)
+ end
+ end
+
+ def self.process_merged_columns(result, columns_index)
+ format_columns_name(result, columns_index['safety_sheet_link'][0], columns_index['product_link'][0])
+ delete_columns(result, columns_index['safety_sheet_link'][1], columns_index['product_link'][1])
+ end
+
+ def self.format_columns_name(result, *indexes)
+ indexes.sort.reverse_each do |index|
+ result.columns[index] = result.columns[index].sub(/\s+\S+\z/, '')
+ end
+ end
+
+ def self.delete_columns(result, *indexes)
+ indexes.sort.reverse_each do |index|
+ result.columns.delete_at(index)
+ result.rows.each { |row| row.delete_at(index) }
+ end
+ end
+ end
+end
diff --git a/lib/export/export_collections.rb b/lib/export/export_collections.rb
index 6cd5ab9590..411983562b 100644
--- a/lib/export/export_collections.rb
+++ b/lib/export/export_collections.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# rubocop: disable Metrics/ClassLength
+# rubocop: disable Metrics/ClassLength, Metrics/AbcSize, Performance/MethodObjectAsBlock
module Export
class ExportCollections
attr_accessor :file_path
@@ -12,12 +12,14 @@ def initialize(export_id, collection_ids, format = 'zip', nested = false, gate =
@nested = nested
@gt = gate
- @file_path = Rails.public_path.join( format, "#{export_id}.#{format}")
- @schema_file_path = Rails.public_path.join( 'json', 'schema.json')
+ @file_path = Rails.public_path.join(format, "#{export_id}.#{format}")
+ @schema_file_path = Rails.public_path.join('json', 'schema.json')
@data = {}
@uuids = {}
@attachments = []
+ @segments = []
+ @datasets = []
@images = []
end
@@ -30,7 +32,7 @@ def to_udm
builder.to_xml
end
- # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity
+ # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity
def to_file
case @format
when 'json'
@@ -99,9 +101,9 @@ def to_file
@file_path
end
end
- # rubocop:enable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity
+ # rubocop:enable Metrics/MethodLength,Metrics/CyclomaticComplexity
- def prepare_data
+ def prepare_data # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# get the collections from the database, in order of ancestry, but with empty ancestry first
collections = Collection.order(Arel.sql("NULLIF(ancestry, '') ASC NULLS FIRST")).find(@collection_ids)
# add decendants for nested collections
@@ -113,27 +115,75 @@ def prepare_data
collections += descendants
end
+ Labimotion::Export.fetch_element_klasses(&method(:fetch_many)) # rubocop:disable Performance/MethodObjectAsBlock
+ Labimotion::Export.fetch_segment_klasses(&method(:fetch_many)) # rubocop:disable Performance/MethodObjectAsBlock
+ Labimotion::Export.fetch_dataset_klasses(&method(:fetch_many)) # rubocop:disable Performance/MethodObjectAsBlock
# loop over all collections
collections.each do |collection|
# fetch collection
fetch_one(collection, {
- 'user_id' => 'User'
- })
-
+ 'user_id' => 'User',
+ })
fetch_samples collection
+ fetch_chemicals collection
fetch_reactions collection
- fetch_wellplates collection unless @gt == false
- fetch_screens collection unless @gt == false
- fetch_research_plans collection unless @gt == false
+ # fetch_elements collection if @gt == false
+ fetch_wellplates collection if @gt == false
+ fetch_screens collection if @gt == false
+ fetch_research_plans collection if @gt == false
+ add_cell_line_material_to_package collection if @gt == false
+ add_cell_line_sample_to_package collection if @gt == false
end
end
private
+ def add_cell_line_material_to_package(collection)
+ type = 'CelllineMaterial'
+ collection.cellline_samples.each do |sample|
+ material = sample.cellline_material
+ next if uuid?(type, material.id)
+
+ uuid = uuid(type, material.id)
+ @data[type] = {} unless @data[type]
+ @data[type][uuid] = material.as_json
+ end
+ end
+
+ def add_cell_line_sample_to_package(collection)
+ type = 'CelllineSample'
+ collection.cellline_samples.each do |sample|
+ next if uuid?(type, sample.id)
+
+ uuid = uuid(type, sample.id)
+ @data[type] = {} unless @data[type]
+ @data[type][uuid] = sample.as_json
+ fetch_containers(sample)
+ @data['CollectionsCelllineSample'] = {} unless @data['CollectionsCelllineSample']
+ @data['CollectionsCelllineSample'][SecureRandom.uuid] = {
+ collection_id: @uuids['Collection'][collection.id],
+ cellline_sample_id: @uuids[type][sample.id],
+ }
+
+ @data['CelllineMaterialCelllineSample'] = {} unless @data['CelllineMaterialCelllineSample']
+ @data['CelllineMaterialCelllineSample'][SecureRandom.uuid] = {
+ cellline_material_id: @uuids['CelllineMaterial'][sample.cellline_material.id],
+ cellline_sample_id: @uuids[type][sample.id],
+ }
+ end
+ end
+
+ def fetch_chemicals(collection)
+ chemicals = collection.samples.filter_map(&:chemical)
+ fetch_many(chemicals, {
+ 'id' => 'Chemical',
+ 'sample_id' => 'Sample',
+ })
+ end
+
def fetch_samples(collection)
# get samples in order of ancestry, but with empty ancestry first
samples = collection.samples.order(Arel.sql("NULLIF(ancestry, '') ASC NULLS FIRST"))
-
# fetch samples
fetch_many(samples, {
'molecule_name_id' => 'MoleculeName',
@@ -141,11 +191,11 @@ def fetch_samples(collection)
'fingerprint_id' => 'Fingerprint',
'created_by' => 'User',
'user_id' => 'User',
- })
+ })
fetch_many(collection.collections_samples, {
'collection_id' => 'Collection',
'sample_id' => 'Sample',
- })
+ })
# loop over samples and fetch sample properties
samples.each do |sample|
@@ -154,10 +204,13 @@ def fetch_samples(collection)
fetch_one(sample.molecule_name, {
'molecule_id' => 'Molecule',
'user_id' => 'User',
- })
+ })
fetch_many(sample.residues, {
'sample_id' => 'Sample',
- })
+ })
+
+ segment, @attachments = Labimotion::Export.fetch_segments(sample, @attachments, &method(:fetch_one))
+ @segments += segment if segment.present?
# fetch containers, attachments and literature
fetch_containers(sample)
@@ -195,6 +248,9 @@ def fetch_reactions(collection)
})
end
+ segment, @attachments = Labimotion::Export.fetch_segments(reaction, @attachments, &method(:fetch_one))
+ @segments += segment if segment.present?
+
# fetch containers, attachments and literature
fetch_containers(reaction)
fetch_literals(reaction)
@@ -204,6 +260,12 @@ def fetch_reactions(collection)
end
end
+ def fetch_elements(collection)
+ @segments, @attachments = Labimotion::Export.fetch_elements(collection, @segments, @attachments,
+ method(:fetch_many), method(:fetch_one),
+ method(:fetch_containers))
+ end
+
def fetch_wellplates(collection)
fetch_many(collection.wellplates)
fetch_many(collection.collections_wellplates, {
@@ -218,6 +280,9 @@ def fetch_wellplates(collection)
'wellplate_id' => 'Wellplate',
})
+ segment, @attachments = Labimotion::Export.fetch_segments(wellplate, @attachments, &method(:fetch_one))
+ @segments += segment if segment.present?
+
fetch_containers(wellplate)
end
end
@@ -237,6 +302,14 @@ def fetch_screens(collection)
'wellplate_id' => 'Wellplate',
})
+ fetch_many(screen.research_plans_screens, {
+ 'screen_id' => 'Screen',
+ 'research_plan_id' => 'ResearchPlan',
+ })
+
+ segment, @attachments = Labimotion::Export.fetch_segments(screen, @attachments, &method(:fetch_one))
+ @segments += segment if segment.present?
+
# fetch containers and attachments
fetch_containers(screen)
end
@@ -260,6 +333,8 @@ def fetch_research_plans(collection)
'created_by' => 'User',
'created_for' => 'User',
})
+ segment, @attachments = Labimotion::Export.fetch_segments(research_plan, @attachments, &method(:fetch_one))
+ @segments += segment if segment.present?
# add attachments to the list of attachments
@attachments += research_plan.attachments
@@ -277,7 +352,6 @@ def fetch_research_plans(collection)
# rubocop:disable Metrics/MethodLength
def fetch_containers(containable)
containable_type = containable.class.name
-
# fetch root container
root_container = containable.container
fetch_one(containable.container, {
@@ -285,9 +359,9 @@ def fetch_containers(containable)
'parent_id' => 'Container',
})
- unless root_container.nil?
+ unless root_container.nil? # rubocop:disable Style/GuardClause
# fetch analyses container
- analyses_container = root_container.children.where("container_type = 'analyses'").first()
+ analyses_container = root_container.children.where("container_type = 'analyses'").first
fetch_one(analyses_container, {
'containable_id' => containable_type,
'parent_id' => 'Container',
@@ -295,6 +369,7 @@ def fetch_containers(containable)
# fetch analysis_containers
analysis_containers = analyses_container.children.where("container_type = 'analysis'")
+
analysis_containers.each do |analysis_container|
fetch_one(analysis_container, {
'containable_id' => containable_type,
@@ -308,6 +383,10 @@ def fetch_containers(containable)
'containable_id' => containable_type,
'parent_id' => 'Container',
})
+ if attachment_container.dataset.present?
+ @datasets += Labimotion::Export.fetch_datasets(attachment_container.dataset,
+ &method(:fetch_one))
+ end
fetch_many(attachment_container.attachments, {
'attachable_id' => 'Container',
'created_by' => 'User',
@@ -343,7 +422,7 @@ def fetch_many(instances, foreign_keys = {})
end
end
- # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
+ # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
def fetch_one(instance, foreign_keys = {})
return if instance.nil?
@@ -362,7 +441,6 @@ def fetch_one(instance, foreign_keys = {})
# append updated json to @data
@data[type] = {} unless @data.key?(type)
-
# replace ids in the ancestry field
if instance.respond_to?(:ancestry)
ancestor_uuids = []
@@ -381,7 +459,6 @@ def fetch_one(instance, foreign_keys = {})
end
uuid
end
- # rubocop:enable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
def fetch_image(image_path, image_file_name)
return if image_file_name.blank?
@@ -407,5 +484,5 @@ def uuid?(type, id)
end
end
-# rubocop: enable Metrics/ClassLength
-#
+# rubocop: enable Metrics/ClassLength, Performance/MethodObjectAsBlock
+# rubocop:enable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
diff --git a/lib/export/export_excel.rb b/lib/export/export_excel.rb
index 41fe90bc20..49f23536b4 100644
--- a/lib/export/export_excel.rb
+++ b/lib/export/export_excel.rb
@@ -11,11 +11,11 @@ def initialize(**args)
@xfile.workbook.styles.fonts.first.name = 'Calibri'
end
- def generate_sheet_with_samples(table, samples = nil)
+ def generate_sheet_with_samples(table, samples = nil, selected_columns = nil)
@samples = samples
return if samples.nil? # || samples.count.zero?
- generate_headers(table)
+ generate_headers(table, [], selected_columns)
sheet = @xfile.workbook.add_worksheet(name: table.to_s) # do |sheet|
grey = sheet.styles.add_style(sz: 12, border: { style: :thick, color: 'FF777777', edges: [:bottom] })
sheet.add_row(@headers, style: grey) # Add header
@@ -39,7 +39,7 @@ def generate_sheet_with_samples(table, samples = nil)
image_width = row_image_width if row_image_width > image_width
# 3/4 -> The misterious ratio!
if filtered_sample[decouple_idx].present?
- filtered_sample[decouple_idx] = filtered_sample[decouple_idx].presence == 't' ? 'Yes' : 'No'
+ filtered_sample[decouple_idx] = filtered_sample[decouple_idx].presence == true ? 'yes' : 'No'
end
size = sheet.styles.add_style :sz => 12
@@ -112,9 +112,9 @@ def literatures_info(ids)
output = output.join("\n")
output
end
-
+
def filter_with_permission_and_detail_level(sample)
- # return all data if sample in own collection
+ # return all data if sample/chemical in own collection
if sample['shared_sync'] == 'f' || sample['shared_sync'] == false
headers = @headers
reference_values = ['melting pt', 'boiling pt']
@@ -125,6 +125,8 @@ def filter_with_permission_and_detail_level(sample)
regex = /[\[\]()]/
string = sample[column].gsub(regex, '')
string.split(',').join(' - ')
+ elsif column == 'solvent'
+ extract_label_from_solvent_column(sample[column]) || ''
else
sample[column]
end
@@ -141,7 +143,6 @@ def filter_with_permission_and_detail_level(sample)
data = headers.map { |column| column ? sample[column] : nil }
data[@image_index] = svg_path(sample) if headers.include?('image')
end
-
data
end
diff --git a/lib/export/export_json.rb b/lib/export/export_json.rb
deleted file mode 100644
index f22f641544..0000000000
--- a/lib/export/export_json.rb
+++ /dev/null
@@ -1,264 +0,0 @@
-module Export
- class ExportJson
- attr_accessor :collection_id, :sample_ids, :reaction_ids, :research_plan_ids
- attr_reader :data
-
- def initialize(**args)
- @collection_id = args[:collection_id]
- @sample_ids = [args[:sample_ids]].flatten.compact.uniq || []
- @reaction_ids = [args[:reaction_ids]].flatten.compact.uniq || []
- @research_plan_ids = [args[:research_plan_ids]].flatten.compact.uniq || []
- s_ids = ReactionsSample.where(reaction_id: reaction_ids).pluck(:sample_id).compact
- @sample_ids = @sample_ids | s_ids unless s_ids.empty?
- # FIXME: find a better way to bypass reaction query if only sample ids given
- if @sample_ids.present? && @reaction_ids.blank?
- @reaction_ids = [0]
- end
- @data = { 'reactions' => {}, 'samples' => {}, 'analysis' => {}, 'research_plans' => {} }
- end
-
- def export
- query
- prepare_data
- self
- end
-
- def to_json
- @data.to_json(:include => { :research_plan_metadata => {}, :analyses => {} })
- end
-
- def to_file(file_name)
- file_name += '.json' if File.extname(file_name) != '.json'
- File.write(file_name, to_json)
- end
-
- #private
- def query
- @data['reactions'] = db_exec_query(reaction_sql)
- @data['samples'] = db_exec_query(sample_sql)
- @data['research_plans'] = query_research_plans
- @data['analyses'] = {}
- @data['reaction_analyses'] = db_exec_query(analyses_sql('reaction'))
- @data['sample_analyses'] = db_exec_query(analyses_sql('sample'))
- @data['attachments'] = db_exec_query(attachments_sql)
- @data
- end
-
- def prepare_data
- reactions_data
- samples_data
- research_plans_data
- analyses_data('reaction')
- analyses_data('sample')
- attachments_data
- end
-
- def attachments_data
- @data['attachments'] = JSON.parse(@data['attachments'][0]['ids'] || '[]')
- end
-
- def analyses_data(type)
- a = @data[type + '_analyses'][0].delete(type + '_analyses') || '{}'
- @data['analyses'].merge!(JSON.parse a)
- end
-
- def samples_data
- @data['samples'] = JSON.parse(@data['samples'][0]['samples'] || '{}')
- @data['samples'].each_value do |el|
- # [
- # 'reaction_sample',
- # 'residues_attributes',
- # 'elemental_compositions_attributes'
- # ].each do |column|
- # el[column] = el[column] && JSON.parse(el[column])
- # end
- svg_file = if !el['sample_svg_file'].blank?
- File.join('samples', el['sample_svg_file'])
- elsif !el['molecule_svg_file'].blank?
- File.join('molecules', el['molecule_svg_file'])
- end
- svg_path = svg_file && Rails.root.join(
- 'public', 'images', svg_file
- )
- svg = File.read(svg_path) if File.exist?(svg_path)
- el['sample_svg_file'] = svg || nil
- end
- end
-
- def reactions_data
- @data['reactions'] = JSON.parse(@data['reactions'][0]['reactions'] || '{}')
- @data['reactions'].each_value do |el|
- %w(description observation).each do |column|
- el[column] = JSON.parse(YAML.load(el[column]).to_json) if el[column]
- end
- svg_file = if !el['reaction_svg_file'].blank?
- File.join('reactions', el['reaction_svg_file'])
- end
- svg_path = svg_file && Rails.root.join(
- 'public', 'images', svg_file
- )
- svg = File.read(svg_path) if File.exist?(svg_path)
- el['reaction_svg_file'] = svg || nil
- # %w(dangerous_products purification).each do |column|
- # el[column] = JSON.parse(el[column]) if el[column]
- # end
- end
- end
-
- def research_plans_data
- @data['research_plans'] = {}.tap do |r|
- @data['research_plans'].each { |rp| r[SecureRandom.uuid] = rp }
- end
- end
-
- def db_exec_query(sql)
- ActiveRecord::Base.connection.exec_query(sql)
- end
-
- def ids_sql(arr, t, c = 'id')
- return nil if arr.blank?
- " and #{t}.#{c} in (#{arr.join(',')})"
- end
-
- def c_id
- @collection_id
- end
-
- def reaction_sql
- <<~SQL
- select json_object_agg(dump.uuid, row_to_json(dump)) as reactions from(
- select r."name", r.reaction_svg_file, r.created_at, r.updated_at, r.description, r."role"
- , r.timestamp_start, r.timestamp_stop, r.observation
- , array_to_json(r.purification) as purification
- , array_to_json(r.dangerous_products) as dangerous_products
- , r.conditions
- , r.tlc_solvents, r.tlc_description
- , r.rf_value, r.temperature, r.status, r.solvent, r.short_label
- , r.duration, r.rxno
- --, r.created_by, r.reaction_svg_file, r.deleted_at
- , cl.id as uuid, clo.id as origin_uuid --, r.origin
- ,(select array_to_json(array_agg(row_to_json(lis))) as lls from (
- select lh.element_type,lh.element_id,lh.category,lh.litype,ld.title,ld.url,ld.refs,ld.doi
- from literals lh, literatures ld where lh.literature_id = ld.id
- and lh.element_id = r.id and lh.element_type = 'Reaction'
- ) as lis) as literatures
- from reactions r
- inner join collections_reactions cr on cr.reaction_id = r.id and cr.deleted_at isnull
- inner join code_logs cl on cl."source" = 'reaction' and cl.source_id = r.id
- left join code_logs clo on cl."source" = 'reaction' and clo.source_id = (r.origin->>'id')::int
- where cr.collection_id = #{c_id} #{ids_sql(reaction_ids, 'r')}) dump;
- SQL
- end
-
- def sample_sql
- <<~SQL
- select json_object_agg(dump.uuid, row_to_json(dump)) as samples from(
- select
- -- , s.ancestry, s.user_id, s.created_by, s.molfile, s.molecule_id
- -- ,s.xref,s.fingerprint_id, s.deleted_at
- s.id, s."name", encode(s.molfile,'escape') as molfile
- , s.target_amount_value, s.target_amount_unit
- , s.real_amount_value, s.real_amount_unit
- , s.molarity_value, s.molarity_unit
- , s.created_at, s.updated_at, s.description
- , s.purity, s.solvent, s.impurities, s.location, s.is_top_secret
- , s.external_label, s.short_label
- , s.imported_readout, s.sample_svg_file, s.identifier
- , s.density, s.melting_point as melting_point
- , s.boiling_point as boiling_point, s.stereo
- , m.inchikey, m.molecule_svg_file
- , cl.id as uuid
- , cl_r.id as r_uuid
- , rsm.type as reaction_sample
- , rsm.reference as r_reference
- , rsm.equivalent as r_equivalent
- , rsm.position as r_position
- , r.created_at as r_created_at
- , (select array_to_json(array_agg(row_to_json(ecd)))
- from (select ec.composition_type, ec.loading, ec."data" from elemental_compositions ec where s.id = ec.sample_id) ecd) as elemental_compositions_attributes
- , (select array_to_json(array_agg(row_to_json(red)))
- from (select re.custom_info, re.residue_type from residues re where s.id = re.sample_id) red) as residues_attributes
- , row_to_json(mn) as molecule_name_attributes
- ,(select array_to_json(array_agg(row_to_json(lis))) as lls from (
- select lh.element_type,lh.element_id,lh.category,lh.litype,ld.title,ld.url,ld.refs,ld.doi
- from literals lh, literatures ld where lh.literature_id = ld.id
- and lh.element_id = s.id and lh.element_type = 'Sample'
- ) as lis) as literatures
- from samples s
- inner join molecules m on s.molecule_id = m.id
- inner join molecule_names mn on mn.id = s.molecule_name_id
- inner join collections_samples cs on cs.sample_id = s.id and cs.deleted_at isnull
- inner join code_logs cl on cl."source" = 'sample' and cl.source_id = s.id
- left join reactions_samples rsm on (rsm.sample_id = s.id and rsm.deleted_at isnull)
- left join reactions r on r.id = rsm.reaction_id
- left join code_logs cl_r on cl_r."source" = 'reaction' and cl_r.source_id = r.id
- where cs.collection_id = #{c_id} #{ids_sql(sample_ids, 's')}
- order by r_uuid asc) dump;
- SQL
- end
-
- def query_research_plans
- Collection.find(@collection_id).research_plans.where(id: @research_plan_ids)
- end
-
- def analyses_sql(type)
- return unless %w(reaction sample).include?(type)
- cont_type = type.classify
- cl_source = type
- table = type + 's'
- t = type[0]
- ids = ids_sql(send("#{type}_ids"), t)
- col_el = "collections_#{table}"
- col_el_field = "cs.#{type}_id"
-
- <<~SQL
- select json_object_agg(uuid, analyses) as #{type}_analyses from(
- select cl.id as uuid
- , (select array_to_json(array_agg(row_to_json(analysis)))
- from (
- select anac.id, anac."name", anac.description, anac.extended_metadata, clg.id as uuid
- , (select array_to_json(array_agg(row_to_json(dataset)))
- from (
- select datc.id, datc."name", datc.description, datc.extended_metadata
- , (
- select array_to_json(array_agg(row_to_json(attachment)))
- from (
- select att.filename, att.identifier, att.checksum, att.content_type, case att.aasm_state when 'oo_editing' then null else att.aasm_state end as aasm_state
- from attachments att
- where att.attachable_id = datc.id and att.attachable_type = 'Container'
- ) attachment
- ) as attachments
- from containers datc
- inner join container_hierarchies chd on datc.id = chd.descendant_id and anac.id = chd.ancestor_id and chd.generations = 1
- ) dataset
- ) as datasets
- from containers cont
- inner join container_hierarchies ch on cont.id = ch.ancestor_id and ch.generations = 2
- inner join containers anac on anac.id = ch.descendant_id
- left join code_logs clg on clg."source" = 'container' and clg.source_id = anac.id
- where cont.containable_type = '#{cont_type}' and cont.containable_id = #{t}.id
- ) analysis
- ) as analyses
- from #{table} #{t}
- inner join code_logs cl on cl."source" = '#{cl_source}' and cl.source_id = #{t}.id
- inner join #{col_el} cs on #{col_el_field} = #{t}.id and cs.deleted_at isnull
- where cs.collection_id = #{c_id} #{ids}) dump;
- SQL
- end
-
- def attachments_sql
- r_selec = "(cr.collection_id = #{c_id} #{ids_sql(reaction_ids, 'cr', 'reaction_id')})"
- s_selec = "(cs.collection_id = #{c_id} #{ids_sql(sample_ids, 'cs', 'sample_id')})"
- <<-SQL
- select array_to_json(array_agg(att.id)) as ids
- from attachments att
- inner join containers dc on dc.id = att.attachable_id and att.attachable_type = 'Container'
- inner join container_hierarchies ch on dc.id = ch.descendant_id and ch.generations = 3
- inner join containers rootc on rootc.id = ch.ancestor_id
- left join collections_samples cs on cs.sample_id = rootc.containable_id and rootc.containable_type = 'Sample' and cs.deleted_at isnull
- left join collections_reactions cr on cr.reaction_id = rootc.containable_id and rootc.containable_type = 'Reaction' and cr.deleted_at isnull
- where #{s_selec} or #{r_selec};
- SQL
- end
- end
-end
diff --git a/lib/export/export_research_plan.rb b/lib/export/export_research_plan.rb
index 8d08435c76..ddb7c9d551 100644
--- a/lib/export/export_research_plan.rb
+++ b/lib/export/export_research_plan.rb
@@ -77,7 +77,6 @@ def to_html
ApplicationController.render(
template: 'export/research_plan.haml',
assigns: { name: @name, fields: @fields },
- formats: [:docx],
layout: false
)
end
diff --git a/lib/export/export_sdf.rb b/lib/export/export_sdf.rb
index 47edfe22e2..dd759c8307 100644
--- a/lib/export/export_sdf.rb
+++ b/lib/export/export_sdf.rb
@@ -44,7 +44,6 @@ def filter_with_permission_and_detail_level(sample)
end
data = data.rstrip
data += "\n"
-
@headers.each do |column|
column_data = format_field(column, sample[column])
data.concat(column_data)
@@ -73,9 +72,24 @@ def filter_with_permission_and_detail_level(sample)
data.concat("\$\$\$\$\n")
end
+ def extract_reference_values(raw_value)
+ regex = /[\[\]()]/
+ string = raw_value.gsub(regex, '')
+ string.split(',').join(' - ')
+ end
+
def format_field(column, raw_value)
field = column.gsub(/\s+/, '_').upcase
- value = validate_value(raw_value)
+ reference_values = ['melting pt', 'boiling pt']
+ sample_column =
+ if reference_values.include?(column)
+ extract_reference_values(raw_value)
+ elsif column == 'solvent'
+ extract_label_from_solvent_column(raw_value) || ''
+ else
+ raw_value
+ end
+ value = validate_value(sample_column)
"> <#{field}>\n#{value}\n\n"
end
diff --git a/lib/export/export_table.rb b/lib/export/export_table.rb
index d837777fd1..7f7239e500 100644
--- a/lib/export/export_table.rb
+++ b/lib/export/export_table.rb
@@ -43,7 +43,6 @@ class ExportTable
'r ref', 'r eq'
].freeze
-
HEADERS_ANALYSIS_0 = [].freeze
HEADERS_ANALYSIS = ["name", "description", "uuid", "kind", "status", "content"].freeze
HEADERS_DATASET_0 = [].freeze
@@ -51,6 +50,21 @@ class ExportTable
HEADERS_ATTACHMENT_0 = [].freeze
HEADERS_ATTACHMENT = ["filename", "checksum"].freeze
+ def extract_label_from_solvent_column(sample_column)
+ return unless sample_column.is_a?(String) && !sample_column.empty?
+
+ solvent_hash = begin
+ JSON.parse(sample_column)
+ rescue StandardError
+ nil
+ end
+
+ return nil if solvent_hash.nil?
+
+ solvent_values = solvent_hash.map { |solvent| solvent&.fetch('label', nil) }
+ solvent_values.compact.join('-')
+ end
+
def generate_headers(table, excluded_columns = [], selected_columns = [])
@row_headers = @samples.columns - excluded_columns
@headers = @row_headers - %w[s_id ts co_id scu_id shared_sync pl dl_s dl_wp dl_r m_image molfile_version]
@@ -63,7 +77,7 @@ def generate_headers(table, excluded_columns = [], selected_columns = [])
when :sample_analyses
generate_headers_sample_id
add_analyses_header(selected_columns)
- when :sample
+ when :sample, :sample_chemicals
generate_headers_sample
else generate_headers_sample_id
end
@@ -96,6 +110,13 @@ def generate_headers_reaction
}
end
+ def format_headers(headers)
+ headers.map! do |header|
+ header.tr('_', ' ')
+ end
+ headers
+ end
+
def generate_headers_sample
@headers00 = @headers.map { |column|
HEADERS_SAMPLE_0.include?(column) ? column : nil
@@ -103,6 +124,7 @@ def generate_headers_sample
@headers100 = @headers.map { |column|
HEADERS_SAMPLE_10.include?(column) ? column : nil
}
+ @headers = format_headers(@headers)
end
def generate_headers_sample_id
diff --git a/lib/import/helper/cellline_importer.rb b/lib/import/helper/cellline_importer.rb
new file mode 100644
index 0000000000..8095670c1b
--- /dev/null
+++ b/lib/import/helper/cellline_importer.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+class CelllineImporter
+ def initialize(data, current_user_id, instances)
+ @data = data
+ @current_user_id = current_user_id
+ @instances = instances
+ @material_exclude_properties = ['id']
+ @sample_exclude_properties = %w[id user_id]
+ end
+
+ def execute
+ create_cellline_materials
+ create_cellline_samples
+ end
+
+ def create_cellline_samples
+ @data.fetch('CelllineSample', {}).each do |uuid, fields|
+ create_cellline_sample(uuid, fields)
+ end
+ end
+
+ def create_cellline_sample(uuid, fields)
+ material_uuid = @data.fetch('CelllineMaterialCelllineSample', {}).values
+ .select { |entry| entry['cellline_sample_id'] == uuid }
+ .pick('cellline_material_id')
+ material = @instances['CelllineMaterial'][material_uuid]
+
+ sample = CelllineSample.create(
+ fields.except('id', 'user_id')
+ .merge(
+ user_id: @current_user_id,
+ cellline_material_id: material.id,
+ ),
+ )
+ sample.container = Container.create_root_container
+ update_instances!(uuid, sample)
+ add_collections_to_sample(uuid, sample)
+ end
+
+ def update_instances!(uuid, instance)
+ type = instance.class.name
+ @instances[type] = {} unless @instances.key?(type)
+ @instances[type][uuid] = instance
+ end
+
+ def create_cellline_materials
+ @data.fetch('CelllineMaterial', {}).each do |uuid, fields|
+ material = CelllineMaterial.find_by(name: fields['name'], source: fields['source'])
+ material ||= CelllineMaterial.create(fields.except('id'))
+ update_instances!(uuid, material)
+ end
+ end
+
+ def add_collections_to_sample(uuid, sample)
+ @data.fetch('CollectionsCelllineSample', {}).values
+ .select { |x| x['cellline_sample_id'] == uuid }.each do |entry|
+ sample.collections << @instances['Collection'][entry['collection_id']]
+ end
+ sample.save
+ end
+end
diff --git a/lib/import/import_chemicals.rb b/lib/import/import_chemicals.rb
new file mode 100644
index 0000000000..03b2f66571
--- /dev/null
+++ b/lib/import/import_chemicals.rb
@@ -0,0 +1,170 @@
+# frozen_string_literal: true
+
+module Import
+ class ImportChemicals
+ SAFETY_PHRASES = %w[pictograms h_statements p_statements].freeze
+ AMOUNT = %w[amount].freeze
+ SAFETY_SHEET = %w[safety_sheet_link_merck product_link_merck].freeze
+ KEYS_TO_EXCLUDE = SAFETY_SHEET + %w[cas].freeze
+ SIGMA_ALDRICH_PATTERN = /(sigmaaldrich|merck)/.freeze
+ THERMOFISCHER_PATTERN = /(thermofischer|alfa)/.freeze
+ SAFETY_SHEET_PATH = '/safety_sheets/'
+ VENDOR_MAP = {
+ SIGMA_ALDRICH_PATTERN => 'Merck',
+ THERMOFISCHER_PATTERN => 'Alfa',
+ }.freeze
+ CHEMICAL_FIELDS = [
+ 'cas', 'status', 'vendor', 'order number', 'amount', 'price', 'person', 'required date', 'ordered date',
+ 'required by', 'pictograms', 'h statements', 'p statements', 'safety sheet link', 'product link', 'host building',
+ 'host room', 'host cabinet', 'host group', 'owner', 'borrowed by', 'current building', 'current room',
+ 'current cabinet', 'current group', 'disposal info', 'important notes'
+ ].freeze
+ GHS_VALUES = %w[GHS01 GHS02 GHS03 GHS04 GHS05 GHS06 GHS07 GHS08 GHS09].freeze
+ AMOUNT_UNITS = %w[g mg μg].freeze
+
+ def self.build_chemical(row, header)
+ chemical = Chemical.new
+ chemical.chemical_data = [{}]
+ import_data(chemical, row, header)
+ end
+
+ def self.import_data(chemical, row, header)
+ header.each do |column_header|
+ value = row[column_header]
+ next if skip_import?(value, column_header)
+
+ if column_header == 'cas'
+ chemical.cas = value
+ else
+ process_column(chemical, column_header, value)
+ end
+ end
+ chemical
+ end
+
+ def self.skip_import?(value, column_header)
+ value.blank? || column_header.nil?
+ end
+
+ def self.process_column(chemical, column_header, value)
+ map_column = CHEMICAL_FIELDS.find { |e| e == column_header.downcase.rstrip }
+ key = to_snake_case(column_header)
+ format_value = value.strip
+ if map_column.present? && should_process_key(key)
+ chemical['chemical_data'][0][key] = format_value
+ elsif SAFETY_SHEET.include?(key)
+ set_safety_sheet(chemical, key, format_value)
+ elsif SAFETY_PHRASES.include?(key)
+ set_safety_phrases(chemical, key, format_value)
+ elsif AMOUNT.include?(key)
+ set_amount(chemical, format_value)
+ end
+ end
+
+ def self.to_snake_case(column_header)
+ key = column_header.downcase.rstrip.gsub(/\s+/, '_')
+ key == 'owner' ? 'host_owner' : key
+ end
+
+ def self.should_process_key(key)
+ KEYS_TO_EXCLUDE.exclude?(key) && (AMOUNT + SAFETY_PHRASES).exclude?(key)
+ end
+
+ def self.set_safety_sheet(chemical, key, value)
+ vendor = detect_vendor(value)
+ return unless vendor
+
+ product_info = handle_safety_sheet(key, vendor, value, chemical)
+ product_info_key = "#{vendor.downcase}ProductInfo"
+ chemical['chemical_data'][0][product_info_key] ||= {}
+ chemical['chemical_data'][0][product_info_key].merge!(product_info || {})
+ rescue StandardError => e
+ raise "Error setting safety sheet info for chemical: #{e.message}"
+ end
+
+ def self.detect_vendor(value)
+ VENDOR_MAP.each do |pattern, vendor|
+ return vendor if value.present? && value.match?(pattern)
+ end
+ nil
+ end
+
+ def self.handle_safety_sheet(key, vendor, value, chemical)
+ case key
+ when 'safety_sheet_link_merck'
+ product_number = extract_product_number(value)
+ create_safety_sheet_path(vendor.downcase, value, product_number, chemical) if product_number.present?
+ set_safety_sheet_link(vendor, product_number, value) if product_number.present?
+ when 'product_link_merck'
+ { 'productLink' => value }
+ end
+ end
+
+ def self.extract_product_number(url)
+ match = url.match(/productNumber=(\d+)/) || url.match(/sku=(\w+)/)
+ if match
+ match[1]
+ else
+ path = url.split('/')
+ path.last
+ end
+ end
+
+ def self.create_safety_sheet_path(vendor, value, product_number, chemical)
+ file_path = "#{product_number}_#{vendor.capitalize}.pdf"
+ chemical['chemical_data'][0]['safetySheetPath'] ||= []
+ sheet_path = { "#{vendor}_link" => "#{SAFETY_SHEET_PATH}#{file_path}" }
+ is_created = Chemotion::ChemicalsService.create_sds_file(file_path, value)
+ result = [true, 'file is already saved'].include?(is_created)
+ chemical['chemical_data'][0]['safetySheetPath'] << sheet_path if result
+ chemical
+ end
+
+ def self.set_safety_sheet_link(vendor, product_number, value)
+ {
+ 'vendor' => vendor,
+ 'productNumber' => product_number,
+ 'sdsLink' => value,
+ }
+ end
+
+ def self.check_available_ghs_values(values)
+ ghs_values_to_set = []
+ values.each do |value|
+ format_value = value.strip
+ ghs_values_to_set.push(format_value) if GHS_VALUES.include?(format_value)
+ end
+ ghs_values_to_set
+ end
+
+ def self.assign_phrases(key, values, phrases)
+ case key
+ when 'pictograms'
+ value = check_available_ghs_values(values)
+ phrases[key] = value
+ when 'h_statements'
+ value = Chemotion::ChemicalsService.construct_h_statements(values)
+ phrases[key] = value
+ when 'p_statements'
+ value = Chemotion::ChemicalsService.construct_p_statements(values)
+ phrases[key] = value
+ end
+ end
+
+ def self.set_safety_phrases(chemical, key, value)
+ phrases = chemical['chemical_data'][0]['safetyPhrases'] ||= {}
+ values = value.split(/,|-/)
+ assign_phrases(key, values, phrases)
+ end
+
+ def self.set_amount(chemical, value)
+ chemical['chemical_data'][0]['amount'] = {} if chemical['chemical_data'][0]['amount'].nil?
+ quantity = value.to_f
+ unit = value.gsub(/\d+(\.\d+)?/, '')
+ return chemical unless AMOUNT_UNITS.include?(unit)
+
+ chemical['chemical_data'][0]['amount']['value'] = quantity
+ chemical['chemical_data'][0]['amount']['unit'] = unit
+ end
+ end
+end
diff --git a/lib/import/import_collections.rb b/lib/import/import_collections.rb
index eb98b8d311..92694fc1b1 100644
--- a/lib/import/import_collections.rb
+++ b/lib/import/import_collections.rb
@@ -42,6 +42,7 @@ def extract
file_name = entry.name.sub('attachments/', '')
attachment = Attachment.new(
transferred: true,
+ con_state: Labimotion::ConState::NONE,
created_by: @current_user_id,
created_for: @current_user_id,
key: SecureRandom.uuid,
@@ -87,14 +88,20 @@ def import
gate_collection if @gt == true
import_collections if @gt == false
import_samples
+ import_chemicals if @gt == false
import_residues
import_reactions
import_reactions_samples
+ CelllineImporter.new(@data, @current_user_id, @instances).execute if @gt == false
+ # import_elements if @gt == false
+ # import_elements_samples if @gt == false
import_wellplates if @gt == false
import_wells if @gt == false
- import_screens if @gt == false
import_research_plans if @gt == false
+ import_screens if @gt == false
import_containers
+ import_segments
+ import_datasets
import_attachments
import_literals
end
@@ -181,6 +188,21 @@ def fetch_bound(value)
end
end
+ def import_chemicals
+ @data.fetch('Chemical', {}).each do |_uuid, fields|
+ sample = @instances.fetch('Sample').fetch(fields.fetch('sample_id'))
+ next unless sample
+
+ chemical = Chemical.create!(fields.slice(
+ 'cas',
+ 'chemical_data',
+ ).merge(
+ sample_id: sample&.id,
+ ))
+ chemical.save!
+ end
+ end
+
def import_samples
@data.fetch('Sample', {}).each do |uuid, fields|
# look for the molecule_name
@@ -221,6 +243,7 @@ def import_samples
'impurities',
'location',
'is_top_secret',
+ 'dry_solvent',
'external_label',
'short_label',
'real_amount_value',
@@ -235,6 +258,7 @@ def import_samples
'decoupled',
'molecular_mass',
'sum_formula',
+ 'inventory_sample',
).merge(
created_by: @current_user_id,
collections: fetch_many(
@@ -320,6 +344,7 @@ def import_reactions
'solvent',
'short_label',
'role',
+ 'rxno',
'origin',
'duration',
'created_at',
@@ -373,6 +398,10 @@ def import_reactions_samples
end
end
+ def import_elements
+ Labimotion::Import.import_elements(@data, @instances, @gt, @current_user_id, method(:fetch_many), &method(:update_instances!))
+ end
+
def import_wellplates
@data.fetch('Wellplate', {}).each do |uuid, fields|
# create the wellplate
@@ -413,7 +442,7 @@ def import_wells
'updated_at',
).merge(
wellplate: @instances.fetch('Wellplate').fetch(fields.fetch('wellplate_id')),
- sample: @instances.fetch('Sample').fetch(fields.fetch('sample_id'), nil),
+ sample: @instances.fetch('Sample', nil)&.fetch(fields.fetch('sample_id'), nil),
))
# add reaction to the @instances map
@@ -441,6 +470,9 @@ def import_screens
wellplates: fetch_many(
'Wellplate', 'ScreensWellplate', 'screen_id', 'wellplate_id', uuid
),
+ research_plans: fetch_many(
+ 'ResearchPlan', 'ResearchPlansScreen', 'screen_id', 'research_plan_id', uuid
+ ),
))
# create the root container like with samples
@@ -541,6 +573,15 @@ def import_attachments
Rails.logger.debug(e.backtrace)
end
+ def import_segments
+ Labimotion::Import.import_segments(@data, @instances, @gt, @current_user_id, &method(:update_instances!))
+ # nil
+ end
+
+ def import_datasets
+ Labimotion::Import.import_datasets(@data, @instances, @gt, @current_user_id, &method(:update_instances!))
+ end
+
def import_literals
@data.fetch('Literal', {}).each do |uuid, fields|
# get the element for this literal
diff --git a/lib/import/import_json.rb b/lib/import/import_json.rb
index f7d08cb671..a59314421a 100644
--- a/lib/import/import_json.rb
+++ b/lib/import/import_json.rb
@@ -351,10 +351,8 @@ def filter_attributes(klass)
attributes = klass.attribute_names - %w[id user_id created_by deleted_at]
case klass.name
when 'Sample'
- attributes -= [
- 'ancestry', 'molecule_id', 'xref', 'fingerprint_id', 'molecule_name_id',
- 'is_top_secret', 'molecule_svg_file'
- ]
+ attributes -= %w[ancestry molecule_id xref fingerprint_id molecule_name_id
+ is_top_secret molecule_svg_file]
attributes += %w[residues_attributes elemental_compositions_attributes molecule_name_attributes]
# when 'Reaction'
# attributes -= ['reaction_svg_file']
diff --git a/lib/import/import_samples.rb b/lib/import/import_samples.rb
index 5d0fa89940..8fed5834a4 100644
--- a/lib/import/import_samples.rb
+++ b/lib/import/import_samples.rb
@@ -1,298 +1,401 @@
-require 'roo'
-class Import::ImportSamples
- attr_reader :xlsx, :sheet, :header, :mandatory_check, :rows, :unprocessable,
- :processed, :file_path, :collection_id, :current_user_id
-
- def initialize
- @rows = []
- @unprocessable = []
- @processed = []
- end
+# frozen_string_literal: true
- def from_file(file_path, collection_id, current_user_id)
- @file_path = file_path
- @collection_id = collection_id
- @current_user_id = current_user_id
- self
- end
+require 'roo'
- def process
- begin
- read_file
- rescue
- return error_process_file
+# rubocop:disable Metrics/ClassLength
+module Import
+ class ImportSamples
+ attr_reader :xlsx, :sheet, :header, :mandatory_check, :rows, :unprocessable,
+ :processed, :file_path, :collection_id, :current_user_id, :file_name
+
+ def initialize(file_path, collection_id, user_id, file_name, import_type)
+ @rows = []
+ @unprocessable = []
+ @processed = []
+ @file_path = file_path
+ @collection_id = collection_id
+ @current_user_id = user_id
+ @file_name = file_name
+ @import_type = import_type
end
- begin
- check_required_fields
- rescue
- return error_required_fields
- end
+ def process
+ begin
+ read_file
+ rescue StandardError => e
+ return error_process_file(e.message)
+ end
- begin
- insert_rows
- rescue
- return error_insert_rows
+ begin
+ check_required_fields
+ rescue StandardError => e
+ return error_required_fields(e.message)
+ end
+
+ begin
+ process_all_rows
+ rescue StandardError => e
+ error_process(e.message)
+ end
end
- begin
- write_to_db
- return @unprocessable.empty? ? success : warning
- rescue
- return warning
+ def read_file
+ @xlsx = Roo::Spreadsheet.open(file_path)
end
- end
- private
+ def check_required_fields
+ @sheet = xlsx.sheet(0)
+ @header = sheet.row(1)
+ @mandatory_check = {}
+ ['molfile', 'smiles', 'cano_smiles', 'canonical smiles', 'decoupled'].each do |check|
+ @mandatory_check[check] = true if header.find { |e| /^\s*#{check}?/i =~ e }
+ end
- def read_file
- @xlsx = Roo::Spreadsheet.open(file_path)
- end
+ message = 'Column headers should have: molfile, or Smiles (or cano_smiles, canonical smiles)'
+ raise message if mandatory_check.empty?
+ end
- def check_required_fields
- @sheet = xlsx.sheet(0)
- @header = sheet.row(1)
- @mandatory_check = {}
- ["molfile", "smiles", "cano_smiles", "canonical smiles"].each do |check|
- if header.find { |e| /^\s*#{check}?/i =~ e } != nil
- @mandatory_check[check] = true
+ def extract_molfile_and_molecule(row)
+ if molfile?(row)
+ get_data_from_molfile(row)
+ elsif smiles?(row)
+ get_data_from_smiles(row)
end
end
- if mandatory_check.length.zero?
- raise "Column headers should have: molfile, or Smiles (or cano_smiles, canonical smiles)"
- end
- end
- def insert_rows
- (2..xlsx.last_row).each do |i|
- row = Hash[[header, xlsx.row(i)].transpose]
- next unless has_structure(row) || row['decoupled'] == 'Yes'
+ def process_row(data)
+ row = [header, xlsx.row(data)].transpose.to_h
+ is_decoupled = row['decoupled']
+ return unless structure?(row) || is_decoupled
rows << row.each_pair { |k, v| v && row[k] = v.to_s }
end
- end
- def write_to_db
- unprocessable_count = 0
- ActiveRecord::Base.transaction do
- rows.map.with_index do |row, i|
- begin
- if row['decoupled'] == 'Yes' && !has_structure(row)
- molecule = Molecule.find_or_create_dummy
- else
- # If molfile and smiles (Canonical smiles) is both present
- # Double check the rows
- if has_molfile(row) && has_smiles(row)
- molfile, go_to_next = get_data_from_molfile_and_smiles(row)
- next if go_to_next
- end
+ def process_row_data(row)
+ is_decoupled = row['decoupled']
+ return Molecule.find_or_create_dummy if is_decoupled && !structure?(row)
- if has_molfile(row)
- molfile, molecule = get_data_from_molfile(row)
- elsif has_smiles(row)
- molfile, molecule, go_to_next = get_data_from_smiles(row)
- next if go_to_next
- end
+ molecule, molfile = extract_molfile_and_molecule(row)
+ return if molfile.nil? || molecule.nil?
+
+ [molecule, molfile]
+ end
+
+ def molecule_not_exist(molecule)
+ @unprocessable << { row: row, index: i } if molecule.nil?
+ molecule.nil?
+ end
+
+ def write_to_db
+ unprocessable_count = 0
+ begin
+ ActiveRecord::Base.transaction do
+ rows.map.with_index do |row, i|
+ molecule, molfile = process_row_data(row)
if molecule_not_exist(molecule)
unprocessable_count += 1
next
end
+ sample_save(row, molfile, molecule)
+ rescue StandardError => _e
+ unprocessable_count += 1
+ @unprocessable << { row: row, index: i }
end
- sample_save(row, molfile, molecule)
- rescue
- unprocessable_count += 1
- @unprocessable << { row: row, index: i }
end
+ rescue StandardError => _e
+ raise 'More than 1 row can not be processed' if unprocessable_count.positive?
end
- raise 'More than 1 row can not be processed' if unprocessable_count.positive?
end
- end
- def has_structure row
- has_molfile(row) || has_smiles(row)
- end
+ def structure?(row)
+ molfile?(row) || smiles?(row)
+ end
- def has_molfile(row)
- mandatory_check["molfile"] && row["molfile"].to_s.present?
- end
+ def molfile?(row)
+ mandatory_check['molfile'] && row['molfile'].to_s.present?
+ end
- def has_smiles(row)
- header = mandatory_check["smiles"] || mandatory_check["cano_smiles"] || mandatory_check["canonical smiles"]
- cell = row["smiles"].to_s.present? || row["cano_smiles"].to_s.present? || row["canonical smiles"].to_s.present?
- header && cell
- end
+ def smiles?(row)
+ header = mandatory_check['smiles'] || mandatory_check['cano_smiles'] || mandatory_check['canonical smiles']
+ cell = row['smiles'].to_s.present? || row['cano_smiles'].to_s.present? || row['canonical smiles'].to_s.present?
+ header && cell
+ end
+
+ def get_data_from_molfile_and_smiles(row)
+ molfile = row['molfile'].presence
+ if molfile
+ babel_info = Chemotion::OpenBabelService.molecule_info_from_molfile(molfile)
+ molfile_smiles = babel_info[:smiles]
+ molfile_smiles = Chemotion::OpenBabelService.canon_smiles_to_smiles molfile_smiles if mandatory_check['smiles']
+ end
+ if molfile_smiles.blank? && (molfile_smiles != row['cano_smiles'] &&
+ molfile_smiles != row['smiles'] && molfile_smiles != row['canonical smiles'])
+ @unprocessable << { row: row, index: i }
+ go_to_next = true
+ end
+ [go_to_next, molfile]
+ end
- def get_data_from_molfile_and_smiles(row)
- molfile = row["molfile"].presence
- if molfile
+ def get_data_from_molfile(row)
+ molfile = row['molfile'].to_s
babel_info = Chemotion::OpenBabelService.molecule_info_from_molfile(molfile)
- molfile_smiles = babel_info[:smiles]
- if mandatory_check["smiles"]
- molfile_smiles = Chemotion::OpenBabelService.canon_smiles_to_smiles molfile_smiles
+ inchikey = babel_info[:inchikey]
+ molecule = Molecule.find_or_create_by_molfile(molfile, babel_info) if inchikey.presence
+ [molecule, molfile]
+ end
+
+ def assign_molecule_data(molfile_coord, babel_info, inchikey, row)
+ if inchikey.blank?
+ @unprocessable << { row: row, index: i }
+ go_to_next = true
+ else
+ molecule = Molecule.find_or_create_by(inchikey: inchikey, is_partial: false) do |molecul|
+ pubchem_info =
+ Chemotion::PubchemService.molecule_info_from_inchikey(inchikey)
+ molecul.molfile = molfile_coord
+ molecul.assign_molecule_data babel_info, pubchem_info
+ end
end
+ [molecule, molfile_coord, go_to_next]
end
- if molfile_smiles.blank? &&
- (molfile_smiles != row["cano_smiles"] && molfile_smiles != row["smiles"] && molfile_smiles != row["canonical smiles"])
- @unprocessable << { row: row, index: i }
- go_to_next = true
+
+ def get_data_from_smiles(row)
+ smiles = (mandatory_check['smiles'] && row['smiles'].presence) ||
+ (mandatory_check['cano_smiles'] && row['cano_smiles'].presence) ||
+ (mandatory_check['canonical smiles'] && row['canonical smiles'].presence)
+ inchikey = Chemotion::OpenBabelService.smiles_to_inchikey smiles
+ ori_molf = Chemotion::OpenBabelService.smiles_to_molfile smiles
+ babel_info = Chemotion::OpenBabelService.molecule_info_from_molfile(ori_molf)
+ molfile_coord = Chemotion::OpenBabelService.add_molfile_coordinate(ori_molf)
+ assign_molecule_data(molfile_coord, babel_info, inchikey, row)
end
- return molfile, go_to_next
- end
- def get_data_from_molfile(row)
- molfile = row["molfile"].to_s
- babel_info = Chemotion::OpenBabelService.molecule_info_from_molfile(molfile)
- inchikey = babel_info[:inchikey]
- is_partial = babel_info[:is_partial]
- if inchikey.presence
- molecule = Molecule.find_or_create_by_molfile(molfile, babel_info)
+ def included_fields
+ Sample.attribute_names - excluded_fields
end
- return molfile, molecule
- end
- def get_data_from_smiles(row)
- smiles = (mandatory_check['smiles'] && row['smiles'].presence) ||
- (mandatory_check['cano_smiles'] && row['cano_smiles'].presence) ||
- (mandatory_check['canonical smiles'] && row['canonical smiles'].presence)
- inchikey = Chemotion::OpenBabelService.smiles_to_inchikey smiles
- ori_molf = Chemotion::OpenBabelService.smiles_to_molfile smiles
- babel_info = Chemotion::OpenBabelService.molecule_info_from_molfile(ori_molf)
- molfile_coord = Chemotion::OpenBabelService.add_molfile_coordinate(ori_molf)
- if inchikey.blank?
- @unprocessable << { row: row, index: i }
- go_to_next = true
- else
- molecule = Molecule.find_or_create_by(inchikey: inchikey, is_partial: false) do |molecule|
- pubchem_info =
- Chemotion::PubchemService.molecule_info_from_inchikey(inchikey)
- molecule.molfile = molfile_coord
- molecule.assign_molecule_data babel_info, pubchem_info
+ def construct_solvents_array(solvents)
+ solvents_array = solvents.split('-')
+ solvents_array.map(&:capitalize)
+ end
+
+ def handle_sample_solvent_column(sample, row)
+ return unless row['solvent'].is_a? String
+
+ solvent_array = construct_solvents_array(row['solvent'])
+ solvent_column = []
+ solvent_array.each do |element|
+ solvent = Chemotion::SampleConst.solvents_smiles_options.find { |s| s[:label].include?(element) }
+ next if solvent.blank?
+
+ solvent_column.push({ label: solvent[:value][:external_label],
+ smiles: solvent[:value][:smiles],
+ ratio: '1' })
end
+ sample['solvent'] = '' if sample['solvent'].is_a? String
+ sample['solvent'] = solvent_column unless solvent_column.empty?
end
- return molfile_coord, molecule, go_to_next
- end
- def molecule_not_exist(molecule)
- @unprocessable << { row: row, index: i } if molecule.nil?
- molecule.nil?
- end
+ # format row[field] for melting and boiling point
+ def format_to_interval_syntax(row_field)
+ return "[#{-Float::INFINITY}, #{Float::INFINITY}]" if row_field.nil?
- # format row[field] for melting and boiling point
- def format_to_interval_syntax(row_field)
- # Regex checks for a range of numbers that are separated by a dash, or a single number
- matches = row_field.scan(/^(-?\d+(?:[.,]\d+)?)(?:\s*-\s*(-?\d+(?:[.,]\d+)?))?$/).flatten.compact
- numbers = matches.empty? ? [-Float::INFINITY, Float::INFINITY] : matches.filter_map(&:to_f)
- lower_bound, upper_bound = numbers.size == 1 ? [numbers[0], Float::INFINITY] : numbers
- "[#{lower_bound}, #{upper_bound}]"
- end
+ # Regex checks for a range of numbers that are separated by a dash, or a single number
+ matches = row_field.scan(/^(-?\d+(?:[.,]\d+)?)(?:\s*-\s*(-?\d+(?:[.,]\d+)?))?$/).flatten.compact
+ return "[#{-Float::INFINITY}, #{Float::INFINITY}]" if matches.empty?
- def sample_save(row, molfile, molecule)
- sample = Sample.new(created_by: current_user_id)
- sample.molfile = molfile
- sample.molecule = molecule
- # Populate new sample
- stereo = {}
- header.each_with_index do |field, index|
- if field.to_s.strip =~ /^stereo_(abs|rel)$/
- stereo[$1] = row[field]
+ numbers = matches.filter_map(&:to_f)
+ lower_bound, upper_bound = numbers.size == 1 ? [numbers[0], Float::INFINITY] : numbers
+ "[#{lower_bound}, #{upper_bound}]"
+ end
+
+ def assign_molecule_name_id(sample, value)
+ split_names = value.split(';')
+ molecule_name_id = MoleculeName.find_by(name: split_names[0]).id
+ sample['molecule_name_id'] = molecule_name_id
+ end
+
+ def handle_sample_fields(sample, db_column, value)
+ case db_column
+ when 'cas'
+ sample['xref']['cas'] = value
+ when 'mn.name'
+ assign_molecule_name_id(sample, value)
+ else
+ sample[db_column] = value || ''
end
- map_column = ReportHelpers::EXP_MAP_ATTR[:sample].values.find { |e| e[1] == '"' + field + '"' }
- db_column = map_column.nil? ? field : map_column[0].sub('s.', '')
- db_column.delete!('"')
- next unless included_fields.include?(db_column)
+ end
- comparison_values = %w[melting_point boiling_point]
- sample[db_column] = comparison_values.include?(db_column) ? format_to_interval_syntax(row[field]) : row[field]
- sample[db_column] = '' if %w[description solvent location external_label].include?(db_column) && row[field].nil?
- sample[db_column] = row[field] == 'Yes' if %w[decoupled].include?(db_column)
+ def process_fields(sample, db_column, field, row, molecule)
+ molecule.create_molecule_name_by_user(row[field], current_user_id) if field == 'molecule name'
+ process_sample_fields(sample, db_column, field, row)
end
- if row['solvent'].is_a? String
- solvent = Chemotion::SampleConst.solvents_smiles_options.find { |s| s[:label].include?(row['solvent']) }
- sample['solvent'] = [{ label: solvent[:value][:external_label], smiles: solvent[:value][:smiles], ratio: '100' }] if solvent.present?
+ def process_sample_fields(sample, db_column, field, row)
+ additional_columns = %w[cas mn.name].freeze
+ return unless included_fields.include?(db_column) || additional_columns.include?(db_column)
+
+ excluded_column = %w[description solvent location external_label].freeze
+ comparison_values = %w[melting_point boiling_point].freeze
+
+ value = row[field]
+ value = format_to_interval_syntax(value) if comparison_values.include?(db_column)
+ handle_sample_fields(sample, db_column, value)
+ sample[db_column] = '' if excluded_column.include?(db_column) && row[field].nil?
+ sample[db_column] = assign_decoupled_value(row[field]) if %w[decoupled].include?(db_column)
end
- sample['xref']['cas'] = row['cas'] if row['cas'].present?
- sample.validate_stereo(stereo)
- sample.collections << Collection.find(collection_id)
- sample.collections << Collection.get_all_collection_for_user(current_user_id)
- sample.save!
- processed.push(sample)
- end
+ def assign_decoupled_value(value)
+ return false if value.nil?
- def excluded_fields
- [
- 'id',
- # 'name',
- # 'target_amount_value',
- # 'target_amount_unit',
- 'created_at',
- 'updated_at',
- # 'description',
- 'molecule_id',
- 'molfile',
- # 'purity',
- # 'solvent',
- 'impurities',
- # 'location',
- 'is_top_secret',
- 'ancestry',
- # 'external_label',
- 'created_by',
- 'short_label',
- # 'real_amount_value',
- # 'real_amount_unit',
- # 'imported_readout',
- 'deleted_at',
- 'sample_svg_file',
- 'user_id',
- 'identifier',
- # 'density',
- # 'melting_point',
- # 'boiling_point',
- 'fingerprint_id',
- 'xref',
- # 'molarity_value',
- # 'molarity_unit',
- 'molecule_name_id',
- ]
- end
+ if value.is_a?(String)
+ return false unless value.casecmp('yes').zero? || value == '1'
- def included_fields
- Sample.attribute_names - excluded_fields
- end
+ value = true
+ end
+ value
+ end
- def error_process_file
- { status: "invalid",
- message: "Can not process this type of file.",
- data: [] }
- end
+ def save_chemical(chemical, sample)
+ chemical.sample_id = sample.id
+ chemical.save!
+ end
- def error_required_fields
- { status: "invalid",
- message: "Column headers should have: molfile or Canonical Smiles.",
- data: [] }
- end
+ def validate_sample_and_save(sample, stereo, row)
+ handle_sample_solvent_column(sample, row)
+ sample.validate_stereo(stereo)
+ sample.collections << Collection.find(collection_id)
+ sample.collections << Collection.get_all_collection_for_user(current_user_id)
+ sample.inventory_sample = true if @import_type == 'chemical'
+ chemical = ImportChemicals.build_chemical(row, header) if @import_type == 'chemical'
+ sample.save!
+ save_chemical(chemical, sample) if @import_type == 'chemical'
+ processed.push(sample)
+ end
- def error_insert_rows
- { status: "invalid",
- message: "Error while parsing the file.",
- data: [] }
- end
+ def create_sample_and_assign_molecule(current_user_id, molfile, molecule)
+ sample = Sample.new(created_by: current_user_id)
+ sample.molfile = molfile
+ sample.molecule = molecule
+ sample
+ end
- def warning
- { status: "warning",
- message: "No data saved, because following rows cannot be processed: #{unprocessable_rows}.",
- data: unprocessable }
- end
+ # rubocop:disable Style/StringLiterals
+ def sample_save(row, molfile, molecule)
+ sample = create_sample_and_assign_molecule(current_user_id, molfile, molecule)
+ stereo = {}
+ header.each do |field|
+ stereo[Regexp.last_match(1)] = row[field] if field.to_s.strip =~ /^stereo_(abs|rel)$/
+ map_column = ReportHelpers::EXP_MAP_ATTR[:sample].values.find { |e| e[1] == "\"#{field}\"" }
+ db_column = map_column.nil? || map_column[1] == "\"cas\"" ? field : map_column[0].sub('s.', '').delete!('"')
+ process_fields(sample, db_column, field, row, molecule)
+ end
+ validate_sample_and_save(sample, stereo, row)
+ end
+ # rubocop:enable Style/StringLiterals
- def unprocessable_rows
- unprocessable.map { |u| u[:index] + 2 }.join(', ')
- end
+ def process_all_rows
+ (2..xlsx.last_row).each do |data|
+ process_row(data)
+ end
+ begin
+ write_to_db
+ if processed.empty?
+ no_success
+ else
+ @unprocessable.empty? ? success : warning
+ end
+ rescue StandardError => e
+ warning(e.message)
+ end
+ end
+
+ def excluded_fields
+ [
+ 'id',
+ # 'name',
+ # 'target_amount_value',
+ # 'target_amount_unit',
+ 'created_at',
+ 'updated_at',
+ # 'description',
+ 'molecule_id',
+ 'molfile',
+ # 'purity',
+ # 'solvent',
+ 'impurities',
+ # 'location',
+ 'is_top_secret',
+ # 'dry_solvent',
+ 'ancestry',
+ # 'external_label',
+ 'created_by',
+ 'short_label',
+ # 'real_amount_value',
+ # 'real_amount_unit',
+ # 'imported_readout',
+ 'deleted_at',
+ 'sample_svg_file',
+ 'user_id',
+ 'identifier',
+ # 'density',
+ # 'melting_point',
+ # 'boiling_point',
+ 'fingerprint_id',
+ # 'xref',
+ # 'molarity_value',
+ # 'molarity_unit',
+ 'molecule_name_id',
+ ]
+ end
+
+ def error_process_file(error)
+ { status: 'invalid',
+ message: 'Can not process this type of file.',
+ error: error,
+ data: [] }
+ end
- def success
- { status: "ok",
- message: "",
- data: processed }
+ def error_required_fields(error)
+ { status: 'invalid',
+ error: error,
+ message: 'Column headers should have: molfile or Canonical Smiles.',
+ data: [] }
+ end
+
+ def error_process(error)
+ { status: 'invalid',
+ error: error,
+ message: 'Error while parsing the file.',
+ data: [] }
+ end
+
+ def no_success(error)
+ { status: 'invalid',
+ error: error,
+ message: "No samples could be imported for file #{@file_name} " \
+ "because of the following error #{error}.",
+ unprocessed_data: unprocessable }
+ end
+
+ def warning(error = nil)
+ { status: 'warning',
+ error: error,
+ message: "following rows in file: #{@file_name} " \
+ "could not be imported: #{unprocessable_rows}.",
+ unprocessed_data: unprocessable,
+ data: processed }
+ end
+
+ def unprocessable_rows
+ unprocessable.map { |u| u[:index] + 2 }.join(', ')
+ end
+
+ def success
+ { status: 'ok',
+ message: "samples in file: #{@file_name} have been imported successfully",
+ data: processed }
+ end
end
end
+# rubocop:enable Metrics/ClassLength
diff --git a/lib/import/import_sdf.rb b/lib/import/import_sdf.rb
index 10a03ddd28..214198a476 100644
--- a/lib/import/import_sdf.rb
+++ b/lib/import/import_sdf.rb
@@ -2,9 +2,9 @@
require 'charlock_holmes'
-class Import::ImportSdf
+class Import::ImportSdf < Import::ImportSamples
attr_reader :collection_id, :current_user_id, :processed_mol, :file_path,
- :inchi_array, :raw_data, :rows, :custom_data_keys, :mapped_keys
+ :inchi_array, :raw_data, :rows, :custom_data_keys, :mapped_keys, :unprocessable_samples
SIZE_LIMIT = 40 # MB
MOLFILE_BLOCK_END_LINE = 'M END'
@@ -18,7 +18,8 @@ def initialize(args)
@inchi_array = args[:inchikeys] || []
@rows = args[:rows] || []
@custom_data_keys = {}
- @mapped_keys = args[:mapped_keys] || {}
+ @mapped_keys = keys_to_map || {}
+ @unprocessable_samples = []
read_data
@count = @raw_data.empty? && @rows.size || @raw_data.size
@@ -29,6 +30,29 @@ def initialize(args)
end
end
+ def keys_to_map
+ {
+ description: { field: 'description', displayName: 'Description', multiple: true },
+ location: { field: 'location', displayName: 'Location' },
+ name: { field: 'name', displayName: 'Name' },
+ external_label: { field: 'external_label', displayName: 'External label' },
+ purity: { field: 'purity', displayName: 'Purity' },
+ molecule_name: { field: 'molecule_name', displayName: 'Molecule Name' },
+ short_label: { field: 'short_label', displayName: 'Short Label' },
+ real_amount: { field: 'real_amount', displayName: 'Real Amount' },
+ real_amount_unit: { field: 'real_amount_unit', displayName: 'Real Amount Unit' },
+ target_amount: { field: 'target_amount', displayName: 'Target Amount' },
+ target_amount_unit: { field: 'target_amount_unit', displayName: 'Target Amount Unit' },
+ molarity: { field: 'molarity', displayName: 'Molarity' },
+ density: { field: 'density', displayName: 'Density' },
+ melting_point: { field: 'melting_point', displayName: 'Melting Point' },
+ boiling_point: { field: 'boiling_point', displayName: 'Boiling Point' },
+ cas: { field: 'cas', displayName: 'Cas' },
+ solvent: { field: 'solvent', displayName: 'Solvent' },
+ dry_solvent: { field: 'dry_solvent', displayName: 'Dry Solvent' },
+ }
+ end
+
def read_data
if file_path
size = File.size(file_path)
@@ -46,7 +70,12 @@ def read_data
end
def message
- @message[:error].join("\n") + @message[:info].join("\n")
+ if @unprocessable_samples.empty?
+ @message[:error].join("\n") + @message[:info].join("\n")
+ else
+ result = " Following samples could not be imported #{@unprocessable_samples}"
+ @message[:error].join("\n") + @message[:info].join("\n") + result
+ end
end
def error_messages
@@ -87,7 +116,6 @@ def is_number?(string)
def create_samples
ids = []
read_data if raw_data.empty? && rows.empty?
-
if !raw_data.empty? && inchi_array.empty?
ActiveRecord::Base.transaction do
raw_data.each do |molfile|
@@ -102,7 +130,7 @@ def create_samples
created_by: current_user_id,
molfile: molfile,
molfile_version: babel_info[:molfile_version],
- molecule_id: molecule.id
+ molecule_id: molecule.id,
)
sample.collections << Collection.find(collection_id)
sample.collections << Collection.get_all_collection_for_user(current_user_id)
@@ -115,7 +143,7 @@ def create_samples
ActiveRecord::Base.transaction do
attribs = Sample.attribute_names & @mapped_keys.keys
error_messages = []
- rows.each do |row|
+ rows.each_with_index do |row, i|
next unless row
error_columns = ''
@@ -140,26 +168,21 @@ def create_samples
molecule_name = molecule.create_molecule_name_by_user(row['molecule_name'], current_user_id)
sample['molecule_name_id'] = molecule_name.id unless molecule_name.blank?
end
-
- mp = row['melting_point'].scan(/\d+(?:\.\d+)?/).map(&:to_f) if row['melting_point'].present?
- sample['melting_point'] = Range.new(-Float::INFINITY, Float::INFINITY)
- sample['melting_point'] = Range.new(mp[0], Float::INFINITY) if mp.present? && mp.length == 1
- sample['melting_point'] = Range.new(mp[0], mp[1]) if mp.present? && mp.length == 2
- bp = row['boiling_point'].scan(/\d+(?:\.\d+)?/).map(&:to_f) if row['boiling_point'].present?
- sample['boiling_point'] = Range.new(-Float::INFINITY, Float::INFINITY)
- sample['boiling_point'] = Range.new(bp[0], Float::INFINITY) if bp.present? && bp.length == 1
- sample['boiling_point'] = Range.new(bp[0], bp[1]) if bp.present? && bp.length == 2
+ sample['melting_point'] = format_to_interval_syntax(row['melting_point']) if row['melting_point'].present?
+ sample['boiling_point'] = format_to_interval_syntax(row['boiling_point']) if row['boiling_point'].present?
+ sample['solvent'] = handle_sample_solvent_column(sample, row) if row['solvent'].present?
sample['description'] = row['description'] if row['description'].present?
sample['location'] = row['location'] if row['location'].present?
+ sample['external_label'] = row['external_label'] if row['external_label'].present?
+ sample['density'] = row['density'] if row['density'].present?
sample['name'] = row['name'] if row['name'].present?
sample['xref']['cas'] = row['cas'] if row['cas'].present?
- sample['external_label'] = row['external_label'] if row['external_label'].present?
sample['short_label'] = row['short_label'] if row['short_label'].present?
sample['molarity_value'] = row['molarity']&.scan(/\d+\.*\d*/)[0] if row['molarity'].present?
+ sample['dry_solvent'] = row['dry_solvent'] if row['dry_solvent'].present?
properties = process_molfile_opt_data(molfile)
sample.validate_stereo('abs' => properties['STEREO_ABS'], 'rel' => properties['STEREO_REL'])
-
sample.target_amount_value = properties['TARGET_AMOUNT'] unless properties['TARGET_AMOUNT'].blank?
sample.target_amount_unit = properties['TARGET_UNIT'] unless properties['TARGET_UNIT'].blank?
if row['target_amount'].present? && row['target_amount_unit'].blank?
@@ -179,7 +202,6 @@ def create_samples
error_columns += ' target amount, target amount unit ,'
end
end
-
sample.real_amount_value = properties['REAL_AMOUNT'] unless properties['REAL_AMOUNT'].blank?
sample.real_amount_unit = properties['REAL_UNIT'] unless properties['REAL_UNIT'].blank?
if row['real_amount'].present? && row['real_amount_unit'].blank?
@@ -205,6 +227,11 @@ def create_samples
sample.collections << Collection.get_all_collection_for_user(current_user_id)
sample.save!
ids << sample.id
+ rescue StandardError => _e
+ @unprocessable_samples << (i + 1)
+ end
+ unless @unprocessable_samples.empty?
+ error_messages = "Following samples could not be imported #{@unprocessable_samples}."
end
@message[:error_messages] = error_messages if error_messages.present?
end
diff --git a/lib/pub_chem.rb b/lib/pub_chem.rb
index 9dcb7b4b77..234e18c486 100644
--- a/lib/pub_chem.rb
+++ b/lib/pub_chem.rb
@@ -3,16 +3,17 @@
module PubChem
include HTTParty
- #debug_output $stderr
+ # debug_output $stderr
PUBCHEM_HOST = 'pubchem.ncbi.nlm.nih.gov'
def self.http_s
- Rails.env.test? && "http://" || "https://"
+ (Rails.env.test? && 'http://') || 'https://'
end
def self.get_record_from_molfile(molfile)
- @auth = {:username => '', :password => ''}
- options = { :timeout => 10, :headers => {'Content-Type' => 'application/x-www-form-urlencoded'}, :body => { 'sdf' => molfile } }
+ @auth = { username: '', password: '' }
+ options = { timeout: 10, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
+ body: { 'sdf' => molfile } }
HTTParty.post(http_s + PUBCHEM_HOST + '/rest/pug/compound/sdf/record/JSON', options)
rescue StandardError => e
@@ -21,9 +22,9 @@ def self.get_record_from_molfile(molfile)
end
def self.get_record_from_inchikey(inchikey)
- @auth = {:username => '', :password => ''}
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/json'} }
- HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/'+inchikey+'/record/JSON', options)
+ @auth = { username: '', password: '' }
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
+ HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/' + inchikey + '/record/JSON', options)
rescue StandardError => e
Rails.logger.error ["with inchikey: #{inchikey}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
nil
@@ -31,9 +32,9 @@ def self.get_record_from_inchikey(inchikey)
def self.get_cids_from_inchikeys(inchikeys)
options = {
- :timeout => 10,
- :headers => {'Content-Type' => 'application/x-www-form-urlencoded'},
- :body => { "inchikey"=>"#{inchikeys.join(',')}" },
+ timeout: 10,
+ headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
+ body: { 'inchikey' => "#{inchikeys.join(',')}" },
}
HTTParty.post(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/property/InChIKey/JSON', options).body
rescue StandardError => e
@@ -43,9 +44,9 @@ def self.get_cids_from_inchikeys(inchikeys)
def self.get_records_from_inchikeys(inchikeys)
options = {
- :timeout => 10,
- :headers => {'Content-Type' => 'application/x-www-form-urlencoded'},
- :body => { "inchikey"=>"#{inchikeys.join(',')}" },
+ timeout: 10,
+ headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
+ body: { 'inchikey' => "#{inchikeys.join(',')}" },
}
HTTParty.post(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/record/JSON', options).body
rescue StandardError => e
@@ -54,10 +55,10 @@ def self.get_records_from_inchikeys(inchikeys)
end
def self.get_molfile_by_inchikey(inchikey)
- @auth = {:username => '', :password => ''}
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/json'} }
+ @auth = { username: '', password: '' }
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
- HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/'+inchikey+'/record/SDF', options).body
+ HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/' + inchikey + '/record/SDF', options).body
rescue StandardError => e
Rails.logger.error ["with inchikey: #{inchikey}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
nil
@@ -65,41 +66,42 @@ def self.get_molfile_by_inchikey(inchikey)
def self.get_molfiles_by_inchikeys(inchikeys)
options = {
- :timeout => 10,
- :headers => {'Content-Type' => 'application/x-www-form-urlencoded'},
- :body => { "inchikey"=>"#{inchikeys.join(',')}" },
+ timeout: 10,
+ headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
+ body: { 'inchikey' => "#{inchikeys.join(',')}" },
}
- HTTParty.post(http_s+'/rest/pug/compound/inchikey/record/SDF', options).body
+ HTTParty.post(http_s + '/rest/pug/compound/inchikey/record/SDF', options).body
rescue StandardError => e
Rails.logger.error "[PubChemError] of [get_molfiles_by_inchikeys] with inchikey [#{inchikeys}], exception [#{e.backtrace}]"
- return nil
+ nil
end
def self.get_molfile_by_smiles(smiles)
- @auth = {:username => '', :password => ''}
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/json'} }
- encoded_smiles = URI::encode(smiles, '[]/()+-.@#=\\')
- HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/smiles/'+encoded_smiles+'/record/SDF', options).body
+ @auth = { username: '', password: '' }
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
+ encoded_smiles = URI.encode(smiles, '[]/()+-.@#=\\')
+ HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/smiles/' + encoded_smiles + '/record/SDF', options).body
rescue StandardError => e
Rails.logger.error ["with smiles: #{smiles}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
nil
end
def self.get_xref_by_inchikey(inchikey)
- @auth = {:username => '', :password => ''}
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/json'} }
+ @auth = { username: '', password: '' }
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
- HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/'+inchikey+'/xrefs/RN/JSON', options).body
+ HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/' + inchikey + '/xrefs/RN/JSON', options).body
rescue StandardError => e
Rails.logger.error ["with inchikey: #{inchikey}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
nil
end
def self.get_cid_from_inchikey(inchikey)
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/plain'} }
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/plain' } }
begin
resp = HTTParty.get(http_s + PUBCHEM_HOST + '/rest/pug/compound/inchikey/' + inchikey + '/cids/TXT', options)
return nil unless resp.success?
+
resp.body.presence&.strip
rescue StandardError => e
Rails.logger.error ["with inchikey: #{inchikey}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
@@ -110,16 +112,11 @@ def self.get_cid_from_inchikey(inchikey)
def self.get_cas_from_cid(cid)
return [] unless cid
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/json'} }
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
page = "https://#{PUBCHEM_HOST}/rest/pug_view/data/compound/#{cid}/XML?heading=CAS"
resp_xml = HTTParty.get(page, options).body
resp_doc = Nokogiri::XML(resp_xml)
- # cas_values = resp_doc.css('Name:contains("CAS")').map { |x| x.parent.css('StringValue').text }
- cas_values = resp_doc.css('Name:contains("CAS")').map { |x|
- x.parent.css('Value').css('StringWithMarkup').css('String').map { |y|
- y.text
- }
- }.flatten
+ cas_values = resp_doc.css('Value').css('StringWithMarkup').css('String').map(&:text).flatten
cas = most_occurance(cas_values)
[cas]
end
@@ -127,11 +124,13 @@ def self.get_cas_from_cid(cid)
def self.get_lcss_from_cid(cid)
return nil unless cid
return nil unless cid.is_a? Integer
- options = { :timeout => 10, :headers => {'Content-Type' => 'text/json'}, :format => 'plain' }
+
+ options = { timeout: 10, headers: { 'Content-Type' => 'text/json' }, format: 'plain' }
page = "https://#{PUBCHEM_HOST}/rest/pug_view/data/compound/#{cid}/JSON?heading=GHS%20Classification"
begin
resp = HTTParty.get(page, options)
return nil unless resp.success?
+
JSON.parse resp, symbolize_names: true
rescue StandardError => e
Rails.logger.error ["with cid: #{cid}", e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR)
@@ -148,14 +147,14 @@ def self.update_list(type = 'Weekly')
ftp.connect(FTP_PATH)
ftp.login
ftp.chdir(dir_path)
- dirname_list = ftp.list.map { |entry| entry.split(/\s+/)[-1]}
+ dirname_list = ftp.list.map { |entry| entry.split(/\s+/)[-1] }
ftp.close
dirname_list
end
def self.date_select(date, date_list)
date = Date.parse(date) unless date.is_a?(Date)
- date_list.select { |d| d =~ /\d{4}-\d{1,2}-\d{1,2}/ && Date.parse(d) > date }
+ date_list.select { |d| d =~ /\d{4}-\d{1,2}-\d{1,2}/ && Date.parse(d) > date }
end
def self.sdf_file_list(date, type = 'Weekly')
@@ -164,7 +163,7 @@ def self.sdf_file_list(date, type = 'Weekly')
ftp.connect(FTP_PATH)
ftp.login
ftp.chdir(dir_path)
- dirname_list = ftp.list('Compound*').map { |entry| entry.split(/\s+/)[-1]}
+ dirname_list = ftp.list('Compound*').map { |entry| entry.split(/\s+/)[-1] }
ftp.close
dirname_list
end
@@ -172,6 +171,7 @@ def self.sdf_file_list(date, type = 'Weekly')
# compose the ftp directory
def self.ftp_update_dir(type: 'Weekly', date: nil)
return "/pubchem/Compound/#{type}/" unless date.present?
+
date = date.strftime('%Y-%m-%d') if date.is_a?(Date)
"/pubchem/Compound/#{type}/#{date}/SDF/"
end
@@ -184,7 +184,7 @@ def self.dowload_sdf_update_files(remotefile_path)
ftp.connect(FTP_PATH)
ftp.login
begin
- ftp.getbinaryfile(remotefile_path) { |data| tf.write data }
+ ftp.getbinaryfile(remotefile_path) { |data| tf.write data }
ensure
ftp.close
end
@@ -210,12 +210,10 @@ def self.sdf_to_hash(tempfile)
names = {}
cid = nil
ink = nil
- lines.each.with_index do |line, i|
- cid = line.strip if previous_line =~ />\s+/
- ink = line.strip if previous_line =~ />\s+/
- if previous_line =~ />\s+/
- names[$1] = line.strip
- end
+ lines.each.with_index do |line, _i|
+ cid = line.strip if />\s+/.match?(previous_line)
+ ink = line.strip if />\s+/.match?(previous_line)
+ names[::Regexp.last_match(1)] = line.strip if />\s+/.match?(previous_line)
previous_line = line
end
results[ink] = { 'cid' => cid, 'names' => names }
diff --git a/lib/reporter/docx/detail_reaction.rb b/lib/reporter/docx/detail_reaction.rb
index c99376fa96..5aa39c9cde 100644
--- a/lib/reporter/docx/detail_reaction.rb
+++ b/lib/reporter/docx/detail_reaction.rb
@@ -44,11 +44,39 @@ def content
gp_title_html: gp_title_html,
synthesis_title_html: synthesis_title_html,
synthesis_html: synthesis_html,
+ variations: variations,
}
end
private
+ def variations
+ obj.variations.map do |var|
+ {
+ 'temperature' => "#{var[:properties][:temperature][:value]} #{var[:properties][:temperature][:unit]}",
+ 'duration' => "#{var[:properties][:duration][:value]} #{var[:properties][:duration][:unit]}",
+ 'startingMaterials' => variation_materials(var, :startingMaterials),
+ 'reactants' => variation_materials(var, :reactants),
+ 'solvents' => variation_materials(var, :solvents),
+ 'products' => variation_products(var),
+ }
+ end
+ end
+
+ def variation_materials(variation, type)
+ variation[type].map do |_, v|
+ "#{v[:aux][:sumFormula]}:\n#{v[:value]} #{v[:unit]} " \
+ "; #{v[:aux].fetch(:equivalent, 'n/a')} Equiv " +
+ (v[:aux][:isReference] ? '; Ref' : '')
+ end
+ end
+
+ def variation_products(variation)
+ variation[:products].map do |_, v|
+ "#{v[:aux][:sumFormula]}:\n#{v[:value]} #{v[:unit]}; (#{v[:aux][:yield]} % yield)"
+ end
+ end
+
def title
(obj.name.presence || obj.short_label)
end
diff --git a/lib/reporter/spectrum/detail.rb b/lib/reporter/spectrum/detail.rb
index 7ee0b293c5..247e69f8ad 100644
--- a/lib/reporter/spectrum/detail.rb
+++ b/lib/reporter/spectrum/detail.rb
@@ -36,7 +36,7 @@ def prd_info_delta
# - - - - - - - - - -
def atts_content
- @prd['atts'].map do |att|
+ @prd['atts']&.map do |att|
att_content(att)
end.compact
end
diff --git a/lib/reporter/worker.rb b/lib/reporter/worker.rb
index bf12de4703..73c0095442 100644
--- a/lib/reporter/worker.rb
+++ b/lib/reporter/worker.rb
@@ -86,6 +86,7 @@ def extract(objects) # rubocop:disable Metrics/MethodLength
entity_class.new(
instance,
+ current_user: @author,
detail_levels: ElementDetailLevelCalculator.new(user: @author, element: instance).detail_levels,
).serializable_hash
end
diff --git a/lib/reporter/worker_spectrum.rb b/lib/reporter/worker_spectrum.rb
index 25b2c47cbf..0a146c60ee 100644
--- a/lib/reporter/worker_spectrum.rb
+++ b/lib/reporter/worker_spectrum.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Reporter
class WorkerSpectrum < Worker
def initialize(args)
@@ -9,32 +11,73 @@ def initialize(args)
def substance
@substance ||= {
- objs: contents
+ objs: contents,
}
end
def contents
- replace_att_objs
+ product_attrs = extract_product_attrs(@objs)
+ replace_att_objs(product_attrs)
@contents ||= Spectrum::Document.new(
- objs: @prd_atts,
- mol_serials: @mol_serials,
- font_family: 'Times New Roman'
- ).convert
+ objs: product_attrs,
+ mol_serials: @mol_serials,
+ font_family: 'Times New Roman',
+ ).convert
end
- def replace_att_objs
- @prd_atts.map do |prd|
- att_objs = prd['atts'].map do |att|
- kind = att['kind']
- att = Attachment.find(att['id'])
- can_dwnld = if att
- element = att.container.root.containable
- can_read = ElementPolicy.new(@author, element).read?
- can_read && ElementPermissionProxy.new(@author, element, user_ids).read_dataset?
+ def extract_product_attrs(objects)
+ product_attrs = []
+ objects&.map do |obj|
+ product_attrs << extract_products_attrs(obj) if obj[:role] != 'gp'
+ end
+ product_attrs.compact_blank!
+ end
+
+ def extract_products_attrs(object)
+ target_object = {}
+ if object[:type] == 'reaction'
+ object[:products]&.map do |prod|
+ target_object[:prdId] = prod[:id]
+ target_object[:iupac_name] = prod.dig(:molecule, :iupac_name)
+ target_object[:sum_formular] = prod.dig(:molecule, :sum_formular)
+ target_object[:molId] = prod.dig(:molecule, :id)
+ target_object[:showedName] = prod[:showed_name]
+ target_object[:atts] = extract_attributes(prod)
+ end
+ end
+ target_object
+ end
+
+ def extract_attributes(product) # rubocop:disable Metrics/CyclomaticComplexity
+ atts = []
+ product.dig(:container, :children, 0, :children)&.map do |container|
+ is_report = container.dig(:extended_metadata, :report)
+ return nil unless is_report
+
+ kind = container.dig(:extended_metadata, :kind)
+ container[:children]&.map do |analysis|
+ analysis[:attachments]&.map do |attach|
+ attach[:kind] = kind
+ atts << attach
end
+ end
+ end
+ atts
+ end
+
+ def replace_att_objs(product_attrs) # rubocop:disable Metrics/CyclomaticComplexity
+ product_attrs&.map do |prd|
+ att_objs = prd[:atts]&.map do |att|
+ kind = att[:kind]
+ att = Attachment.find(att[:id])
+ can_dwnld = if att
+ element = att.container.root.containable
+ can_read = ElementPolicy.new(@author, element).read?
+ can_read && ElementPermissionProxy.new(@author, element, user_ids).read_dataset?
+ end
can_dwnld ? { obj: att, kind: kind } : nil
end
- prd['atts'] = att_objs
+ prd[:atts] = att_objs
prd
end
end
diff --git a/lib/template/Standard.docx b/lib/template/Standard.docx
index 9f1080b03a..ef3564937b 100644
Binary files a/lib/template/Standard.docx and b/lib/template/Standard.docx differ
diff --git a/package.json b/package.json
index ba07601054..2995076291 100644
--- a/package.json
+++ b/package.json
@@ -10,25 +10,26 @@
"@babel/preset-env": "^7.11.0",
"@babel/preset-react": "7.10.4",
"@citation-js/plugin-isbn": "0.3.0",
- "@complat/chem-spectra-client": "1.0.0-rc10",
- "@complat/react-spectra-editor": "1.0.0-rc10",
+ "@complat/chem-spectra-client": "1.1.1",
+ "@complat/react-spectra-editor": "1.1.1",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@novnc/novnc": "^1.2.0",
"@rails/ujs": "^6.1.3-1",
"@rails/webpacker": "https://github.com/rails/webpacker.git",
- "@sentry/react": "^7.16.0",
+ "@sentry/react": "^7.73.0",
"@sentry/tracing": "^7.16.0",
"acorn": "^5.7.0",
- "ag-grid-community": "^25.1.0",
- "ag-grid-react": "^25.1.0",
+ "ag-grid-community": "^29.0.0",
+ "ag-grid-react": "^29.0.0",
"alt": "0.18.6",
"alt-utils": "2.0.0",
"antd": "^3.19.3",
"aviator": "v0.6.1",
"base-64": "^0.1.0",
- "chemotion-converter-client": "0.1.40",
- "citation-js": "0.5.7",
+ "chem-generic-ui": "^1.1.1",
+ "chemotion-converter-client": "0.5.0",
+ "citation-js": "0.6.8",
"classnames": "^2.2.5",
"clipboard": "^1.5.12",
"commonmark": "^0.28.1",
@@ -44,7 +45,7 @@
"immutable": "^4.0.0-rc.12",
"jcampconverter": "^2.11.0",
"js-yaml": "^3.13.1",
- "jsdom": "^9.8.0",
+ "jsdom": "^22.1.0",
"lodash": "^4.17.20",
"mobx": "^6.6.0",
"mobx-react": "^7.5.0",
@@ -61,6 +62,7 @@
"quill": "^1.3.7",
"quill-delta": "3.4.3",
"quill-delta-to-html": "0.8.2",
+ "quill-delta-to-plaintext": "^1.0.0",
"raw-loader": "^4.0.2",
"react": "^17.0.2",
"react-async-script-loader": "0.3.0",
@@ -71,9 +73,9 @@
"react-contextmenu": "^2.14.0",
"react-cookie": "^0.4.8",
"react-datepicker": "~1.4.1",
+ "react-datetime-picker": "^4.1.1",
"react-dnd": "^14.0.3",
"react-dnd-html5-backend": "^14.0.3",
- "react-datetime-picker": "^4.1.1",
"react-dom": "^17.0.2",
"react-dom-factories": "^1.0.0",
"react-draggable": "^4.4.3",
@@ -93,13 +95,13 @@
"react-select3": "npm:react-select@^3.1.1",
"react-stickydiv": "^3.4.19",
"react-svg-file-zoom-pan": "0.1.5",
- "react-svg-file-zoom-pan-latest": "npm:@complat/react-svg-file-zoom-pan@1.0.13",
+ "react-svg-file-zoom-pan-latest": "npm:@complat/react-svg-file-zoom-pan@1.1.3",
"react-svg-inline": "^1.2.0",
"react-treeview": "0.4.7",
"react-ui-tree": "3.1.0",
"react-virtualized-select": "3.0.1",
"react-vis": "1.9.3",
- "reactflow": "^11.3.0",
+ "reactflow": "^11.7.2",
"redux": "^4.1.0",
"redux-immutable": "^4.0.0",
"redux-thunk": "^2.0.0",
@@ -110,7 +112,7 @@
"uglifyify": "^5.0.2",
"util": "^0.12.4",
"uuid": "^3.3.2",
- "whatwg-fetch": "2.0.3",
+ "whatwg-fetch": "^3.6.2",
"xlsx": "^0.17.0",
"yarn": "^1.22.19"
},
@@ -132,20 +134,18 @@
"eslint-plugin-no-relative-import-paths": "^1.4.0",
"eslint-plugin-react": "^7.30.1",
"expect": "^24.7.1",
- "jsdom-global": "2.1.0",
- "mocha": "^8.1.3",
+ "mocha": "^10.2.0",
"nyc": "^15.1.0",
"process": "^0.11.10",
"react-refresh": "^0.12.0",
"redux-logger": "^3.0.6",
- "sinon": "^7.5.0",
- "sinon-spy-react": "^2.0.1",
+ "sinon": "^15.2.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^4.8.1"
},
"scripts": {
"postinstall": "./package_postinstall.sh",
- "test": "NODE_PATH=./app/packs:./spec/javascripts yarn mocha --require '@babel/register' './spec/javascripts/helper/setup.js' './spec/javascripts/**/*.spec.js'",
+ "test": "NODE_PATH=./app/packs:./spec/javascripts yarn mocha --exit --require '@babel/register' './spec/javascripts/helper/setup.js' './spec/javascripts/**/*.spec.js'",
"coverage": "yarn nyc npm test;yarn nyc report --reporter=html"
},
"nyc": {
@@ -157,7 +157,7 @@
},
"license": "MIT",
"engines": {
- "node": "14.21.3"
+ "node": "18.18.2"
},
"browserslist": [
"defaults"
diff --git a/package_postinstall.sh b/package_postinstall.sh
index c03c5f0711..75227a16ef 100755
--- a/package_postinstall.sh
+++ b/package_postinstall.sh
@@ -4,12 +4,10 @@
set -euo pipefail
-src1=$(node -e 'console.log(require.resolve("@citation-js/core/lib-mjs/util/fetchFile.js"))')
-src2=$(node -e 'console.log(require.resolve("@citation-js/core/lib-mjs/index.js"))')
-src3=$(node -e 'console.log(require.resolve("@citation-js/plugin-bibtex/lib-mjs/input/constants.js"))')
-src4=$(node -e 'console.log(require.resolve("@citation-js/plugin-wikidata/lib-mjs/entity.js"))')
+## ag-grid css
+src5=$(node -e 'console.log(require.resolve("ag-grid-community/styles/ag-grid.css"))')
+src6=$(node -e 'console.log(require.resolve("ag-grid-community/styles/ag-grid-no-native-widgets.css"))')
-[[ -e "$src1" && -e "$src2" && -e "$src3" && -e "$src4" ]] || exit 1
YEL='\033[0;33m'
NOC='\033[0m'
@@ -17,17 +15,15 @@ yellow() {
printf "${YEL}${1:-}${NOC}\n"
}
-yellow "rewrite import for citation.js in:"
-yellow "$src1"
-sed -i "s~import { version } from '../../package.json';~import pkg from '../../package.json';const version = pkg.version;~" $src1
-yellow "$src2"
-sed -i "s~import { version } from '../package.json';~import pkg from '../package.json';const version = pkg.version;~" $src2
-yellow "$src3"
-sed -i "s~export { diacritics, commands } from './unicode.json';~import unicode from './unicode.json';export const diacritics = unicode.diacritics;export const commands = unicode.commands;~" $src3
-yellow "$src4"
-sed -i "s~import { props, ignoredProps } from './props';~import wikiprops from './props';const { props, ignoredProps } = wikiprops ;~" $src4
-yellow "Done fixing import."
+
+yellow "$src5"
+sed -i "s~height: min~height: Min~" $src5
+sed -i "s~height: min~height: Min~" $src6
+yellow "Done fixing css."
+
+
+
# move svgedit to public folder
yellow "Adding symbolic link to svg editor in public folder"
@@ -36,3 +32,26 @@ node_modules_folder="$(node -e 'const p = require.resolve("@svgedit/svgcanvas");
rm -f ./public/svgedit && ln -s "$node_modules_folder"/svgedit/dist/editor ./public/svgedit
yellow "Finished adding symbolic link to svg editor in public folder"
+
+# d3js source files
+src_d3=(
+ "@complat/react-spectra-editor/dist/components/common/draw.js"
+ "@complat/react-spectra-editor/dist/components/d3_line/line_focus.js"
+ "@complat/react-spectra-editor/dist/components/d3_multi/multi_focus.js"
+ "@complat/react-spectra-editor/dist/components/d3_rect/rect_focus.js"
+ "@complat/react-spectra-editor/dist/helpers/brush.js"
+ "@complat/react-spectra-editor/dist/helpers/compass.js"
+ "@complat/react-spectra-editor/dist/helpers/init.js"
+ "@complat/react-spectra-editor/dist/helpers/zoom.js"
+)
+
+# Rewrite import for d3.js
+for src_file in "${src_d3[@]}"; do
+ src=$(node -e "console.log(require.resolve('$src_file'))")
+ yellow "Rewriting import for d3.js in $src"
+ sed -i "s~const d3 = require('d3');~import('d3').then(d3 => {~" "$src"
+ if ! tail -n1 "$src" | grep -q "});"; then
+ echo -e "\n});" >> "$src"
+ fi
+ yellow "Done rewriting import for d3.js in $src"
+done
\ No newline at end of file
diff --git a/public/ontologies_default/bao.default.edited.json b/public/ontologies_default/bao.default.edited.json
new file mode 100644
index 0000000000..255c59dcfe
--- /dev/null
+++ b/public/ontologies_default/bao.default.edited.json
@@ -0,0 +1,13542 @@
+{
+ "ols_terms": [{
+ "key": null,
+ "title": "-- Recently selected --",
+ "selectable": false,
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002753 | assay method component",
+ "title": "assay method component",
+ "value": "BAO:0002753 | assay method component $1245c6b5-33a1-4f93-97e7-b018d0131e9a",
+ "is_enabled": true,
+ "id": "0002753",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000035 | physical detection method",
+ "title": "physical detection method",
+ "value": "BAO:0000035 | physical detection method $7308161b-c30d-4087-a2c4-3b55793bf953",
+ "is_enabled": true,
+ "id": "0000035",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000046 | fluorescence method",
+ "title": "fluorescence method",
+ "value": "BAO:0000046 | fluorescence method $6916710f-2de6-4a02-9268-0555e0326a4b",
+ "is_enabled": true,
+ "id": "0000046",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000003 | fluorescence polarization",
+ "title": "fluorescence polarization",
+ "value": "BAO:0000003 | fluorescence polarization $ed42c354-92b9-4d99-b539-f452ec2fd9a5",
+ "is_enabled": true,
+ "id": "0000003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000005 | flow cytometry",
+ "title": "flow cytometry",
+ "value": "BAO:0000005 | flow cytometry $9219079e-9221-4971-9118-dd1445267c75",
+ "is_enabled": true,
+ "id": "0000005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000001 | fluorescence resonance energy transfer",
+ "title": "fluorescence resonance energy transfer",
+ "value": "BAO:0000001 | fluorescence resonance energy transfer $7e9db54f-5c8c-4370-b352-b1828c4eca10",
+ "is_enabled": true,
+ "id": "0000001",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000002 | homogeneous time resolved fluorescence",
+ "title": "homogeneous time resolved fluorescence",
+ "value": "BAO:0000002 | homogeneous time resolved fluorescence $a4fe0853-cb37-42e4-ae98-fef3d44407aa",
+ "is_enabled": true,
+ "id": "0000002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000004 | time resolved fluorescence resonance energy transfer",
+ "title": "time resolved fluorescence resonance energy transfer",
+ "value": "BAO:0000004 | time resolved fluorescence resonance energy transfer $b44500f3-6c6d-4cdf-91be-d4642e7f5042",
+ "is_enabled": true,
+ "id": "0000004",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000058 | thermal shift",
+ "title": "thermal shift",
+ "value": "BAO:0000058 | thermal shift $5ef96073-ef08-47c2-8a7a-d9ac2ae94ccb",
+ "is_enabled": true,
+ "id": "0000058",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000363 | fluorescence intensity",
+ "title": "fluorescence intensity",
+ "value": "BAO:0000363 | fluorescence intensity $1e33b507-ae07-470f-a105-23bbe0dd5bf7",
+ "is_enabled": true,
+ "id": "0000363",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000049 | spectrophotometry method",
+ "title": "spectrophotometry method",
+ "value": "BAO:0000049 | spectrophotometry method $d2310380-6f7f-4707-a354-f07f2bb00065",
+ "is_enabled": true,
+ "id": "0000049",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002529 | atomic absorption spectrophotometry",
+ "title": "atomic absorption spectrophotometry",
+ "value": "BAO:0002529 | atomic absorption spectrophotometry $b38c4787-974b-4e67-982a-5100202dd928",
+ "is_enabled": true,
+ "id": "0002529",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000071 | transmittance",
+ "title": "transmittance",
+ "value": "BAO:0000071 | transmittance $ea3901e3-8044-4d21-a9f3-51c7650cf81f",
+ "is_enabled": true,
+ "id": "0000071",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000070 | absorbance",
+ "title": "absorbance",
+ "value": "BAO:0000070 | absorbance $452877ae-678c-4018-be1d-0ce0f6050100",
+ "is_enabled": true,
+ "id": "0000070",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000045 | luminescence method",
+ "title": "luminescence method",
+ "value": "BAO:0000045 | luminescence method $1518414b-40a4-4293-be16-ed8b088e3808",
+ "is_enabled": true,
+ "id": "0000045",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000130 | alphascreen",
+ "title": "alphascreen",
+ "value": "BAO:0000130 | alphascreen $121add39-6659-431f-b55a-d078a2a24b6e",
+ "is_enabled": true,
+ "id": "0000130",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000050 | bioluminescence",
+ "title": "bioluminescence",
+ "value": "BAO:0000050 | bioluminescence $b3017bfd-5e4d-4793-a041-b47804c36d8a",
+ "is_enabled": true,
+ "id": "0000050",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000461 | bioluminescence resonance energy transfer",
+ "title": "bioluminescence resonance energy transfer",
+ "value": "BAO:0000461 | bioluminescence resonance energy transfer $fbdbe037-fb07-4025-950d-04ce04ccde58",
+ "is_enabled": true,
+ "id": "0000461",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000051 | chemiluminescence",
+ "title": "chemiluminescence",
+ "value": "BAO:0000051 | chemiluminescence $e6187d54-958d-48dc-b104-b0221a565318",
+ "is_enabled": true,
+ "id": "0000051",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000462 | chemiluminescence resonance energy transfer",
+ "title": "chemiluminescence resonance energy transfer",
+ "value": "BAO:0000462 | chemiluminescence resonance energy transfer $41fe403e-b52f-4ba2-81e8-37c38d7d56f5",
+ "is_enabled": true,
+ "id": "0000462",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000055 | mass spectrometry",
+ "title": "mass spectrometry",
+ "value": "BAO:0000055 | mass spectrometry $167204a3-a862-451a-8fa2-f79460f8b471",
+ "is_enabled": true,
+ "id": "0000055",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000657 | radiometry method",
+ "title": "radiometry method",
+ "value": "BAO:0000657 | radiometry method $737187b1-44fe-4d98-a186-afd2d28b4763",
+ "is_enabled": true,
+ "id": "0000657",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002527 | autoradiography",
+ "title": "autoradiography",
+ "value": "BAO:0002527 | autoradiography $db6857c5-424e-45df-8bca-c77797312ccd",
+ "is_enabled": true,
+ "id": "0002527",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "NCIT:C18639 | Quantitative Autoradiography",
+ "title": "Quantitative Autoradiography",
+ "value": "NCIT:C18639 | Quantitative Autoradiography $0aa93231-f00e-4ab9-b06f-0a5d65830cc7",
+ "is_enabled": true,
+ "id": "C18639",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002528 | phosphorimaging",
+ "title": "phosphorimaging",
+ "value": "BAO:0002528 | phosphorimaging $247b05bc-4c84-4635-8e80-5c28b225be81",
+ "is_enabled": true,
+ "id": "0002528",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000405 | scintillation counting",
+ "title": "scintillation counting",
+ "value": "BAO:0000405 | scintillation counting $6c1169f2-4ec9-44af-9489-3cf4db2ca2e7",
+ "is_enabled": true,
+ "id": "0000405",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000017 | scintillation proximity assay",
+ "title": "scintillation proximity assay",
+ "value": "BAO:0000017 | scintillation proximity assay $8d47df6f-36ab-492b-8da8-27084f41dbd8",
+ "is_enabled": true,
+ "id": "0000017",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000408 | lysate based",
+ "title": "lysate based",
+ "value": "BAO:0000408 | lysate based $11a9b85c-0410-4085-89ea-6f17fe46d814",
+ "is_enabled": true,
+ "id": "0000408",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000401 | filter assay",
+ "title": "filter assay",
+ "value": "BAO:0000401 | filter assay $27457ce2-cb9e-496c-b8b7-1dd93a5e533b",
+ "is_enabled": true,
+ "id": "0000401",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000427 | label free method",
+ "title": "label free method",
+ "value": "BAO:0000427 | label free method $aa8c9217-719e-413f-bffd-e38b9befd8ab",
+ "is_enabled": true,
+ "id": "0000427",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000160 | nuclear magnetic resonance",
+ "title": "nuclear magnetic resonance",
+ "value": "BAO:0000160 | nuclear magnetic resonance $8e95e22b-d6b1-4494-9b83-ed7e4fdc8917",
+ "is_enabled": true,
+ "id": "0000160",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000161 | circular dichroism",
+ "title": "circular dichroism",
+ "value": "BAO:0000161 | circular dichroism $0b9844c1-f156-451b-975e-f853ac1028b3",
+ "is_enabled": true,
+ "id": "0000161",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000163 | electrical sensor",
+ "title": "electrical sensor",
+ "value": "BAO:0000163 | electrical sensor $ee18c71e-5490-473b-829f-764f322a501d",
+ "is_enabled": true,
+ "id": "0000163",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000061 | impedance",
+ "title": "impedance",
+ "value": "BAO:0000061 | impedance $d56538f9-958b-4b92-b07d-adee50f8d25c",
+ "is_enabled": true,
+ "id": "0000061",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000382 | microelectrode measurement",
+ "title": "microelectrode measurement",
+ "value": "BAO:0000382 | microelectrode measurement $9400203c-72ac-4f0b-8619-eb47f0a9ec0b",
+ "is_enabled": true,
+ "id": "0000382",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000060 | current clamp",
+ "title": "current clamp",
+ "value": "BAO:0000060 | current clamp $1e659a1f-e429-4650-b010-50e93a983988",
+ "is_enabled": true,
+ "id": "0000060",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000063 | voltage clamp",
+ "title": "voltage clamp",
+ "value": "BAO:0000063 | voltage clamp $fb6c5e66-9077-4c9c-a7d7-811a8c3d0041",
+ "is_enabled": true,
+ "id": "0000063",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000062 | patch clamp",
+ "title": "patch clamp",
+ "value": "BAO:0000062 | patch clamp $3090eced-deed-4ed6-b0b2-a6f7c3918132",
+ "is_enabled": true,
+ "id": "0000062",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000471 | carbon nanotube based sensor",
+ "title": "carbon nanotube based sensor",
+ "value": "BAO:0000471 | carbon nanotube based sensor $67f729a4-277b-4e64-96b2-285bdf39b1bc",
+ "is_enabled": true,
+ "id": "0000471",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000057 | optical based",
+ "title": "optical based",
+ "value": "BAO:0000057 | optical based $f0f44a4f-b119-4d68-9858-a2939100ce7c",
+ "is_enabled": true,
+ "id": "0000057",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000069 | resonant waveguide grating",
+ "title": "resonant waveguide grating",
+ "value": "BAO:0000069 | resonant waveguide grating $b6d6ace9-8470-4c52-b6b2-95fa0aaf3ac6",
+ "is_enabled": true,
+ "id": "0000069",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000068 | optical waveguide grating",
+ "title": "optical waveguide grating",
+ "value": "BAO:0000068 | optical waveguide grating $6c7a0e4d-f938-412f-90b8-212937fd6ce0",
+ "is_enabled": true,
+ "id": "0000068",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000067 | fiber optic waveguide",
+ "title": "fiber optic waveguide",
+ "value": "BAO:0000067 | fiber optic waveguide $0ab20dc0-2eb1-4337-a9b1-4c48a117469d",
+ "is_enabled": true,
+ "id": "0000067",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000066 | bio layer interferometry",
+ "title": "bio layer interferometry",
+ "value": "BAO:0000066 | bio layer interferometry $493af6e9-3d5f-4f17-b3a3-91e177fbbaf6",
+ "is_enabled": true,
+ "id": "0000066",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000054 | surface plasmon resonance",
+ "title": "surface plasmon resonance",
+ "value": "BAO:0000054 | surface plasmon resonance $0c18f6ad-63cf-42bd-8810-6be0470decaa",
+ "is_enabled": true,
+ "id": "0000054",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000404 | x ray crystallography",
+ "title": "x ray crystallography",
+ "value": "BAO:0000404 | x ray crystallography $75768a8d-aa61-43c9-a48d-9a3aa4a72d9f",
+ "is_enabled": true,
+ "id": "0000404",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000428 | isothermal titration calorimetry",
+ "title": "isothermal titration calorimetry",
+ "value": "BAO:0000428 | isothermal titration calorimetry $664037ff-2c2d-493c-9712-58fc46b90c9c",
+ "is_enabled": true,
+ "id": "0000428",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000456 | quartz crystal microbalance",
+ "title": "quartz crystal microbalance",
+ "value": "BAO:0000456 | quartz crystal microbalance $a8ceccb9-7249-40d6-a215-69f64b5461ab",
+ "is_enabled": true,
+ "id": "0000456",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000452 | imaging method",
+ "title": "imaging method",
+ "value": "BAO:0000452 | imaging method $a5ba57d5-1514-4425-bb11-10794550e008",
+ "is_enabled": true,
+ "id": "0000452",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002525 | tomography",
+ "title": "tomography",
+ "value": "BAO:0002525 | tomography $1325bde4-093c-465d-80fd-32b4d71640fb",
+ "is_enabled": true,
+ "id": "0002525",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002526 | microscopy",
+ "title": "microscopy",
+ "value": "BAO:0002526 | microscopy $80666c8b-6c97-45a3-9b90-6be1b62298cc",
+ "is_enabled": true,
+ "id": "0002526",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000449 | electron microscopy",
+ "title": "electron microscopy",
+ "value": "BAO:0000449 | electron microscopy $08c57128-87e2-4c55-ac2b-b735803a9d2f",
+ "is_enabled": true,
+ "id": "0000449",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000454 | scanning electron microscopy",
+ "title": "scanning electron microscopy",
+ "value": "BAO:0000454 | scanning electron microscopy $e4d0f82c-49d3-43a4-a33b-b22f46c2cc3d",
+ "is_enabled": true,
+ "id": "0000454",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000455 | transmission electron microscopy",
+ "title": "transmission electron microscopy",
+ "value": "BAO:0000455 | transmission electron microscopy $d6ac81c8-0c26-4507-b32d-584716ce3315",
+ "is_enabled": true,
+ "id": "0000455",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000459 | scanning probe microscopy",
+ "title": "scanning probe microscopy",
+ "value": "BAO:0000459 | scanning probe microscopy $78462714-a791-4f9a-b55e-13349d5dc3d7",
+ "is_enabled": true,
+ "id": "0000459",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002523 | atomic force microscopy",
+ "title": "atomic force microscopy",
+ "value": "BAO:0002523 | atomic force microscopy $da045079-b7e1-4d10-b79c-fe1bcd2776a3",
+ "is_enabled": true,
+ "id": "0002523",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002524 | scanning tunneling microscopy",
+ "title": "scanning tunneling microscopy",
+ "value": "BAO:0002524 | scanning tunneling microscopy $26e09c50-6fb3-43e8-9884-bf901a4321a0",
+ "is_enabled": true,
+ "id": "0002524",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000451 | optical microscopy",
+ "title": "optical microscopy",
+ "value": "BAO:0000451 | optical microscopy $c4e79443-2a4a-4a40-a135-7ba2459bac0c",
+ "is_enabled": true,
+ "id": "0000451",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002512 | scanning near-field optical microscopy",
+ "title": "scanning near-field optical microscopy",
+ "value": "BAO:0002512 | scanning near-field optical microscopy $a6f972ae-222d-4c6b-91c9-4690a8d1b415",
+ "is_enabled": true,
+ "id": "0002512",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002513 | vibrational spectroscopic imaging",
+ "title": "vibrational spectroscopic imaging",
+ "value": "BAO:0002513 | vibrational spectroscopic imaging $431c4fcc-8607-4019-bb2b-75fb50ebfee1",
+ "is_enabled": true,
+ "id": "0002513",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002516 | infrared imaging",
+ "title": "infrared imaging",
+ "value": "BAO:0002516 | infrared imaging $fd34cc21-6b17-43e1-acd5-bf6428143e1e",
+ "is_enabled": true,
+ "id": "0002516",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002518 | near-infrared imaging",
+ "title": "near-infrared imaging",
+ "value": "BAO:0002518 | near-infrared imaging $6aa787e0-4a59-4228-88b4-0f53ecd9b186",
+ "is_enabled": true,
+ "id": "0002518",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002519 | mid-infrared imaging",
+ "title": "mid-infrared imaging",
+ "value": "BAO:0002519 | mid-infrared imaging $0930314a-b3a6-447c-90fb-3f8a49e294c2",
+ "is_enabled": true,
+ "id": "0002519",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002515 | Raman imaging",
+ "title": "Raman imaging",
+ "value": "BAO:0002515 | Raman imaging $3701b578-4135-4509-b45f-70a2b7400e63",
+ "is_enabled": true,
+ "id": "0002515",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002510 | dark field microscopy",
+ "title": "dark field microscopy",
+ "value": "BAO:0002510 | dark field microscopy $a35dc242-a827-4033-a24b-823f0bf9ddb1",
+ "is_enabled": true,
+ "id": "0002510",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002511 | differential interference contrast microscopy",
+ "title": "differential interference contrast microscopy",
+ "value": "BAO:0002511 | differential interference contrast microscopy $8fc70829-b52c-4806-b9dc-1e9690aef85f",
+ "is_enabled": true,
+ "id": "0002511",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000453 | confocal microscopy",
+ "title": "confocal microscopy",
+ "value": "BAO:0000453 | confocal microscopy $60c3bbef-485c-49fe-86c2-940d51b981f3",
+ "is_enabled": true,
+ "id": "0000453",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000458 | phase contrast microscopy",
+ "title": "phase contrast microscopy",
+ "value": "BAO:0000458 | phase contrast microscopy $a447be64-7844-4dc6-94d0-ec58ab05be8f",
+ "is_enabled": true,
+ "id": "0000458",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000457 | brightfield microscopy",
+ "title": "brightfield microscopy",
+ "value": "BAO:0000457 | brightfield microscopy $50ee0cc8-a3fd-4c66-9c18-b680b65c925c",
+ "is_enabled": true,
+ "id": "0000457",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000450 | fluorescence microscopy",
+ "title": "fluorescence microscopy",
+ "value": "BAO:0000450 | fluorescence microscopy $a3c56e86-226a-4d07-9042-67e0db29ca06",
+ "is_enabled": true,
+ "id": "0000450",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000064 | total internal reflection fluorescence microscopy",
+ "title": "total internal reflection fluorescence microscopy",
+ "value": "BAO:0000064 | total internal reflection fluorescence microscopy $4ee94c63-256f-4c52-95fb-fdc14fa1ae23",
+ "is_enabled": true,
+ "id": "0000064",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0010264 | biosensor method",
+ "title": "biosensor method",
+ "value": "BAO:0010264 | biosensor method $144a3786-c0c0-4acd-a2cd-319047ede7a2",
+ "is_enabled": true,
+ "id": "0010264",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0050002 | visual observation method",
+ "title": "visual observation method",
+ "value": "BAO:0050002 | visual observation method $b3fe96dd-a355-464b-ae8f-bd976791d700",
+ "is_enabled": true,
+ "id": "0050002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0050003 | simple measurement method",
+ "title": "simple measurement method",
+ "value": "BAO:0050003 | simple measurement method $c2078793-f061-435d-bd5c-6818a7c010f6",
+ "is_enabled": true,
+ "id": "0050003",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002094 | computational method",
+ "title": "computational method",
+ "value": "BAO:0002094 | computational method $57d48dd1-da32-4dfa-81fd-cdef59b897ac",
+ "is_enabled": true,
+ "id": "0002094",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002095 | bioinformatics method",
+ "title": "bioinformatics method",
+ "value": "BAO:0002095 | bioinformatics method $a6fb1a9b-d75e-485d-bae8-279497cfc604",
+ "is_enabled": true,
+ "id": "0002095",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002166 | computational expression analysis",
+ "title": "computational expression analysis",
+ "value": "BAO:0002166 | computational expression analysis $b9cdcfaf-f07a-49a5-bd51-3502f18d4b80",
+ "is_enabled": true,
+ "id": "0002166",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002204 | computational analysis of protein expression",
+ "title": "computational analysis of protein expression",
+ "value": "BAO:0002204 | computational analysis of protein expression $e2ec7595-2860-44cb-8330-de945c3dae59",
+ "is_enabled": true,
+ "id": "0002204",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002203 | computational analysis of gene expression",
+ "title": "computational analysis of gene expression",
+ "value": "BAO:0002203 | computational analysis of gene expression $44e0f406-e07f-4cb8-9e75-93386c950532",
+ "is_enabled": true,
+ "id": "0002203",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002206 | computational phylogenetic analysis",
+ "title": "computational phylogenetic analysis",
+ "value": "BAO:0002206 | computational phylogenetic analysis $fe1c933e-86c6-4bbb-ba41-d9924561f5c4",
+ "is_enabled": true,
+ "id": "0002206",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002208 | SplitsTree phylogenetic analysis",
+ "title": "SplitsTree phylogenetic analysis",
+ "value": "BAO:0002208 | SplitsTree phylogenetic analysis $3e61d393-9b94-475c-b9f1-ecacf7f12822",
+ "is_enabled": true,
+ "id": "0002208",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002209 | Treefinder phylogenetic analysis",
+ "title": "Treefinder phylogenetic analysis",
+ "value": "BAO:0002209 | Treefinder phylogenetic analysis $fe68bce4-877a-430f-b15b-aa80f8ae6f61",
+ "is_enabled": true,
+ "id": "0002209",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002207 | Mesquite phylogenetic analysis",
+ "title": "Mesquite phylogenetic analysis",
+ "value": "BAO:0002207 | Mesquite phylogenetic analysis $a5bef079-91c5-406b-b6c2-e5805ff29637",
+ "is_enabled": true,
+ "id": "0002207",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002211 | phylogeny inference package",
+ "title": "phylogeny inference package",
+ "value": "BAO:0002211 | phylogeny inference package $c37ca5a5-3d55-40cb-98d3-9e6e75f39b27",
+ "is_enabled": true,
+ "id": "0002211",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002210 | phylogenetic analysis using parsimony",
+ "title": "phylogenetic analysis using parsimony",
+ "value": "BAO:0002210 | phylogenetic analysis using parsimony $639bbf58-f2dc-4414-b65d-c99f0b1a205c",
+ "is_enabled": true,
+ "id": "0002210",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002212 | computational structure analysis",
+ "title": "computational structure analysis",
+ "value": "BAO:0002212 | computational structure analysis $451c8b7a-1ac1-4a59-a528-0e7799794f8d",
+ "is_enabled": true,
+ "id": "0002212",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002216 | 3D structure prediction",
+ "title": "3D structure prediction",
+ "value": "BAO:0002216 | 3D structure prediction $3e3587c0-18dc-4b1c-97f1-0ea2954fb1f1",
+ "is_enabled": true,
+ "id": "0002216",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002226 | protein-protein docking",
+ "title": "protein-protein docking",
+ "value": "BAO:0002226 | protein-protein docking $36ad796e-d86d-4af1-b623-74a2c191ab13",
+ "is_enabled": true,
+ "id": "0002226",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002227 | global range molecular matching",
+ "title": "global range molecular matching",
+ "value": "BAO:0002227 | global range molecular matching $2523787e-45ac-458a-8f65-7af740072afc",
+ "is_enabled": true,
+ "id": "0002227",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002224 | protein threading",
+ "title": "protein threading",
+ "value": "BAO:0002224 | protein threading $ef2d26d1-e437-4bf1-b7e5-53e5d79150ef",
+ "is_enabled": true,
+ "id": "0002224",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002225 | RAPTOR protein threading",
+ "title": "RAPTOR protein threading",
+ "value": "BAO:0002225 | RAPTOR protein threading $18af14be-f629-47a0-82d8-fa28df53de4c",
+ "is_enabled": true,
+ "id": "0002225",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002228 | structure alignment",
+ "title": "structure alignment",
+ "value": "BAO:0002228 | structure alignment $97d42396-4fdf-4d36-80ac-5ce31f384346",
+ "is_enabled": true,
+ "id": "0002228",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002229 | distance matrix alignment",
+ "title": "distance matrix alignment",
+ "value": "BAO:0002229 | distance matrix alignment $1d9e8822-6449-4627-8b64-625c9504292c",
+ "is_enabled": true,
+ "id": "0002229",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002230 | matching molecular models obtained from theory",
+ "title": "matching molecular models obtained from theory",
+ "value": "BAO:0002230 | matching molecular models obtained from theory $5f9ccc52-07e0-4fd1-bba8-d663cb795ccb",
+ "is_enabled": true,
+ "id": "0002230",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002221 | homology modeling",
+ "title": "homology modeling",
+ "value": "BAO:0002221 | homology modeling $a90a6b5c-248e-4804-b193-1ffec682cf70",
+ "is_enabled": true,
+ "id": "0002221",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002222 | MODELLER homology modeling",
+ "title": "MODELLER homology modeling",
+ "value": "BAO:0002222 | MODELLER homology modeling $92be5361-f499-4cde-8fd7-57f0cc2ea388",
+ "is_enabled": true,
+ "id": "0002222",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002223 | SwissModel homology modeling",
+ "title": "SwissModel homology modeling",
+ "value": "BAO:0002223 | SwissModel homology modeling $5b7c1e66-d953-4988-b218-7f80f85b2c78",
+ "is_enabled": true,
+ "id": "0002223",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002217 | computational structure solution",
+ "title": "computational structure solution",
+ "value": "BAO:0002217 | computational structure solution $99eefde4-f789-47b5-ba5b-ce9fc6013ff0",
+ "is_enabled": true,
+ "id": "0002217",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002220 | computational electron microscopy structure solution",
+ "title": "computational electron microscopy structure solution",
+ "value": "BAO:0002220 | computational electron microscopy structure solution $9e9ceac9-5806-41cd-ad10-23fabd79c11b",
+ "is_enabled": true,
+ "id": "0002220",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002219 | computational X-ray structure solution",
+ "title": "computational X-ray structure solution",
+ "value": "BAO:0002219 | computational X-ray structure solution $8ffd1c04-d2c8-4aec-a686-728171f84a68",
+ "is_enabled": true,
+ "id": "0002219",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002218 | computational NMR structure solution",
+ "title": "computational NMR structure solution",
+ "value": "BAO:0002218 | computational NMR structure solution $dafc9a67-cb6e-4cba-8837-7c6bd91fac2f",
+ "is_enabled": true,
+ "id": "0002218",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002213 | 2D structure prediction",
+ "title": "2D structure prediction",
+ "value": "BAO:0002213 | 2D structure prediction $7e0857e5-9748-486c-a9d8-f78e953baa8c",
+ "is_enabled": true,
+ "id": "0002213",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002215 | PredictProtein structure prediction",
+ "title": "PredictProtein structure prediction",
+ "value": "BAO:0002215 | PredictProtein structure prediction $ea59aa07-37be-475c-8c9f-9d5c8b0afed6",
+ "is_enabled": true,
+ "id": "0002215",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002214 | PREDATOR structure prediction",
+ "title": "PREDATOR structure prediction",
+ "value": "BAO:0002214 | PREDATOR structure prediction $217482ca-d12f-4f2d-b1e6-a0a91ec98743",
+ "is_enabled": true,
+ "id": "0002214",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002231 | sequence alignment",
+ "title": "sequence alignment",
+ "value": "BAO:0002231 | sequence alignment $050bfcd3-9f6a-4668-ab92-a76b6c837908",
+ "is_enabled": true,
+ "id": "0002231",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002244 | sequence alignment by type",
+ "title": "sequence alignment by type",
+ "value": "BAO:0002244 | sequence alignment by type $4d8e077f-4241-4eb1-98e4-327c18b16b00",
+ "is_enabled": true,
+ "id": "0002244",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002246 | pairwise sequence alignment",
+ "title": "pairwise sequence alignment",
+ "value": "BAO:0002246 | pairwise sequence alignment $0d4b3592-bfe4-42ee-952d-dfacd7321588",
+ "is_enabled": true,
+ "id": "0002246",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002247 | JAligner sequence alignment",
+ "title": "JAligner sequence alignment",
+ "value": "BAO:0002247 | JAligner sequence alignment $7bfffd58-0d29-4a82-9a42-9e0d6a778786",
+ "is_enabled": true,
+ "id": "0002247",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002245 | multiple sequence alignment",
+ "title": "multiple sequence alignment",
+ "value": "BAO:0002245 | multiple sequence alignment $002744db-23a2-448a-89c2-a965ed1cab43",
+ "is_enabled": true,
+ "id": "0002245",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002240 | Clustal sequence alignment",
+ "title": "Clustal sequence alignment",
+ "value": "BAO:0002240 | Clustal sequence alignment $8a245dcf-4485-47b0-9cb5-a3554263e145",
+ "is_enabled": true,
+ "id": "0002240",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002241 | ClustalW sequence alignment",
+ "title": "ClustalW sequence alignment",
+ "value": "BAO:0002241 | ClustalW sequence alignment $dae4ece2-38af-48d5-9ab7-c43b5952fe69",
+ "is_enabled": true,
+ "id": "0002241",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002242 | ClustalX sequence alignment",
+ "title": "ClustalX sequence alignment",
+ "value": "BAO:0002242 | ClustalX sequence alignment $69a5ab5d-5ca2-4ab5-b585-2dbd8b892b4b",
+ "is_enabled": true,
+ "id": "0002242",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002235 | DIALIGN sequence alignment",
+ "title": "DIALIGN sequence alignment",
+ "value": "BAO:0002235 | DIALIGN sequence alignment $09c4e4a7-376a-44a0-a879-296283f3f3e7",
+ "is_enabled": true,
+ "id": "0002235",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002232 | sequence alignment by method",
+ "title": "sequence alignment by method",
+ "value": "BAO:0002232 | sequence alignment by method $a3be1eec-845b-4993-afef-3eb8ea21abd1",
+ "is_enabled": true,
+ "id": "0002232",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002236 | local sequence alignment",
+ "title": "local sequence alignment",
+ "value": "BAO:0002236 | local sequence alignment $d4511ac8-3f0d-49e2-9c71-4d0f32ad454e",
+ "is_enabled": true,
+ "id": "0002236",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002237 | FASTA local sequence alignment",
+ "title": "FASTA local sequence alignment",
+ "value": "BAO:0002237 | FASTA local sequence alignment $8089d880-f958-4de5-9dc7-a3e7d18e4cdd",
+ "is_enabled": true,
+ "id": "0002237",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002238 | basic local alignment search tool",
+ "title": "basic local alignment search tool",
+ "value": "BAO:0002238 | basic local alignment search tool $52b969e9-318b-47fd-863b-cefa867e4faf",
+ "is_enabled": true,
+ "id": "0002238",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002239 | progressive system alignment",
+ "title": "progressive system alignment",
+ "value": "BAO:0002239 | progressive system alignment $ce7a95d2-8cb9-4794-bf2c-0bf39e94b93e",
+ "is_enabled": true,
+ "id": "0002239",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002240 | Clustal sequence alignment",
+ "title": "Clustal sequence alignment",
+ "value": "BAO:0002240 | Clustal sequence alignment $828be5fb-649b-42bd-af6b-8704944b9783",
+ "is_enabled": true,
+ "id": "0002240",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002241 | ClustalW sequence alignment",
+ "title": "ClustalW sequence alignment",
+ "value": "BAO:0002241 | ClustalW sequence alignment $7d3cc049-42fd-43cb-9b65-b0e58329310c",
+ "is_enabled": true,
+ "id": "0002241",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002242 | ClustalX sequence alignment",
+ "title": "ClustalX sequence alignment",
+ "value": "BAO:0002242 | ClustalX sequence alignment $32be6fdb-500e-4dc3-a2a4-50846df52f17",
+ "is_enabled": true,
+ "id": "0002242",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002243 | MAVID sequence alignment",
+ "title": "MAVID sequence alignment",
+ "value": "BAO:0002243 | MAVID sequence alignment $592ca106-64cf-462b-81e5-f9ac92f6abba",
+ "is_enabled": true,
+ "id": "0002243",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002233 | global sequence alignment",
+ "title": "global sequence alignment",
+ "value": "BAO:0002233 | global sequence alignment $97ab2b6f-9519-4827-b0b8-e182d4f21ffd",
+ "is_enabled": true,
+ "id": "0002233",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002235 | DIALIGN sequence alignment",
+ "title": "DIALIGN sequence alignment",
+ "value": "BAO:0002235 | DIALIGN sequence alignment $02fdf705-c572-43cf-b077-e3c87332c2db",
+ "is_enabled": true,
+ "id": "0002235",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002234 | AVID sequence alignment",
+ "title": "AVID sequence alignment",
+ "value": "BAO:0002234 | AVID sequence alignment $0f97b1c2-4011-4ef9-9386-a163a2ba2adc",
+ "is_enabled": true,
+ "id": "0002234",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002305 | quantitative structure activity relationship analysis",
+ "title": "quantitative structure activity relationship analysis",
+ "value": "BAO:0002305 | quantitative structure activity relationship analysis $de3b65d1-b66b-4ea7-881a-809c9cae2a05",
+ "is_enabled": true,
+ "id": "0002305",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002309 | non-linear QSAR",
+ "title": "non-linear QSAR",
+ "value": "BAO:0002309 | non-linear QSAR $51e866ae-4a93-4ca2-8647-cef7f3dd498d",
+ "is_enabled": true,
+ "id": "0002309",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002310 | neural network QSAR",
+ "title": "neural network QSAR",
+ "value": "BAO:0002310 | neural network QSAR $c8a9ef70-465e-4faf-87b4-8cdcccc7a7d3",
+ "is_enabled": true,
+ "id": "0002310",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002311 | recursive partitioning QSAR",
+ "title": "recursive partitioning QSAR",
+ "value": "BAO:0002311 | recursive partitioning QSAR $8a445192-f3ba-46f4-b041-c2abdf9d5ef2",
+ "is_enabled": true,
+ "id": "0002311",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002306 | linear QSAR",
+ "title": "linear QSAR",
+ "value": "BAO:0002306 | linear QSAR $b2338126-7218-4f54-aeb7-777c1fb91ee0",
+ "is_enabled": true,
+ "id": "0002306",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002307 | partial least squares QSAR",
+ "title": "partial least squares QSAR",
+ "value": "BAO:0002307 | partial least squares QSAR $4be3c176-b898-46f7-86da-fbfefecd953d",
+ "is_enabled": true,
+ "id": "0002307",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002308 | regression QSAR",
+ "title": "regression QSAR",
+ "value": "BAO:0002308 | regression QSAR $35707143-3278-492f-a8d2-57fa010a6bee",
+ "is_enabled": true,
+ "id": "0002308",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002312 | three dimensional QSAR",
+ "title": "three dimensional QSAR",
+ "value": "BAO:0002312 | three dimensional QSAR $148bd3e5-6175-4324-b4f5-99de345531a4",
+ "is_enabled": true,
+ "id": "0002312",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002314 | comparative molecular similarity indices analysis",
+ "title": "comparative molecular similarity indices analysis",
+ "value": "BAO:0002314 | comparative molecular similarity indices analysis $c80015c5-e576-4448-a08a-b08dd6f5662f",
+ "is_enabled": true,
+ "id": "0002314",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002315 | self organizing molecular field analysis",
+ "title": "self organizing molecular field analysis",
+ "value": "BAO:0002315 | self organizing molecular field analysis $335b676e-50cb-4b86-b8c9-413cda014f3f",
+ "is_enabled": true,
+ "id": "0002315",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002313 | comparative molecular field analysis",
+ "title": "comparative molecular field analysis",
+ "value": "BAO:0002313 | comparative molecular field analysis $3d7a572a-065d-479d-8f6b-10efd7d39de2",
+ "is_enabled": true,
+ "id": "0002313",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002316 | two dimensional QSAR",
+ "title": "two dimensional QSAR",
+ "value": "BAO:0002316 | two dimensional QSAR $b8c7dee6-44fb-4855-9ed5-581cb2c5e1ff",
+ "is_enabled": true,
+ "id": "0002316",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002317 | quantum chemistry computational method",
+ "title": "quantum chemistry computational method",
+ "value": "BAO:0002317 | quantum chemistry computational method $366bf0cb-007b-4e95-816e-f8ef7dd3ec54",
+ "is_enabled": true,
+ "id": "0002317",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002326 | semi-empirical quantum chemistry computational method",
+ "title": "semi-empirical quantum chemistry computational method",
+ "value": "BAO:0002326 | semi-empirical quantum chemistry computational method $0e4b9ec5-9d9d-4c77-9a5e-c302cf505aed",
+ "is_enabled": true,
+ "id": "0002326",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002329 | valence electron computational method",
+ "title": "valence electron computational method",
+ "value": "BAO:0002329 | valence electron computational method $e1a96e6c-79a7-49fa-8583-a98e8509ae80",
+ "is_enabled": true,
+ "id": "0002329",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002334 | parameterized model number 3",
+ "title": "parameterized model number 3",
+ "value": "BAO:0002334 | parameterized model number 3 $d7e77fa3-4cb1-445c-93dc-a75389e4ad8d",
+ "is_enabled": true,
+ "id": "0002334",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002332 | intermediate neglect of differential overlap",
+ "title": "intermediate neglect of differential overlap",
+ "value": "BAO:0002332 | intermediate neglect of differential overlap $baf9531c-2232-4935-a47b-7745ccb29bf1",
+ "is_enabled": true,
+ "id": "0002332",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002333 | modified neglect of differential overlap",
+ "title": "modified neglect of differential overlap",
+ "value": "BAO:0002333 | modified neglect of differential overlap $5c0207fb-6f5f-4287-ad12-ac5174905207",
+ "is_enabled": true,
+ "id": "0002333",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002330 | Zerner's intermediate neglect of differential overlap",
+ "title": "Zerner's intermediate neglect of differential overlap",
+ "value": "BAO:0002330 | Zerner's intermediate neglect of differential overlap $91998d55-baca-4e98-a13e-5a9b2dcc3ea0",
+ "is_enabled": true,
+ "id": "0002330",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002331 | austin model 1",
+ "title": "austin model 1",
+ "value": "BAO:0002331 | austin model 1 $8fbb4245-0fb0-4b42-8267-9215d1b94e5b",
+ "is_enabled": true,
+ "id": "0002331",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002327 | pi-electron computational method",
+ "title": "pi-electron computational method",
+ "value": "BAO:0002327 | pi-electron computational method $7e3033b2-7731-4043-af55-c79b7297eb4f",
+ "is_enabled": true,
+ "id": "0002327",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002328 | Pariser Parr Pople method",
+ "title": "Pariser Parr Pople method",
+ "value": "BAO:0002328 | Pariser Parr Pople method $bd680231-735a-4fdd-afe3-23358e3c4cb7",
+ "is_enabled": true,
+ "id": "0002328",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002318 | ab initio quantum chemistry computational method",
+ "title": "ab initio quantum chemistry computational method",
+ "value": "BAO:0002318 | ab initio quantum chemistry computational method $aa121405-1ba4-4672-9084-74a26bec8218",
+ "is_enabled": true,
+ "id": "0002318",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002322 | post Hartree-Fock method",
+ "title": "post Hartree-Fock method",
+ "value": "BAO:0002322 | post Hartree-Fock method $011a5582-8185-41ec-a033-71572bd421ba",
+ "is_enabled": true,
+ "id": "0002322",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002325 | quadratic configuration interaction method",
+ "title": "quadratic configuration interaction method",
+ "value": "BAO:0002325 | quadratic configuration interaction method $912c125a-33da-4111-9234-add5942467b7",
+ "is_enabled": true,
+ "id": "0002325",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002323 | configuration interaction method",
+ "title": "configuration interaction method",
+ "value": "BAO:0002323 | configuration interaction method $df5e4515-9c23-4925-8bb5-33feddde5669",
+ "is_enabled": true,
+ "id": "0002323",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002324 | coupled cluster method",
+ "title": "coupled cluster method",
+ "value": "BAO:0002324 | coupled cluster method $2e005f19-043e-4e43-be81-1b3fcbe4eb10",
+ "is_enabled": true,
+ "id": "0002324",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002319 | Hartree-Fock method",
+ "title": "Hartree-Fock method",
+ "value": "BAO:0002319 | Hartree-Fock method $fe3b3f15-ddc2-41db-9caa-bca3162a74f9",
+ "is_enabled": true,
+ "id": "0002319",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002321 | unrestricted Hartree-Fock",
+ "title": "unrestricted Hartree-Fock",
+ "value": "BAO:0002321 | unrestricted Hartree-Fock $55177296-0225-40d0-9e98-3789cbc294d7",
+ "is_enabled": true,
+ "id": "0002321",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002320 | restricted open-shell Hartree-Fock",
+ "title": "restricted open-shell Hartree-Fock",
+ "value": "BAO:0002320 | restricted open-shell Hartree-Fock $5e5474b7-2578-4d1f-b091-7941583bd44d",
+ "is_enabled": true,
+ "id": "0002320",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002347 | systems biology method",
+ "title": "systems biology method",
+ "value": "BAO:0002347 | systems biology method $f63a1b0f-c5a4-496a-8afd-d5bf2e0cbc78",
+ "is_enabled": true,
+ "id": "0002347",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002348 | pathway analysis",
+ "title": "pathway analysis",
+ "value": "BAO:0002348 | pathway analysis $51aeeaa6-244a-46fd-a0af-3ca07254edc3",
+ "is_enabled": true,
+ "id": "0002348",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002349 | pathway analysis by knowledge base",
+ "title": "pathway analysis by knowledge base",
+ "value": "BAO:0002349 | pathway analysis by knowledge base $a070ae2c-8208-44ac-a5eb-0a9304c475a5",
+ "is_enabled": true,
+ "id": "0002349",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002350 | automatic pathway analysis",
+ "title": "automatic pathway analysis",
+ "value": "BAO:0002350 | automatic pathway analysis $36d901db-8621-47b4-9eec-130a6fcf61ca",
+ "is_enabled": true,
+ "id": "0002350",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002351 | natural language processing",
+ "title": "natural language processing",
+ "value": "BAO:0002351 | natural language processing $03b84bdb-c970-418a-8e2a-0b0fbc547556",
+ "is_enabled": true,
+ "id": "0002351",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002352 | Ariadne Pathway Studio",
+ "title": "Ariadne Pathway Studio",
+ "value": "BAO:0002352 | Ariadne Pathway Studio $4c7caf33-b0ad-4947-894e-bf859331cd0d",
+ "is_enabled": true,
+ "id": "0002352",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002353 | pathway analysis by method",
+ "title": "pathway analysis by method",
+ "value": "BAO:0002353 | pathway analysis by method $b57ede6a-e11d-4cca-a22e-e66593b6d247",
+ "is_enabled": true,
+ "id": "0002353",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002361 | network analysis",
+ "title": "network analysis",
+ "value": "BAO:0002361 | network analysis $70ca3f93-1267-45f4-ba8b-9905e7264c4c",
+ "is_enabled": true,
+ "id": "0002361",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002362 | Cytoscape network analysis",
+ "title": "Cytoscape network analysis",
+ "value": "BAO:0002362 | Cytoscape network analysis $f9bcfca9-3156-4be8-a3e1-73c369f3da2b",
+ "is_enabled": true,
+ "id": "0002362",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002359 | integrated pathway analysis",
+ "title": "integrated pathway analysis",
+ "value": "BAO:0002359 | integrated pathway analysis $c40295ce-4143-439c-99a4-366fa970e314",
+ "is_enabled": true,
+ "id": "0002359",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002360 | MetaDiscovery pathway analysis",
+ "title": "MetaDiscovery pathway analysis",
+ "value": "BAO:0002360 | MetaDiscovery pathway analysis $16923825-5e05-4746-876a-a4503c57c0dd",
+ "is_enabled": true,
+ "id": "0002360",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002354 | gene list enrichment analysis",
+ "title": "gene list enrichment analysis",
+ "value": "BAO:0002354 | gene list enrichment analysis $fb836e7e-cddf-401c-b4d1-e237c7c8b797",
+ "is_enabled": true,
+ "id": "0002354",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002358 | Onto-Express enrichment analysis",
+ "title": "Onto-Express enrichment analysis",
+ "value": "BAO:0002358 | Onto-Express enrichment analysis $e2eaae03-3117-44fb-999d-ea61d147d2a5",
+ "is_enabled": true,
+ "id": "0002358",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002356 | GSEA-P enrichment analysis",
+ "title": "GSEA-P enrichment analysis",
+ "value": "BAO:0002356 | GSEA-P enrichment analysis $78a10e56-130e-48f3-9816-3cc95a2ce620",
+ "is_enabled": true,
+ "id": "0002356",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002357 | GeneTrail enrichment analysis",
+ "title": "GeneTrail enrichment analysis",
+ "value": "BAO:0002357 | GeneTrail enrichment analysis $221e7bb8-4f47-456d-aef8-644389fb901b",
+ "is_enabled": true,
+ "id": "0002357",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002355 | GOstat enrichment analysis",
+ "title": "GOstat enrichment analysis",
+ "value": "BAO:0002355 | GOstat enrichment analysis $1da52d05-c0cd-4e53-bd02-a45bcffbdb04",
+ "is_enabled": true,
+ "id": "0002355",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002363 | target family knowledge analysis",
+ "title": "target family knowledge analysis",
+ "value": "BAO:0002363 | target family knowledge analysis $aded55a5-9221-4d7d-a50c-0b1e53a9a20a",
+ "is_enabled": true,
+ "id": "0002363",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002335 | statistical method",
+ "title": "statistical method",
+ "value": "BAO:0002335 | statistical method $21f7b038-157b-4fa6-a2e8-da899eb5d1f5",
+ "is_enabled": true,
+ "id": "0002335",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002341 | statistical classification method",
+ "title": "statistical classification method",
+ "value": "BAO:0002341 | statistical classification method $52097a62-70a1-4fde-89c5-d682bf1b8888",
+ "is_enabled": true,
+ "id": "0002341",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002345 | neural network model",
+ "title": "neural network model",
+ "value": "BAO:0002345 | neural network model $096df574-9a89-4e1c-ade5-50704f187151",
+ "is_enabled": true,
+ "id": "0002345",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002346 | principal component analysis",
+ "title": "principal component analysis",
+ "value": "BAO:0002346 | principal component analysis $aa1c2c37-b3e1-46ba-9596-a6650f5d99f1",
+ "is_enabled": true,
+ "id": "0002346",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002343 | hierarchial clustering",
+ "title": "hierarchial clustering",
+ "value": "BAO:0002343 | hierarchial clustering $bf9fb6fe-3620-4c63-85cb-70f4b2092678",
+ "is_enabled": true,
+ "id": "0002343",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002344 | k means clustering",
+ "title": "k means clustering",
+ "value": "BAO:0002344 | k means clustering $c91fcb9c-8f62-4d50-b455-2ea98a7e7a26",
+ "is_enabled": true,
+ "id": "0002344",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002342 | decision tree",
+ "title": "decision tree",
+ "value": "BAO:0002342 | decision tree $5bfd0374-aca0-4b16-a3b5-cfe3072e3dbd",
+ "is_enabled": true,
+ "id": "0002342",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002336 | experimental design method",
+ "title": "experimental design method",
+ "value": "BAO:0002336 | experimental design method $a75ba048-8b41-4a5c-a9f4-969c2e8d5772",
+ "is_enabled": true,
+ "id": "0002336",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002340 | randomized block design",
+ "title": "randomized block design",
+ "value": "BAO:0002340 | randomized block design $08f4df58-2583-4278-b4de-ead4ed84dbe2",
+ "is_enabled": true,
+ "id": "0002340",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002337 | completely randomized design",
+ "title": "completely randomized design",
+ "value": "BAO:0002337 | completely randomized design $b5d56649-21db-4b8a-892e-418e60fe9359",
+ "is_enabled": true,
+ "id": "0002337",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002338 | fractional factorial design",
+ "title": "fractional factorial design",
+ "value": "BAO:0002338 | fractional factorial design $dc56d153-30a7-4445-8c7e-49b8e53fe38b",
+ "is_enabled": true,
+ "id": "0002338",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002339 | full factorial design",
+ "title": "full factorial design",
+ "value": "BAO:0002339 | full factorial design $d6efc39e-40e7-4505-8a9d-bc90162f5c8a",
+ "is_enabled": true,
+ "id": "0002339",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002364 | virtual screening",
+ "title": "virtual screening",
+ "value": "BAO:0002364 | virtual screening $f12eda90-3655-43ad-873c-b3b715d8b5c4",
+ "is_enabled": true,
+ "id": "0002364",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002365 | ligand based virtual screening",
+ "title": "ligand based virtual screening",
+ "value": "BAO:0002365 | ligand based virtual screening $51462084-3807-4d65-96c9-ed6eede137f9",
+ "is_enabled": true,
+ "id": "0002365",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002366 | ligand based pharmacophore model",
+ "title": "ligand based pharmacophore model",
+ "value": "BAO:0002366 | ligand based pharmacophore model $d26f8b08-48e9-4dad-a9e2-53d05b0ffef0",
+ "is_enabled": true,
+ "id": "0002366",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002369 | distance comparison modeling",
+ "title": "distance comparison modeling",
+ "value": "BAO:0002369 | distance comparison modeling $4bf01078-8a5b-49cf-b3c7-a43c91bb02c8",
+ "is_enabled": true,
+ "id": "0002369",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002367 | Catalyst modeling",
+ "title": "Catalyst modeling",
+ "value": "BAO:0002367 | Catalyst modeling $4f31fe4f-ebcb-4468-bdcc-d9e1a3fb01ac",
+ "is_enabled": true,
+ "id": "0002367",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002368 | DISCOtech modeling",
+ "title": "DISCOtech modeling",
+ "value": "BAO:0002368 | DISCOtech modeling $3fc24737-4975-4712-9d1f-2a95333b5727",
+ "is_enabled": true,
+ "id": "0002368",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002370 | genetic algorithm similary program",
+ "title": "genetic algorithm similary program",
+ "value": "BAO:0002370 | genetic algorithm similary program $09ad0b96-5f1c-4d83-b918-197b2220b368",
+ "is_enabled": true,
+ "id": "0002370",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002371 | scaffold hopping",
+ "title": "scaffold hopping",
+ "value": "BAO:0002371 | scaffold hopping $af579018-ccc8-47d0-9380-b5b2ce71587a",
+ "is_enabled": true,
+ "id": "0002371",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002261 | 2D structure similarity search",
+ "title": "2D structure similarity search",
+ "value": "BAO:0002261 | 2D structure similarity search $fd51e3ee-ab3a-444a-84c0-0152b64a038a",
+ "is_enabled": true,
+ "id": "0002261",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002262 | MACCS key",
+ "title": "MACCS key",
+ "value": "BAO:0002262 | MACCS key $7581b88c-54dd-4c5c-959c-300edbdda2b6",
+ "is_enabled": true,
+ "id": "0002262",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002263 | circular fingerprint search",
+ "title": "circular fingerprint search",
+ "value": "BAO:0002263 | circular fingerprint search $a1f692e5-3da4-4b2a-95c0-206258ae250e",
+ "is_enabled": true,
+ "id": "0002263",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002264 | 3D structure similarity search",
+ "title": "3D structure similarity search",
+ "value": "BAO:0002264 | 3D structure similarity search $3a9610ea-2efd-4501-9bd8-4bd6d1f74750",
+ "is_enabled": true,
+ "id": "0002264",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002267 | topomer search",
+ "title": "topomer search",
+ "value": "BAO:0002267 | topomer search $d8351ff8-a19d-494a-8f38-330975758ddd",
+ "is_enabled": true,
+ "id": "0002267",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002265 | shape fingerprint search",
+ "title": "shape fingerprint search",
+ "value": "BAO:0002265 | shape fingerprint search $8b6bf295-0fa2-4cc3-ac95-86fb7a3f306b",
+ "is_enabled": true,
+ "id": "0002265",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002266 | rapid overlay of chemical structures",
+ "title": "rapid overlay of chemical structures",
+ "value": "BAO:0002266 | rapid overlay of chemical structures $272e52a6-6b55-432f-8680-0c9a6ea9d0f7",
+ "is_enabled": true,
+ "id": "0002266",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002372 | structure based virtual screening",
+ "title": "structure based virtual screening",
+ "value": "BAO:0002372 | structure based virtual screening $07dc875f-eba0-4924-b00d-9abad7ee2bc3",
+ "is_enabled": true,
+ "id": "0002372",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002373 | molecular docking",
+ "title": "molecular docking",
+ "value": "BAO:0002373 | molecular docking $fd0473b8-1fb7-4683-951b-80bc79c42057",
+ "is_enabled": true,
+ "id": "0002373",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002393 | molecular docking by scoring function",
+ "title": "molecular docking by scoring function",
+ "value": "BAO:0002393 | molecular docking by scoring function $b828f46b-8d88-488e-9dc4-535e967de8f9",
+ "is_enabled": true,
+ "id": "0002393",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002394 | empirical scoring function",
+ "title": "empirical scoring function",
+ "value": "BAO:0002394 | empirical scoring function $567c901c-24b7-4eb7-a29b-f297ace8d83d",
+ "is_enabled": true,
+ "id": "0002394",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002395 | AutoDock3 scoring function",
+ "title": "AutoDock3 scoring function",
+ "value": "BAO:0002395 | AutoDock3 scoring function $72fac2c0-e7a2-4c38-b3bb-9515f982429f",
+ "is_enabled": true,
+ "id": "0002395",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002396 | FLOG scoring function",
+ "title": "FLOG scoring function",
+ "value": "BAO:0002396 | FLOG scoring function $4ddce0cf-6b35-4cf3-acaa-938cace11dbc",
+ "is_enabled": true,
+ "id": "0002396",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002397 | GOLD scoring function",
+ "title": "GOLD scoring function",
+ "value": "BAO:0002397 | GOLD scoring function $82f087c5-a589-42f9-ac39-487fea2b9039",
+ "is_enabled": true,
+ "id": "0002397",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002398 | force field based scoring function",
+ "title": "force field based scoring function",
+ "value": "BAO:0002398 | force field based scoring function $62a19dde-0a09-4f57-a9be-c6adcbcb038a",
+ "is_enabled": true,
+ "id": "0002398",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002286 | CHARMM force field simulation",
+ "title": "CHARMM force field simulation",
+ "value": "BAO:0002286 | CHARMM force field simulation $7180645d-84ae-4de5-9a74-a59c03302ed4",
+ "is_enabled": true,
+ "id": "0002286",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002402 | knowledge based scoring function",
+ "title": "knowledge based scoring function",
+ "value": "BAO:0002402 | knowledge based scoring function $846ee718-4e78-4268-b71d-730f63b433c9",
+ "is_enabled": true,
+ "id": "0002402",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002403 | DrugScore scoring function",
+ "title": "DrugScore scoring function",
+ "value": "BAO:0002403 | DrugScore scoring function $c8f1bbaf-a347-4b0e-b2e6-65bcc25493d0",
+ "is_enabled": true,
+ "id": "0002403",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002404 | potentials of mean force scoring function",
+ "title": "potentials of mean force scoring function",
+ "value": "BAO:0002404 | potentials of mean force scoring function $07623734-c472-414b-a28b-22143188dbcd",
+ "is_enabled": true,
+ "id": "0002404",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002374 | molecular docking by method",
+ "title": "molecular docking by method",
+ "value": "BAO:0002374 | molecular docking by method $0b8367be-26d5-404c-a935-395dd615d3ad",
+ "is_enabled": true,
+ "id": "0002374",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002391 | tabu docking method",
+ "title": "tabu docking method",
+ "value": "BAO:0002391 | tabu docking method $28d72050-e0a5-4868-8bb4-eda99e3194f9",
+ "is_enabled": true,
+ "id": "0002391",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002392 | SFdock docking method",
+ "title": "SFdock docking method",
+ "value": "BAO:0002392 | SFdock docking method $3347da9f-fcb7-468c-a582-37330387b0d0",
+ "is_enabled": true,
+ "id": "0002392",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002383 | genetic algorithm method",
+ "title": "genetic algorithm method",
+ "value": "BAO:0002383 | genetic algorithm method $e0fc2978-a9b9-44d7-9ce5-5c41abe864e2",
+ "is_enabled": true,
+ "id": "0002383",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002384 | AutoDock3 docking method",
+ "title": "AutoDock3 docking method",
+ "value": "BAO:0002384 | AutoDock3 docking method $bbfe7e98-fbdb-4d5c-b838-0e4386291ea5",
+ "is_enabled": true,
+ "id": "0002384",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002385 | DARWIN docking method",
+ "title": "DARWIN docking method",
+ "value": "BAO:0002385 | DARWIN docking method $905316e4-9557-4079-8d1f-63cc4548b9bd",
+ "is_enabled": true,
+ "id": "0002385",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002386 | GOLD docking method",
+ "title": "GOLD docking method",
+ "value": "BAO:0002386 | GOLD docking method $3f33c210-455d-4d32-aef4-2fa3f733beaf",
+ "is_enabled": true,
+ "id": "0002386",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002387 | incremental construction method",
+ "title": "incremental construction method",
+ "value": "BAO:0002387 | incremental construction method $63829b3b-7cdb-4438-829d-db0a06b603a0",
+ "is_enabled": true,
+ "id": "0002387",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002390 | Hummerhead docking method",
+ "title": "Hummerhead docking method",
+ "value": "BAO:0002390 | Hummerhead docking method $25c07123-cae1-4f65-9044-ff99ea1b8b8f",
+ "is_enabled": true,
+ "id": "0002390",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002389 | FlexX docking method",
+ "title": "FlexX docking method",
+ "value": "BAO:0002389 | FlexX docking method $e01b71c1-3790-46af-aa85-cd11a9f911c8",
+ "is_enabled": true,
+ "id": "0002389",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002388 | DOCK4 docking method",
+ "title": "DOCK4 docking method",
+ "value": "BAO:0002388 | DOCK4 docking method $cf5caeab-6288-475c-8115-8ba819d907b6",
+ "is_enabled": true,
+ "id": "0002388",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002379 | descriptor matching method",
+ "title": "descriptor matching method",
+ "value": "BAO:0002379 | descriptor matching method $27827129-509f-4e64-8d9e-11abcd948eea",
+ "is_enabled": true,
+ "id": "0002379",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002381 | DOCK docking method",
+ "title": "DOCK docking method",
+ "value": "BAO:0002381 | DOCK docking method $271f6553-3376-416e-8f33-0aa64822564b",
+ "is_enabled": true,
+ "id": "0002381",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002382 | SLIDE docking method",
+ "title": "SLIDE docking method",
+ "value": "BAO:0002382 | SLIDE docking method $efff3760-869f-4346-82f4-5d730b7593e4",
+ "is_enabled": true,
+ "id": "0002382",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002380 | ADAM docking method",
+ "title": "ADAM docking method",
+ "value": "BAO:0002380 | ADAM docking method $8b753f36-eaca-4c13-9747-df36743cc851",
+ "is_enabled": true,
+ "id": "0002380",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002377 | Monte Carlo simulated annealing",
+ "title": "Monte Carlo simulated annealing",
+ "value": "BAO:0002377 | Monte Carlo simulated annealing $696d2e57-909b-41f4-97e9-c0f67ea4f51d",
+ "is_enabled": true,
+ "id": "0002377",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002378 | AutoDock docking method",
+ "title": "AutoDock docking method",
+ "value": "BAO:0002378 | AutoDock docking method $c1b9d4b7-65ed-42cf-accb-f13c32db9d8b",
+ "is_enabled": true,
+ "id": "0002378",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002375 | Monte Carlo minimization method",
+ "title": "Monte Carlo minimization method",
+ "value": "BAO:0002375 | Monte Carlo minimization method $6f2e68bb-159f-4092-bf1e-39c185d5df50",
+ "is_enabled": true,
+ "id": "0002375",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002376 | internal coordinate mechanics method",
+ "title": "internal coordinate mechanics method",
+ "value": "BAO:0002376 | internal coordinate mechanics method $a2ca2ae8-3521-4127-965e-ee4587781e17",
+ "is_enabled": true,
+ "id": "0002376",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002405 | receptor based pharmacophore search",
+ "title": "receptor based pharmacophore search",
+ "value": "BAO:0002405 | receptor based pharmacophore search $d1d9978b-98a0-4d37-b2a6-5ce6eec7e223",
+ "is_enabled": true,
+ "id": "0002405",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002408 | SPROUT pharmacophore search",
+ "title": "SPROUT pharmacophore search",
+ "value": "BAO:0002408 | SPROUT pharmacophore search $c98db898-82ef-4117-bbe6-e0de0f521f4d",
+ "is_enabled": true,
+ "id": "0002408",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002406 | CoMFA pharmacophore search",
+ "title": "CoMFA pharmacophore search",
+ "value": "BAO:0002406 | CoMFA pharmacophore search $4d8daae7-e0ab-44be-b5b4-0381645cf1cd",
+ "is_enabled": true,
+ "id": "0002406",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002407 | GRID pharmacophore search",
+ "title": "GRID pharmacophore search",
+ "value": "BAO:0002407 | GRID pharmacophore search $365a8a59-16c8-42b3-93af-fbd48a7f138a",
+ "is_enabled": true,
+ "id": "0002407",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002282 | computer simulation method",
+ "title": "computer simulation method",
+ "value": "BAO:0002282 | computer simulation method $ad6a21f7-a8ce-4d96-83cc-9c2ed62f34c8",
+ "is_enabled": true,
+ "id": "0002282",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002303 | stochastic simulation",
+ "title": "stochastic simulation",
+ "value": "BAO:0002303 | stochastic simulation $15f08e7f-fabf-4214-9785-5cfa58a3320d",
+ "is_enabled": true,
+ "id": "0002303",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002304 | Monte Carlo simulation",
+ "title": "Monte Carlo simulation",
+ "value": "BAO:0002304 | Monte Carlo simulation $29f96e80-a27c-42d8-9711-d7326f8da842",
+ "is_enabled": true,
+ "id": "0002304",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002301 | molecular dynamics simulation",
+ "title": "molecular dynamics simulation",
+ "value": "BAO:0002301 | molecular dynamics simulation $2c685fcc-be09-4d7a-bc2e-2da62a6be467",
+ "is_enabled": true,
+ "id": "0002301",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002302 | constraint molecular dynamics simulation",
+ "title": "constraint molecular dynamics simulation",
+ "value": "BAO:0002302 | constraint molecular dynamics simulation $fb53b317-d7de-40f0-a9eb-e5c9fe97629f",
+ "is_enabled": true,
+ "id": "0002302",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002283 | computer simulation method by force field",
+ "title": "computer simulation method by force field",
+ "value": "BAO:0002283 | computer simulation method by force field $09f320b3-06a3-40cf-a5d2-f67eeb1e50f5",
+ "is_enabled": true,
+ "id": "0002283",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002284 | classical force field simulation",
+ "title": "classical force field simulation",
+ "value": "BAO:0002284 | classical force field simulation $3a3185ac-d115-44bf-95d8-089528c6f732",
+ "is_enabled": true,
+ "id": "0002284",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002285 | AMBER force field simulation",
+ "title": "AMBER force field simulation",
+ "value": "BAO:0002285 | AMBER force field simulation $d1276f76-1373-46ff-ac17-827c06ef7e1e",
+ "is_enabled": true,
+ "id": "0002285",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002286 | CHARMM force field simulation",
+ "title": "CHARMM force field simulation",
+ "value": "BAO:0002286 | CHARMM force field simulation $c35fac5c-354a-4ec2-bd03-71ea8e4412c2",
+ "is_enabled": true,
+ "id": "0002286",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002287 | GROMOS force field simulation",
+ "title": "GROMOS force field simulation",
+ "value": "BAO:0002287 | GROMOS force field simulation $9f3c83dd-26a7-4b94-8ae0-b46403b26678",
+ "is_enabled": true,
+ "id": "0002287",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002288 | polarizable force field simulation",
+ "title": "polarizable force field simulation",
+ "value": "BAO:0002288 | polarizable force field simulation $e777a7db-dd25-4309-b698-72a7734564be",
+ "is_enabled": true,
+ "id": "0002288",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002399 | AMBER polarizable",
+ "title": "AMBER polarizable",
+ "value": "BAO:0002399 | AMBER polarizable $9d86507c-31e2-40b9-bd71-138285bef4c4",
+ "is_enabled": true,
+ "id": "0002399",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002400 | CHARMM polarizable",
+ "title": "CHARMM polarizable",
+ "value": "BAO:0002400 | CHARMM polarizable $4cf9605e-782b-4b20-a265-6d0c9147d2ee",
+ "is_enabled": true,
+ "id": "0002400",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002289 | second generation force field simulation",
+ "title": "second generation force field simulation",
+ "value": "BAO:0002289 | second generation force field simulation $4f255602-b34b-487f-b3ca-7b63d627eeef",
+ "is_enabled": true,
+ "id": "0002289",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002291 | MM4 force field simulation",
+ "title": "MM4 force field simulation",
+ "value": "BAO:0002291 | MM4 force field simulation $6daf79e0-71d6-442d-820d-624ad6b415d8",
+ "is_enabled": true,
+ "id": "0002291",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002292 | MMFF force field simulation",
+ "title": "MMFF force field simulation",
+ "value": "BAO:0002292 | MMFF force field simulation $2742343d-18ba-4bd8-8d29-8ebf7c1e8b1b",
+ "is_enabled": true,
+ "id": "0002292",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002290 | CFF force field simulation",
+ "title": "CFF force field simulation",
+ "value": "BAO:0002290 | CFF force field simulation $b8c916f9-85dc-4577-9f16-efdf5620ea90",
+ "is_enabled": true,
+ "id": "0002290",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002296 | local minimum search",
+ "title": "local minimum search",
+ "value": "BAO:0002296 | local minimum search $ce185820-1d0f-4fd7-b31c-5afa48c40cd9",
+ "is_enabled": true,
+ "id": "0002296",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002297 | energy minimization method",
+ "title": "energy minimization method",
+ "value": "BAO:0002297 | energy minimization method $bc344243-f513-408e-8f88-366b43415418",
+ "is_enabled": true,
+ "id": "0002297",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002300 | steepest descent method",
+ "title": "steepest descent method",
+ "value": "BAO:0002300 | steepest descent method $43a921e1-b6b9-4fda-b1f3-f37bdbabd645",
+ "is_enabled": true,
+ "id": "0002300",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002299 | conjugate gradient method",
+ "title": "conjugate gradient method",
+ "value": "BAO:0002299 | conjugate gradient method $ba638525-e9b8-4115-96ad-31d825dd720a",
+ "is_enabled": true,
+ "id": "0002299",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002298 | Newton-Raphson method",
+ "title": "Newton-Raphson method",
+ "value": "BAO:0002298 | Newton-Raphson method $0cdda7f5-657a-4e5f-aa9b-f2b8c038e377",
+ "is_enabled": true,
+ "id": "0002298",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002293 | global minimum search",
+ "title": "global minimum search",
+ "value": "BAO:0002293 | global minimum search $0f1be21a-1389-487c-b1b9-2940902bedb5",
+ "is_enabled": true,
+ "id": "0002293",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002295 | simulated annealing",
+ "title": "simulated annealing",
+ "value": "BAO:0002295 | simulated annealing $39abbd66-62c4-42ea-8cf3-c6c999d0af09",
+ "is_enabled": true,
+ "id": "0002295",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002294 | genetic algorithm search",
+ "title": "genetic algorithm search",
+ "value": "BAO:0002294 | genetic algorithm search $2178fa53-bd8f-4494-8dc7-83f0f8b61265",
+ "is_enabled": true,
+ "id": "0002294",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002248 | cheminformatics method",
+ "title": "cheminformatics method",
+ "value": "BAO:0002248 | cheminformatics method $67137240-db72-4963-8a06-e2443c485f74",
+ "is_enabled": true,
+ "id": "0002248",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002249 | conformational search",
+ "title": "conformational search",
+ "value": "BAO:0002249 | conformational search $0b1650c7-c19a-4b9b-a0b1-3147429e08d7",
+ "is_enabled": true,
+ "id": "0002249",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002251 | random conformational search",
+ "title": "random conformational search",
+ "value": "BAO:0002251 | random conformational search $82562385-d3f5-4406-a0d7-dc17cb4c94b1",
+ "is_enabled": true,
+ "id": "0002251",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002252 | cartesian conformational search",
+ "title": "cartesian conformational search",
+ "value": "BAO:0002252 | cartesian conformational search $fac2421e-481b-4d7c-b243-854d471ff4c1",
+ "is_enabled": true,
+ "id": "0002252",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002253 | dihedral conformational search",
+ "title": "dihedral conformational search",
+ "value": "BAO:0002253 | dihedral conformational search $69d6b0b2-0fc6-4572-803a-7bcb9bf059dc",
+ "is_enabled": true,
+ "id": "0002253",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002250 | distance geometry conformational search",
+ "title": "distance geometry conformational search",
+ "value": "BAO:0002250 | distance geometry conformational search $d2160447-c0ac-4110-8c7f-355c19888816",
+ "is_enabled": true,
+ "id": "0002250",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002254 | systematic conformational search",
+ "title": "systematic conformational search",
+ "value": "BAO:0002254 | systematic conformational search $29721325-553d-4b30-96aa-facb7802b6b1",
+ "is_enabled": true,
+ "id": "0002254",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002269 | structure generation",
+ "title": "structure generation",
+ "value": "BAO:0002269 | structure generation $bcfe80dd-4efb-46bb-8f21-d24388b2d836",
+ "is_enabled": true,
+ "id": "0002269",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002280 | rule based structure generation",
+ "title": "rule based structure generation",
+ "value": "BAO:0002280 | rule based structure generation $86b7773c-ce70-4638-bd8c-11b3d7667e03",
+ "is_enabled": true,
+ "id": "0002280",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002281 | CONCORD structure generation",
+ "title": "CONCORD structure generation",
+ "value": "BAO:0002281 | CONCORD structure generation $63a2bf38-8921-44fd-8205-b994ed023edd",
+ "is_enabled": true,
+ "id": "0002281",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002272 | de novo structure design",
+ "title": "de novo structure design",
+ "value": "BAO:0002272 | de novo structure design $8abea3e2-1c86-44a5-bb5d-871092f4b01b",
+ "is_enabled": true,
+ "id": "0002272",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002273 | GROW structure design",
+ "title": "GROW structure design",
+ "value": "BAO:0002273 | GROW structure design $e3340117-2e95-422f-84ff-1136023be045",
+ "is_enabled": true,
+ "id": "0002273",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002274 | Groupbuild structure design",
+ "title": "Groupbuild structure design",
+ "value": "BAO:0002274 | Groupbuild structure design $ebd01d80-59e2-42d7-b937-c619b1bc742b",
+ "is_enabled": true,
+ "id": "0002274",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002277 | SPROUT structure design",
+ "title": "SPROUT structure design",
+ "value": "BAO:0002277 | SPROUT structure design $89fda707-569c-4d31-93a6-1b7979aee401",
+ "is_enabled": true,
+ "id": "0002277",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002275 | LEGEND structure design",
+ "title": "LEGEND structure design",
+ "value": "BAO:0002275 | LEGEND structure design $02989912-78de-4f63-a81f-12dcf515efba",
+ "is_enabled": true,
+ "id": "0002275",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002276 | LUDI structure design",
+ "title": "LUDI structure design",
+ "value": "BAO:0002276 | LUDI structure design $938ff0d7-7209-48b6-bc7f-c4a9969ebbaf",
+ "is_enabled": true,
+ "id": "0002276",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002278 | fragment based structure generation",
+ "title": "fragment based structure generation",
+ "value": "BAO:0002278 | fragment based structure generation $b7bd7909-3934-41a5-aa6b-8a98e3a66bd5",
+ "is_enabled": true,
+ "id": "0002278",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002279 | Chem-X structure generation",
+ "title": "Chem-X structure generation",
+ "value": "BAO:0002279 | Chem-X structure generation $e54f958f-ee6b-49cf-a09d-41eefc749708",
+ "is_enabled": true,
+ "id": "0002279",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002270 | data based structure generation",
+ "title": "data based structure generation",
+ "value": "BAO:0002270 | data based structure generation $5ac980e1-741b-4618-8b6d-5a3a13dc8da1",
+ "is_enabled": true,
+ "id": "0002270",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002271 | CORINA structure generation",
+ "title": "CORINA structure generation",
+ "value": "BAO:0002271 | CORINA structure generation $5196ab7a-4f3b-4bf8-9dc9-458c3a944165",
+ "is_enabled": true,
+ "id": "0002271",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002257 | library design",
+ "title": "library design",
+ "value": "BAO:0002257 | library design $8d13626c-9843-403c-b1ec-3cbc844fc8b4",
+ "is_enabled": true,
+ "id": "0002257",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002258 | structure database search",
+ "title": "structure database search",
+ "value": "BAO:0002258 | structure database search $c407c428-b77d-4bb8-8550-2b40bcb61f0d",
+ "is_enabled": true,
+ "id": "0002258",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002268 | substructure search",
+ "title": "substructure search",
+ "value": "BAO:0002268 | substructure search $1ef6e1f3-767a-48a8-8f8f-c30fe1567c1a",
+ "is_enabled": true,
+ "id": "0002268",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002260 | structure similarity search",
+ "title": "structure similarity search",
+ "value": "BAO:0002260 | structure similarity search $5fc1bc48-ad26-4097-8e0d-b9c4803466a2",
+ "is_enabled": true,
+ "id": "0002260",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002261 | 2D structure similarity search",
+ "title": "2D structure similarity search",
+ "value": "BAO:0002261 | 2D structure similarity search $daf29508-1274-492d-8ab4-758c6af7a064",
+ "is_enabled": true,
+ "id": "0002261",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002262 | MACCS key",
+ "title": "MACCS key",
+ "value": "BAO:0002262 | MACCS key $439ccaaf-2b90-4872-ab82-055f25c08fa8",
+ "is_enabled": true,
+ "id": "0002262",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002263 | circular fingerprint search",
+ "title": "circular fingerprint search",
+ "value": "BAO:0002263 | circular fingerprint search $96d060ff-93f6-406b-9718-5cd563b0c14d",
+ "is_enabled": true,
+ "id": "0002263",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002264 | 3D structure similarity search",
+ "title": "3D structure similarity search",
+ "value": "BAO:0002264 | 3D structure similarity search $36513ea3-68fa-43c9-bb19-ba1f91084423",
+ "is_enabled": true,
+ "id": "0002264",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002267 | topomer search",
+ "title": "topomer search",
+ "value": "BAO:0002267 | topomer search $36772058-0604-4478-b2ec-f9ed9438a59d",
+ "is_enabled": true,
+ "id": "0002267",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002265 | shape fingerprint search",
+ "title": "shape fingerprint search",
+ "value": "BAO:0002265 | shape fingerprint search $0f751f88-3c6d-4433-8da7-9d067d7a99f3",
+ "is_enabled": true,
+ "id": "0002265",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002266 | rapid overlay of chemical structures",
+ "title": "rapid overlay of chemical structures",
+ "value": "BAO:0002266 | rapid overlay of chemical structures $9a633d08-e5ec-4c6a-ba88-77f6cfca0b05",
+ "is_enabled": true,
+ "id": "0002266",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002259 | exact match structure search",
+ "title": "exact match structure search",
+ "value": "BAO:0002259 | exact match structure search $d70ec9db-8979-46a3-9233-33d280604f5f",
+ "is_enabled": true,
+ "id": "0002259",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002255 | database filtering",
+ "title": "database filtering",
+ "value": "BAO:0002255 | database filtering $5a77a31a-34e8-436a-8c29-3acd227c3aae",
+ "is_enabled": true,
+ "id": "0002255",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002256 | Lipinski rule of 5 filtering",
+ "title": "Lipinski rule of 5 filtering",
+ "value": "BAO:0002256 | Lipinski rule of 5 filtering $21979f58-91e6-4cc9-b3f5-bf52c0d8fab1",
+ "is_enabled": true,
+ "id": "0002256",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003028 | assay method",
+ "title": "assay method",
+ "value": "BAO:0003028 | assay method $eef34ab1-c809-4037-ae2f-77c21d216bc3",
+ "is_enabled": true,
+ "id": "0003028",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002429 | assay supporting method",
+ "title": "assay supporting method",
+ "value": "BAO:0002429 | assay supporting method $2890aad7-49a0-44f9-8b74-61d85ba7a7aa",
+ "is_enabled": true,
+ "id": "0002429",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002754 | assay data processing method",
+ "title": "assay data processing method",
+ "value": "BAO:0002754 | assay data processing method $eaf3cf1d-948f-4c4a-bd86-25dca9da49ec",
+ "is_enabled": true,
+ "id": "0002754",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000028 | assay quality assessment method",
+ "title": "assay quality assessment method",
+ "value": "BAO:0000028 | assay quality assessment method $43862d87-8d9f-4200-9456-58d8bd8d18e6",
+ "is_enabled": true,
+ "id": "0000028",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000531 | coefficient of variation",
+ "title": "coefficient of variation",
+ "value": "BAO:0000531 | coefficient of variation $3cf8d805-51c3-4465-9d83-f11fdb332090",
+ "is_enabled": true,
+ "id": "0000531",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000530 | signal to noise",
+ "title": "signal to noise",
+ "value": "BAO:0000530 | signal to noise $d7c7a911-0123-43b5-964a-a50c9ef46f3b",
+ "is_enabled": true,
+ "id": "0000530",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000528 | z-prime factor",
+ "title": "z-prime factor",
+ "value": "BAO:0000528 | z-prime factor $805326e0-ac63-4f3e-86b5-c01e4da0964a",
+ "is_enabled": true,
+ "id": "0000528",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000527 | z factor",
+ "title": "z factor",
+ "value": "BAO:0000527 | z factor $1d4770b6-4715-4b80-a9cc-7942f6c8dd19",
+ "is_enabled": true,
+ "id": "0000527",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000529 | signal window",
+ "title": "signal window",
+ "value": "BAO:0000529 | signal window $b998bf42-cabc-4743-880f-2139edc96323",
+ "is_enabled": true,
+ "id": "0000529",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002143 | robust z-prime factor",
+ "title": "robust z-prime factor",
+ "value": "BAO:0002143 | robust z-prime factor $119cf8d9-05b3-4643-803b-604caff350c1",
+ "is_enabled": true,
+ "id": "0002143",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000043 | endpoint qualifier",
+ "title": "endpoint qualifier",
+ "value": "BAO:0000043 | endpoint qualifier $71cb1137-492f-495b-bf52-a61649cee12f",
+ "is_enabled": true,
+ "id": "0000043",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000075 | endpoint normalization method",
+ "title": "endpoint normalization method",
+ "value": "BAO:0000075 | endpoint normalization method $2c58dd73-92b1-4b2b-b293-a311119b9d36",
+ "is_enabled": true,
+ "id": "0000075",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002750 | normalization based on control",
+ "title": "normalization based on control",
+ "value": "BAO:0002750 | normalization based on control $7db1f064-caf1-409c-8e89-482a2e2e6f16",
+ "is_enabled": true,
+ "id": "0002750",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000065 | percent inhibition normalization",
+ "title": "percent inhibition normalization",
+ "value": "BAO:0000065 | percent inhibition normalization $fc6fc3a7-e12d-4a7f-9187-a00edb071e74",
+ "is_enabled": true,
+ "id": "0000065",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000431 | percent control normalization",
+ "title": "percent control normalization",
+ "value": "BAO:0000431 | percent control normalization $03af1d5c-8705-4fe7-a0f9-cbebbac3f3fa",
+ "is_enabled": true,
+ "id": "0000431",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001104 | percent activation normalization",
+ "title": "percent activation normalization",
+ "value": "BAO:0001104 | percent activation normalization $93cd364d-5781-4dff-a535-2ace3a215a5b",
+ "is_enabled": true,
+ "id": "0001104",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002751 | normalization without control",
+ "title": "normalization without control",
+ "value": "BAO:0002751 | normalization without control $846ad766-6f56-41de-a56f-ced40e97d99c",
+ "is_enabled": true,
+ "id": "0002751",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002161 | mad-score normalization",
+ "title": "mad-score normalization",
+ "value": "BAO:0002161 | mad-score normalization $179da601-392e-4ff1-97f5-3bc908110bc6",
+ "is_enabled": true,
+ "id": "0002161",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002160 | z-score normalization",
+ "title": "z-score normalization",
+ "value": "BAO:0002160 | z-score normalization $586e8743-5ce6-4691-8fad-e359fd29170c",
+ "is_enabled": true,
+ "id": "0002160",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002159 | b-score normalization",
+ "title": "b-score normalization",
+ "value": "BAO:0002159 | b-score normalization $16945a77-9b57-4b5f-b3ab-65d1bc7390fd",
+ "is_enabled": true,
+ "id": "0002159",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000419 | endpoint correction",
+ "title": "endpoint correction",
+ "value": "BAO:0000419 | endpoint correction $3c7810ef-d9ed-43c5-acfc-7e678ddd17d6",
+ "is_enabled": true,
+ "id": "0000419",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000433 | curve fit method",
+ "title": "curve fit method",
+ "value": "BAO:0000433 | curve fit method $913a075c-fa7a-4830-a9ea-02aa208745cf",
+ "is_enabled": true,
+ "id": "0000433",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040001 | image analysis method",
+ "title": "image analysis method",
+ "value": "BAO:0040001 | image analysis method $a07b6ad7-7fc5-4b93-ad25-57e38d50ffd8",
+ "is_enabled": true,
+ "id": "0040001",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040002 | image correction",
+ "title": "image correction",
+ "value": "BAO:0040002 | image correction $f58d8b2f-ea8a-42f5-b39f-3b61b37df3d4",
+ "is_enabled": true,
+ "id": "0040002",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040004 | image resize",
+ "title": "image resize",
+ "value": "BAO:0040004 | image resize $f38d4d13-3967-4bab-a554-a31ccd4f198f",
+ "is_enabled": true,
+ "id": "0040004",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040005 | image sharpening",
+ "title": "image sharpening",
+ "value": "BAO:0040005 | image sharpening $92f79dac-1331-4cb0-aa7c-1b2eae882058",
+ "is_enabled": true,
+ "id": "0040005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040003 | background correction",
+ "title": "background correction",
+ "value": "BAO:0040003 | background correction $25cdb473-99ea-4f71-bd62-92d69d48fcf3",
+ "is_enabled": true,
+ "id": "0040003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040006 | image smoothing",
+ "title": "image smoothing",
+ "value": "BAO:0040006 | image smoothing $4be54a18-b459-4f34-a945-087d68fd5276",
+ "is_enabled": true,
+ "id": "0040006",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040007 | image segmentation",
+ "title": "image segmentation",
+ "value": "BAO:0040007 | image segmentation $e2ab139b-185a-4a68-895d-c3c037be5b33",
+ "is_enabled": true,
+ "id": "0040007",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040008 | edge detection",
+ "title": "edge detection",
+ "value": "BAO:0040008 | edge detection $cfd7ab5c-0174-4117-be95-a98d2b36488d",
+ "is_enabled": true,
+ "id": "0040008",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040009 | image thresholding",
+ "title": "image thresholding",
+ "value": "BAO:0040009 | image thresholding $60e70c6d-e300-427c-bb9a-5c31cf1862b3",
+ "is_enabled": true,
+ "id": "0040009",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002170 | endpoint modifier",
+ "title": "endpoint modifier",
+ "value": "BAO:0002170 | endpoint modifier $314884dd-8635-4e92-bd34-7557c91f035f",
+ "is_enabled": true,
+ "id": "0002170",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002174 | median",
+ "title": "median",
+ "value": "BAO:0002174 | median $0c7c310b-351d-4ccb-a5c7-4d23585e34c2",
+ "is_enabled": true,
+ "id": "0002174",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002175 | p",
+ "title": "p",
+ "value": "BAO:0002175 | p $a21840d7-b45d-411e-bc4b-62878ba4b97c",
+ "is_enabled": true,
+ "id": "0002175",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002172 | log",
+ "title": "log",
+ "value": "BAO:0002172 | log $9b23d0b1-636e-4ebc-88dc-391c31f602a6",
+ "is_enabled": true,
+ "id": "0002172",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002173 | mean",
+ "title": "mean",
+ "value": "BAO:0002173 | mean $d39e61cb-b793-4a45-95be-9d1363c20e49",
+ "is_enabled": true,
+ "id": "0002173",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002176 | standard deviation",
+ "title": "standard deviation",
+ "value": "BAO:0002176 | standard deviation $2fe30be6-517d-4359-8ba1-6420999a1fb0",
+ "is_enabled": true,
+ "id": "0002176",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002171 | ln",
+ "title": "ln",
+ "value": "BAO:0002171 | ln $d4eea944-6ece-4be5-8982-bdfed02a40e7",
+ "is_enabled": true,
+ "id": "0002171",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002140 | activity threshold specification",
+ "title": "activity threshold specification",
+ "value": "BAO:0002140 | activity threshold specification $53cd0e14-c63c-4cf2-bc8f-0af37e4a3696",
+ "is_enabled": true,
+ "id": "0002140",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002141 | activity threshold signal direction",
+ "title": "activity threshold signal direction",
+ "value": "BAO:0002141 | activity threshold signal direction $81332148-5ac5-4a3a-bb2d-120f4c457312",
+ "is_enabled": true,
+ "id": "0002141",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002500 | separation method",
+ "title": "separation method",
+ "value": "BAO:0002500 | separation method $8dc0ec23-f86f-483c-a387-5d8692128873",
+ "is_enabled": true,
+ "id": "0002500",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002509 | cell separation method",
+ "title": "cell separation method",
+ "value": "BAO:0002509 | cell separation method $83c36239-df7e-43be-b464-a97d9c056471",
+ "is_enabled": true,
+ "id": "0002509",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002501 | affinity selection",
+ "title": "affinity selection",
+ "value": "BAO:0002501 | affinity selection $0c8abb90-4371-4e7d-b7be-b254698b2002",
+ "is_enabled": true,
+ "id": "0002501",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002502 | antibody-based separation method",
+ "title": "antibody-based separation method",
+ "value": "BAO:0002502 | antibody-based separation method $b65d89c1-e49e-45ab-9dbe-62a3e3465c96",
+ "is_enabled": true,
+ "id": "0002502",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002507 | immunomagnetic separation method",
+ "title": "immunomagnetic separation method",
+ "value": "BAO:0002507 | immunomagnetic separation method $2e4b39cd-0663-4c4c-a99b-d5eb11dc73b7",
+ "is_enabled": true,
+ "id": "0002507",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002508 | immunoprecipitation",
+ "title": "immunoprecipitation",
+ "value": "BAO:0002508 | immunoprecipitation $e554c10f-bdac-46f6-8ccd-f265cd7d8853",
+ "is_enabled": true,
+ "id": "0002508",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002505 | immunodepletion",
+ "title": "immunodepletion",
+ "value": "BAO:0002505 | immunodepletion $9a052880-3370-43b0-a2f4-3c06fa5d4531",
+ "is_enabled": true,
+ "id": "0002505",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002503 | immunocapture",
+ "title": "immunocapture",
+ "value": "BAO:0002503 | immunocapture $388e7c05-5f11-423e-8ae6-5669452e89fb",
+ "is_enabled": true,
+ "id": "0002503",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002504 | immunochromatography",
+ "title": "immunochromatography",
+ "value": "BAO:0002504 | immunochromatography $3d124734-47a0-4cc5-adf8-4a949061347e",
+ "is_enabled": true,
+ "id": "0002504",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002647 | cell culture method",
+ "title": "cell culture method",
+ "value": "BAO:0002647 | cell culture method $e423cfeb-106b-4bae-b4bd-caf893a0e789",
+ "is_enabled": true,
+ "id": "0002647",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002648 | one cell type",
+ "title": "one cell type",
+ "value": "BAO:0002648 | one cell type $80ed4fb5-7f04-4842-8d7c-d4137b49960f",
+ "is_enabled": true,
+ "id": "0002648",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002649 | co-culture",
+ "title": "co-culture",
+ "value": "BAO:0002649 | co-culture $72ee4b62-8c3f-42bf-9675-0dd1eb576dc7",
+ "is_enabled": true,
+ "id": "0002649",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000468 | signal quantitation method",
+ "title": "signal quantitation method",
+ "value": "BAO:0000468 | signal quantitation method $e0c47b4f-992b-4268-9886-41e0f9ed4845",
+ "is_enabled": true,
+ "id": "0000468",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000464 | densitometric scan",
+ "title": "densitometric scan",
+ "value": "BAO:0000464 | densitometric scan $36449990-6cfe-499b-934f-c214dcb15a0c",
+ "is_enabled": true,
+ "id": "0000464",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002026 | structure analysis method",
+ "title": "structure analysis method",
+ "value": "BAO:0002026 | structure analysis method $ef99b867-114a-4483-a6a5-0c8f1d9760bc",
+ "is_enabled": true,
+ "id": "0002026",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002045 | primary structure analysis method",
+ "title": "primary structure analysis method",
+ "value": "BAO:0002045 | primary structure analysis method $d4070c85-23b3-4092-a79e-f04e89148de9",
+ "is_enabled": true,
+ "id": "0002045",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002409 | secondary structure analysis method",
+ "title": "secondary structure analysis method",
+ "value": "BAO:0002409 | secondary structure analysis method $51fcdb4b-a0ca-485d-8abc-b8121fb71430",
+ "is_enabled": true,
+ "id": "0002409",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002410 | structure activity relationship analysis",
+ "title": "structure activity relationship analysis",
+ "value": "BAO:0002410 | structure activity relationship analysis $c8f58c51-5987-4263-a1c4-c75d46b53204",
+ "is_enabled": true,
+ "id": "0002410",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002305 | quantitative structure activity relationship analysis",
+ "title": "quantitative structure activity relationship analysis",
+ "value": "BAO:0002305 | quantitative structure activity relationship analysis $63620d78-4d30-4ff4-823f-fc9c303c5a62",
+ "is_enabled": true,
+ "id": "0002305",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002309 | non-linear QSAR",
+ "title": "non-linear QSAR",
+ "value": "BAO:0002309 | non-linear QSAR $5778b560-a403-446b-8f6e-395f2c68b095",
+ "is_enabled": true,
+ "id": "0002309",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002310 | neural network QSAR",
+ "title": "neural network QSAR",
+ "value": "BAO:0002310 | neural network QSAR $10ef755f-51bd-43be-8dd6-c8601e62a912",
+ "is_enabled": true,
+ "id": "0002310",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002311 | recursive partitioning QSAR",
+ "title": "recursive partitioning QSAR",
+ "value": "BAO:0002311 | recursive partitioning QSAR $2d6fdaa8-94fd-4917-a4ed-dd8e7cb49bf8",
+ "is_enabled": true,
+ "id": "0002311",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002306 | linear QSAR",
+ "title": "linear QSAR",
+ "value": "BAO:0002306 | linear QSAR $f26cb831-e482-4970-b87f-655d60e54ac8",
+ "is_enabled": true,
+ "id": "0002306",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002307 | partial least squares QSAR",
+ "title": "partial least squares QSAR",
+ "value": "BAO:0002307 | partial least squares QSAR $2b7ed0e6-c951-4617-85d6-e7cd2652366b",
+ "is_enabled": true,
+ "id": "0002307",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002308 | regression QSAR",
+ "title": "regression QSAR",
+ "value": "BAO:0002308 | regression QSAR $180e0219-9045-4440-a862-5079d54b3369",
+ "is_enabled": true,
+ "id": "0002308",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002312 | three dimensional QSAR",
+ "title": "three dimensional QSAR",
+ "value": "BAO:0002312 | three dimensional QSAR $ebedb03e-6662-4d56-8c03-94272e0fc1f4",
+ "is_enabled": true,
+ "id": "0002312",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002314 | comparative molecular similarity indices analysis",
+ "title": "comparative molecular similarity indices analysis",
+ "value": "BAO:0002314 | comparative molecular similarity indices analysis $28fff377-68f4-4300-9a2d-093dd245f7d8",
+ "is_enabled": true,
+ "id": "0002314",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002315 | self organizing molecular field analysis",
+ "title": "self organizing molecular field analysis",
+ "value": "BAO:0002315 | self organizing molecular field analysis $8aed437c-df34-4e36-a93f-01fd45f0e9db",
+ "is_enabled": true,
+ "id": "0002315",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002313 | comparative molecular field analysis",
+ "title": "comparative molecular field analysis",
+ "value": "BAO:0002313 | comparative molecular field analysis $80dce3de-7081-4170-be2a-8fc13109b0ca",
+ "is_enabled": true,
+ "id": "0002313",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002316 | two dimensional QSAR",
+ "title": "two dimensional QSAR",
+ "value": "BAO:0002316 | two dimensional QSAR $d5c757cb-cd4b-4244-8fb4-c0c75b6981ca",
+ "is_enabled": true,
+ "id": "0002316",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002412 | SAR by NMR",
+ "title": "SAR by NMR",
+ "value": "BAO:0002412 | SAR by NMR $ecf85ac1-3e8e-452d-ae02-0c5b0fe3e679",
+ "is_enabled": true,
+ "id": "0002412",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002212 | computational structure analysis",
+ "title": "computational structure analysis",
+ "value": "BAO:0002212 | computational structure analysis $b741e324-e9b0-4adf-a2cd-302509a16905",
+ "is_enabled": true,
+ "id": "0002212",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002216 | 3D structure prediction",
+ "title": "3D structure prediction",
+ "value": "BAO:0002216 | 3D structure prediction $c23c39b1-6d42-4e98-b4cc-bac733478c87",
+ "is_enabled": true,
+ "id": "0002216",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002226 | protein-protein docking",
+ "title": "protein-protein docking",
+ "value": "BAO:0002226 | protein-protein docking $eab86539-2f1c-4df0-86ec-9b375b8fee46",
+ "is_enabled": true,
+ "id": "0002226",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002227 | global range molecular matching",
+ "title": "global range molecular matching",
+ "value": "BAO:0002227 | global range molecular matching $b0cc3fb0-e731-4199-bc39-1fa4ebc7db14",
+ "is_enabled": true,
+ "id": "0002227",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002224 | protein threading",
+ "title": "protein threading",
+ "value": "BAO:0002224 | protein threading $9fbfaf79-8990-4637-8bc5-0e40debff21b",
+ "is_enabled": true,
+ "id": "0002224",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002225 | RAPTOR protein threading",
+ "title": "RAPTOR protein threading",
+ "value": "BAO:0002225 | RAPTOR protein threading $e142199b-2306-4f27-91cc-a5a6032f01cb",
+ "is_enabled": true,
+ "id": "0002225",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002228 | structure alignment",
+ "title": "structure alignment",
+ "value": "BAO:0002228 | structure alignment $7d00d258-c1be-4670-af08-a3bdb64242ac",
+ "is_enabled": true,
+ "id": "0002228",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002229 | distance matrix alignment",
+ "title": "distance matrix alignment",
+ "value": "BAO:0002229 | distance matrix alignment $1dd4f463-26c7-4914-9df9-bfdfa29b8f8b",
+ "is_enabled": true,
+ "id": "0002229",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002230 | matching molecular models obtained from theory",
+ "title": "matching molecular models obtained from theory",
+ "value": "BAO:0002230 | matching molecular models obtained from theory $42686588-b206-4104-a712-e62391842f71",
+ "is_enabled": true,
+ "id": "0002230",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002221 | homology modeling",
+ "title": "homology modeling",
+ "value": "BAO:0002221 | homology modeling $61eb9e39-13ab-459c-86e8-7edee6d25bec",
+ "is_enabled": true,
+ "id": "0002221",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002222 | MODELLER homology modeling",
+ "title": "MODELLER homology modeling",
+ "value": "BAO:0002222 | MODELLER homology modeling $8de41e75-6eb3-49e6-a06a-fb842720e4d1",
+ "is_enabled": true,
+ "id": "0002222",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002223 | SwissModel homology modeling",
+ "title": "SwissModel homology modeling",
+ "value": "BAO:0002223 | SwissModel homology modeling $20be51cc-67aa-4e6f-8198-4edcadf16804",
+ "is_enabled": true,
+ "id": "0002223",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002217 | computational structure solution",
+ "title": "computational structure solution",
+ "value": "BAO:0002217 | computational structure solution $b4dd17b8-a02b-4a10-a1c6-35675dae8c98",
+ "is_enabled": true,
+ "id": "0002217",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002220 | computational electron microscopy structure solution",
+ "title": "computational electron microscopy structure solution",
+ "value": "BAO:0002220 | computational electron microscopy structure solution $b23caeb2-3021-4d39-b567-da83b60b18dc",
+ "is_enabled": true,
+ "id": "0002220",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002219 | computational X-ray structure solution",
+ "title": "computational X-ray structure solution",
+ "value": "BAO:0002219 | computational X-ray structure solution $7571f2b8-4605-4007-9a78-7277e3336848",
+ "is_enabled": true,
+ "id": "0002219",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002218 | computational NMR structure solution",
+ "title": "computational NMR structure solution",
+ "value": "BAO:0002218 | computational NMR structure solution $e4ea638b-4eb2-4b97-8864-0565bad22c84",
+ "is_enabled": true,
+ "id": "0002218",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002213 | 2D structure prediction",
+ "title": "2D structure prediction",
+ "value": "BAO:0002213 | 2D structure prediction $9ba465a8-c664-4159-80cf-2e9c9f41b69b",
+ "is_enabled": true,
+ "id": "0002213",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002215 | PredictProtein structure prediction",
+ "title": "PredictProtein structure prediction",
+ "value": "BAO:0002215 | PredictProtein structure prediction $bb142737-72c3-49a9-adeb-1f0003af765c",
+ "is_enabled": true,
+ "id": "0002215",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002214 | PREDATOR structure prediction",
+ "title": "PREDATOR structure prediction",
+ "value": "BAO:0002214 | PREDATOR structure prediction $2be1765b-3282-46eb-9084-3b8410e20ffe",
+ "is_enabled": true,
+ "id": "0002214",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002014 | preparation method",
+ "title": "preparation method",
+ "value": "BAO:0002014 | preparation method $aafcbe57-7070-4f59-b0ba-adfd979e2d04",
+ "is_enabled": true,
+ "id": "0002014",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002601 | antibody preparation method",
+ "title": "antibody preparation method",
+ "value": "BAO:0002601 | antibody preparation method $8b7b0415-06be-4f5c-86f9-ee62dacc3247",
+ "is_enabled": true,
+ "id": "0002601",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002602 | ammonium sulfate precipitation method",
+ "title": "ammonium sulfate precipitation method",
+ "value": "BAO:0002602 | ammonium sulfate precipitation method $ef38ae4c-8e7f-4cba-bf87-5e23a041dbb7",
+ "is_enabled": true,
+ "id": "0002602",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002603 | affinity purification method",
+ "title": "affinity purification method",
+ "value": "BAO:0002603 | affinity purification method $2cfe1aeb-59a0-4974-b51b-9a0933dd9a11",
+ "is_enabled": true,
+ "id": "0002603",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002608 | protein L-based affinity purification method",
+ "title": "protein L-based affinity purification method",
+ "value": "BAO:0002608 | protein L-based affinity purification method $a2d9440e-f4fd-40db-8022-abd5acada641",
+ "is_enabled": true,
+ "id": "0002608",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002606 | protein A-based affinity purification method",
+ "title": "protein A-based affinity purification method",
+ "value": "BAO:0002606 | protein A-based affinity purification method $1f89c912-b0ab-40f1-9115-a6d8cd8e3d4f",
+ "is_enabled": true,
+ "id": "0002606",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002607 | protein A/G-based affinity purification method",
+ "title": "protein A/G-based affinity purification method",
+ "value": "BAO:0002607 | protein A/G-based affinity purification method $2a3d4375-174e-46f6-90a3-28277c97bd99",
+ "is_enabled": true,
+ "id": "0002607",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002604 | protein G-based affinity purification method",
+ "title": "protein G-based affinity purification method",
+ "value": "BAO:0002604 | protein G-based affinity purification method $d427e061-68c0-4965-9ef4-f8c4a12f31d8",
+ "is_enabled": true,
+ "id": "0002604",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002605 | antigen-based affinity purification method",
+ "title": "antigen-based affinity purification method",
+ "value": "BAO:0002605 | antigen-based affinity purification method $a96d823c-ea76-4857-8a55-10e14f50bcca",
+ "is_enabled": true,
+ "id": "0002605",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000356 | protein preparation method",
+ "title": "protein preparation method",
+ "value": "BAO:0000356 | protein preparation method $4de5719f-0e37-45ce-a245-c93db347365c",
+ "is_enabled": true,
+ "id": "0000356",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000360 | recombinant expression",
+ "title": "recombinant expression",
+ "value": "BAO:0000360 | recombinant expression $5891f8cd-f21d-4cd2-ad4c-7565d2dd3285",
+ "is_enabled": true,
+ "id": "0000360",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002076 | extraction from natural source",
+ "title": "extraction from natural source",
+ "value": "BAO:0002076 | extraction from natural source $58f50bca-b633-4aac-82e0-4959ec7a3dfb",
+ "is_enabled": true,
+ "id": "0002076",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002078 | purification from natural source",
+ "title": "purification from natural source",
+ "value": "BAO:0002078 | purification from natural source $f8314161-213a-48d4-a376-22afa8134c7a",
+ "is_enabled": true,
+ "id": "0002078",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002077 | synthesis by a chemical process",
+ "title": "synthesis by a chemical process",
+ "value": "BAO:0002077 | synthesis by a chemical process $d8f09270-f321-4d07-88b9-204e83299407",
+ "is_enabled": true,
+ "id": "0002077",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003029 | small molecule preparation method",
+ "title": "small molecule preparation method",
+ "value": "BAO:0003029 | small molecule preparation method $58ef475a-4610-495e-8435-7e7ef5c6116a",
+ "is_enabled": true,
+ "id": "0003029",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002076 | extraction from natural source",
+ "title": "extraction from natural source",
+ "value": "BAO:0002076 | extraction from natural source $de43944b-1320-4521-9705-9082626632a7",
+ "is_enabled": true,
+ "id": "0002076",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002078 | purification from natural source",
+ "title": "purification from natural source",
+ "value": "BAO:0002078 | purification from natural source $ad5600f8-032b-4393-b8f4-415f1cf1d15c",
+ "is_enabled": true,
+ "id": "0002078",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002077 | synthesis by a chemical process",
+ "title": "synthesis by a chemical process",
+ "value": "BAO:0002077 | synthesis by a chemical process $043b5596-d4d3-4c99-8ce1-5858adb7bf3e",
+ "is_enabled": true,
+ "id": "0002077",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002151 | RNA interference construct preparation method",
+ "title": "RNA interference construct preparation method",
+ "value": "BAO:0002151 | RNA interference construct preparation method $800a772d-2f31-42eb-9e2f-84066fa91ed6",
+ "is_enabled": true,
+ "id": "0002151",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002011 | processing method",
+ "title": "processing method",
+ "value": "BAO:0002011 | processing method $477db740-6349-4ae0-92c2-d94f873c83aa",
+ "is_enabled": true,
+ "id": "0002011",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002036 | tissue processing method",
+ "title": "tissue processing method",
+ "value": "BAO:0002036 | tissue processing method $598e6acb-e372-41d1-8292-a4256fbff216",
+ "is_enabled": true,
+ "id": "0002036",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "NCIT:C19286 | Tissue Slice Technology",
+ "title": "Tissue Slice Technology",
+ "value": "NCIT:C19286 | Tissue Slice Technology $e232ddb3-30a3-45d8-8eb2-88dcf45d00cf",
+ "is_enabled": true,
+ "id": "C19286",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002037 | tissue fixation method",
+ "title": "tissue fixation method",
+ "value": "BAO:0002037 | tissue fixation method $f54976c9-8681-4349-b0c6-d520a64b60fe",
+ "is_enabled": true,
+ "id": "0002037",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002033 | cell processing method",
+ "title": "cell processing method",
+ "value": "BAO:0002033 | cell processing method $f7f1c208-c425-4990-8ba1-e3229c6d4a5b",
+ "is_enabled": true,
+ "id": "0002033",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002035 | cell fixation method",
+ "title": "cell fixation method",
+ "value": "BAO:0002035 | cell fixation method $85a8324a-6e26-48c4-92fe-2c6b5588e0fe",
+ "is_enabled": true,
+ "id": "0002035",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002413 | titration method",
+ "title": "titration method",
+ "value": "BAO:0002413 | titration method $f4f4eab0-1755-4ac0-8422-c16dc11e46c9",
+ "is_enabled": true,
+ "id": "0002413",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002414 | Karl Fischer titration",
+ "title": "Karl Fischer titration",
+ "value": "BAO:0002414 | Karl Fischer titration $d9cc3b03-825d-4480-b9a5-58ed76059b94",
+ "is_enabled": true,
+ "id": "0002414",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002418 | dilution method",
+ "title": "dilution method",
+ "value": "BAO:0002418 | dilution method $3c098a25-117a-41a8-b77d-38e8863dfdfe",
+ "is_enabled": true,
+ "id": "0002418",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002416 | checkerboard titration",
+ "title": "checkerboard titration",
+ "value": "BAO:0002416 | checkerboard titration $4ea94495-b735-481c-9c3c-3479dac95b61",
+ "is_enabled": true,
+ "id": "0002416",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002454 | volumetric titration",
+ "title": "volumetric titration",
+ "value": "BAO:0002454 | volumetric titration $ec123599-9eb6-42fb-a133-e456daaa678e",
+ "is_enabled": true,
+ "id": "0002454",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002445 | genotyping method",
+ "title": "genotyping method",
+ "value": "BAO:0002445 | genotyping method $7e28e8b4-530c-4d61-8c06-fdb9b758e8f4",
+ "is_enabled": true,
+ "id": "0002445",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "NCIT:C101294 | Whole Genome Sequencing",
+ "title": "Whole Genome Sequencing",
+ "value": "NCIT:C101294 | Whole Genome Sequencing $a46f8ad2-e14a-4809-b0ab-2536805e6709",
+ "is_enabled": true,
+ "id": "C101294",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002446 | nucleic acid hybridization-based method",
+ "title": "nucleic acid hybridization-based method",
+ "value": "BAO:0002446 | nucleic acid hybridization-based method $b246fdd4-26c7-4e5d-bbd6-cf8721428c50",
+ "is_enabled": true,
+ "id": "0002446",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002448 | restriction enzyme-based method",
+ "title": "restriction enzyme-based method",
+ "value": "BAO:0002448 | restriction enzyme-based method $23647645-60ea-4de2-bb6c-14b912a50c3f",
+ "is_enabled": true,
+ "id": "0002448",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002449 | single nucleotide polymorphism genotyping",
+ "title": "single nucleotide polymorphism genotyping",
+ "value": "BAO:0002449 | single nucleotide polymorphism genotyping $34e5a925-0099-494b-ad2a-2ef463fbd219",
+ "is_enabled": true,
+ "id": "0002449",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002450 | nucleic acid amplification method",
+ "title": "nucleic acid amplification method",
+ "value": "BAO:0002450 | nucleic acid amplification method $11e2a84b-7c50-4f37-b2c2-17db5eb5ba74",
+ "is_enabled": true,
+ "id": "0002450",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002080 | polymerase chain reaction",
+ "title": "polymerase chain reaction",
+ "value": "BAO:0002080 | polymerase chain reaction $c105b1eb-4a98-43e4-b33d-dceb652523f1",
+ "is_enabled": true,
+ "id": "0002080",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002084 | real-time PCR ",
+ "title": "real-time PCR ",
+ "value": "BAO:0002084 | real-time PCR $74faa343-0519-44b2-ab3a-e55df35d0e2e",
+ "is_enabled": true,
+ "id": "0002084",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002089 | reverse transcription PCR",
+ "title": "reverse transcription PCR",
+ "value": "BAO:0002089 | reverse transcription PCR $ab9d169e-1100-4b6b-9e62-f7c11478c597",
+ "is_enabled": true,
+ "id": "0002089",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002090 | quantitative reverse transcription PCR",
+ "title": "quantitative reverse transcription PCR",
+ "value": "BAO:0002090 | quantitative reverse transcription PCR $f1c4a2b1-6e76-4192-aa9b-8a7bb622807e",
+ "is_enabled": true,
+ "id": "0002090",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003031 | quantitative PCR",
+ "title": "quantitative PCR",
+ "value": "BAO:0003031 | quantitative PCR $aa7d349f-20b8-484b-a023-01c7c24e0755",
+ "is_enabled": true,
+ "id": "0003031",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002451 | chromosome mapping",
+ "title": "chromosome mapping",
+ "value": "BAO:0002451 | chromosome mapping $3925e6ed-0060-43d8-9008-983e87e3e76b",
+ "is_enabled": true,
+ "id": "0002451",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002431 | gene expression modulation method",
+ "title": "gene expression modulation method",
+ "value": "BAO:0002431 | gene expression modulation method $519a46dc-67b3-4360-bd90-633010757412",
+ "is_enabled": true,
+ "id": "0002431",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0010249 | CRISPR/Cas9 method",
+ "title": "CRISPR/Cas9 method",
+ "value": "BAO:0010249 | CRISPR/Cas9 method $a9fbdca8-aee5-4fa4-9064-b12db846579f",
+ "is_enabled": true,
+ "id": "0010249",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002442 | gene overexpression",
+ "title": "gene overexpression",
+ "value": "BAO:0002442 | gene overexpression $b9b1d5aa-4d68-4de1-9905-32aca7ca1acf",
+ "is_enabled": true,
+ "id": "0002442",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002444 | gene overexpression by transient transfection",
+ "title": "gene overexpression by transient transfection",
+ "value": "BAO:0002444 | gene overexpression by transient transfection $cf202e93-9ada-47b5-89f0-87aa3609dff0",
+ "is_enabled": true,
+ "id": "0002444",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002443 | gene overexpression by stable transfection",
+ "title": "gene overexpression by stable transfection",
+ "value": "BAO:0002443 | gene overexpression by stable transfection $673a73b3-6968-44fa-a319-36d18c376f8c",
+ "is_enabled": true,
+ "id": "0002443",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002441 | gene knockout",
+ "title": "gene knockout",
+ "value": "BAO:0002441 | gene knockout $2f236edf-135f-4a93-a557-510eebfdb98b",
+ "is_enabled": true,
+ "id": "0002441",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002433 | gene knockdown",
+ "title": "gene knockdown",
+ "value": "BAO:0002433 | gene knockdown $b985d770-0f02-4a40-9324-d315f05a3218",
+ "is_enabled": true,
+ "id": "0002433",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002440 | gene knockdown by morpholino treatment",
+ "title": "gene knockdown by morpholino treatment",
+ "value": "BAO:0002440 | gene knockdown by morpholino treatment $f958b8ff-0757-4251-815d-4b0ab66490fa",
+ "is_enabled": true,
+ "id": "0002440",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002434 | gene knockdown by RNA interference",
+ "title": "gene knockdown by RNA interference",
+ "value": "BAO:0002434 | gene knockdown by RNA interference $17a31457-0f13-48e0-a925-50af4c99dc93",
+ "is_enabled": true,
+ "id": "0002434",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002435 | gene knockdown by dsRNA transfection",
+ "title": "gene knockdown by dsRNA transfection",
+ "value": "BAO:0002435 | gene knockdown by dsRNA transfection $9f88cb87-4679-4081-9da6-8efb7043c0ae",
+ "is_enabled": true,
+ "id": "0002435",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002436 | gene knockdown by lentiviral shRNA transduction",
+ "title": "gene knockdown by lentiviral shRNA transduction",
+ "value": "BAO:0002436 | gene knockdown by lentiviral shRNA transduction $1420a59d-d5f4-4e7c-b6a7-47acefc0788a",
+ "is_enabled": true,
+ "id": "0002436",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002437 | gene knockdown by shRNA transfection",
+ "title": "gene knockdown by shRNA transfection",
+ "value": "BAO:0002437 | gene knockdown by shRNA transfection $380f6e77-1609-46cf-89d1-2ee148e91098",
+ "is_enabled": true,
+ "id": "0002437",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002438 | gene knockdown by siRNA transfection",
+ "title": "gene knockdown by siRNA transfection",
+ "value": "BAO:0002438 | gene knockdown by siRNA transfection $7b4898d4-8824-4cbf-a5c2-9f716e5c8b97",
+ "is_enabled": true,
+ "id": "0002438",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002439 | gene knockdown by antisense RNA",
+ "title": "gene knockdown by antisense RNA",
+ "value": "BAO:0002439 | gene knockdown by antisense RNA $535c63b1-0dae-4b88-9573-320b31ccd29e",
+ "is_enabled": true,
+ "id": "0002439",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002432 | gene knock in",
+ "title": "gene knock in",
+ "value": "BAO:0002432 | gene knock in $136ce012-3c48-4409-9890-92f69cf5b2f2",
+ "is_enabled": true,
+ "id": "0002432",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002452 | labeling method",
+ "title": "labeling method",
+ "value": "BAO:0002452 | labeling method $d2db9745-9a27-4a30-8edc-2246c99e6345",
+ "is_enabled": true,
+ "id": "0002452",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040025 | chemiluminescent labeling method",
+ "title": "chemiluminescent labeling method",
+ "value": "BAO:0040025 | chemiluminescent labeling method $7339f582-f87f-4972-b4a3-52411519e604",
+ "is_enabled": true,
+ "id": "0040025",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002425 | immunolabeling method",
+ "title": "immunolabeling method",
+ "value": "BAO:0002425 | immunolabeling method $835bbb4c-25dd-4433-bf58-dbb0e0339500",
+ "is_enabled": true,
+ "id": "0002425",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002426 | immunofluorescent labeling",
+ "title": "immunofluorescent labeling",
+ "value": "BAO:0002426 | immunofluorescent labeling $726289e9-a7ee-4719-a4a5-ebda383f3002",
+ "is_enabled": true,
+ "id": "0002426",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002427 | immunogold labeling",
+ "title": "immunogold labeling",
+ "value": "BAO:0002427 | immunogold labeling $f8420899-73b2-4d3e-ad74-fd99c3038def",
+ "is_enabled": true,
+ "id": "0002427",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002469 | fluorescent labeling method",
+ "title": "fluorescent labeling method",
+ "value": "BAO:0002469 | fluorescent labeling method $b7b3ad13-7be9-4d2b-b154-adeb6b65f908",
+ "is_enabled": true,
+ "id": "0002469",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002477 | fluorescent dye transfer",
+ "title": "fluorescent dye transfer",
+ "value": "BAO:0002477 | fluorescent dye transfer $5a54f9b1-f501-4c49-b55c-b7c2bc7bd881",
+ "is_enabled": true,
+ "id": "0002477",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002472 | fluorescent DNA intercalation method",
+ "title": "fluorescent DNA intercalation method",
+ "value": "BAO:0002472 | fluorescent DNA intercalation method $431b1021-2b3f-4433-8a07-9c5b7d7f585b",
+ "is_enabled": true,
+ "id": "0002472",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002475 | fluorescent intercalator displacement",
+ "title": "fluorescent intercalator displacement",
+ "value": "BAO:0002475 | fluorescent intercalator displacement $340183a7-d023-4f3a-abdf-402b5b65487e",
+ "is_enabled": true,
+ "id": "0002475",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002476 | propidium iodide DNA staining",
+ "title": "propidium iodide DNA staining",
+ "value": "BAO:0002476 | propidium iodide DNA staining $887ec240-436a-4035-a03d-13b4cde9da00",
+ "is_enabled": true,
+ "id": "0002476",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002473 | SYBR Green I DNA staining",
+ "title": "SYBR Green I DNA staining",
+ "value": "BAO:0002473 | SYBR Green I DNA staining $e8411668-fe20-4f77-bcce-6d773a9243a1",
+ "is_enabled": true,
+ "id": "0002473",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002474 | ethidium bromide DNA staining",
+ "title": "ethidium bromide DNA staining",
+ "value": "BAO:0002474 | ethidium bromide DNA staining $064f18fb-3f0c-4a4f-88d4-3db540f48cc4",
+ "is_enabled": true,
+ "id": "0002474",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002470 | fluorescent DNA hybridization probe method",
+ "title": "fluorescent DNA hybridization probe method",
+ "value": "BAO:0002470 | fluorescent DNA hybridization probe method $3656ae79-bd27-4510-b81a-a38182020a5a",
+ "is_enabled": true,
+ "id": "0002470",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002471 | fluorescent DNA hydrolysis probe method",
+ "title": "fluorescent DNA hydrolysis probe method",
+ "value": "BAO:0002471 | fluorescent DNA hydrolysis probe method $74c79570-3256-40a0-9154-dca321ffa48c",
+ "is_enabled": true,
+ "id": "0002471",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002453 | colorimetric labeling method",
+ "title": "colorimetric labeling method",
+ "value": "BAO:0002453 | colorimetric labeling method $03b0dc7c-f2e2-4843-99b3-be0a0f4ecc90",
+ "is_enabled": true,
+ "id": "0002453",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002468 | crystal violet staining",
+ "title": "crystal violet staining",
+ "value": "BAO:0002468 | crystal violet staining $9bd3653c-764a-487f-b1d3-c2de509eb9ea",
+ "is_enabled": true,
+ "id": "0002468",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002462 | colorimetric protein staining method",
+ "title": "colorimetric protein staining method",
+ "value": "BAO:0002462 | colorimetric protein staining method $d113fd76-632f-497c-90f4-5f3ff95a10f4",
+ "is_enabled": true,
+ "id": "0002462",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002466 | Ponceau S protein staining",
+ "title": "Ponceau S protein staining",
+ "value": "BAO:0002466 | Ponceau S protein staining $7f308142-d706-4902-9055-9f2cf2fe44f6",
+ "is_enabled": true,
+ "id": "0002466",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002467 | bicinchoninic acid assay",
+ "title": "bicinchoninic acid assay",
+ "value": "BAO:0002467 | bicinchoninic acid assay $cfc661c1-d20d-4043-b0b7-646c378a05d6",
+ "is_enabled": true,
+ "id": "0002467",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002460 | sulforhodamine B staining",
+ "title": "sulforhodamine B staining",
+ "value": "BAO:0002460 | sulforhodamine B staining $ace9c2ad-8041-4bae-b35d-cb1df94fbeee",
+ "is_enabled": true,
+ "id": "0002460",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002464 | Coomassie dye protein staining",
+ "title": "Coomassie dye protein staining",
+ "value": "BAO:0002464 | Coomassie dye protein staining $d9042aeb-ea0f-4f40-86da-6b4fd9b021e3",
+ "is_enabled": true,
+ "id": "0002464",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002465 | Lowry assay",
+ "title": "Lowry assay",
+ "value": "BAO:0002465 | Lowry assay $5e013bfc-5ebc-45fc-b382-47f05c34a099",
+ "is_enabled": true,
+ "id": "0002465",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002463 | Bradford protein assay",
+ "title": "Bradford protein assay",
+ "value": "BAO:0002463 | Bradford protein assay $b920e1c7-bbda-47a5-ba03-da713bc23a35",
+ "is_enabled": true,
+ "id": "0002463",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002455 | colorimetric cell staining method",
+ "title": "colorimetric cell staining method",
+ "value": "BAO:0002455 | colorimetric cell staining method $3370404f-a4b8-4221-bc4e-3038410af0ee",
+ "is_enabled": true,
+ "id": "0002455",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002460 | sulforhodamine B staining",
+ "title": "sulforhodamine B staining",
+ "value": "BAO:0002460 | sulforhodamine B staining $aa62726b-3bbf-4b75-99e9-9c15d64f00c9",
+ "is_enabled": true,
+ "id": "0002460",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002461 | trypan blue cell staining",
+ "title": "trypan blue cell staining",
+ "value": "BAO:0002461 | trypan blue cell staining $8df7ede2-a533-4f58-a7ef-dc0037f473eb",
+ "is_enabled": true,
+ "id": "0002461",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002457 | MTT reduction assay",
+ "title": "MTT reduction assay",
+ "value": "BAO:0002457 | MTT reduction assay $30e31fd2-6337-46fe-9b52-8c4e7dfdf771",
+ "is_enabled": true,
+ "id": "0002457",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002458 | XTT reduction assay",
+ "title": "XTT reduction assay",
+ "value": "BAO:0002458 | XTT reduction assay $f9e27fe3-7918-4b99-b753-6f33e3cce9af",
+ "is_enabled": true,
+ "id": "0002458",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002456 | MTS reduction assay",
+ "title": "MTS reduction assay",
+ "value": "BAO:0002456 | MTS reduction assay $831005f6-31b0-481e-a035-502a0f29db81",
+ "is_enabled": true,
+ "id": "0002456",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002459 | resazurin reduction assay",
+ "title": "resazurin reduction assay",
+ "value": "BAO:0002459 | resazurin reduction assay $3980ce1f-af7a-465d-9f38-18885660f30b",
+ "is_enabled": true,
+ "id": "0002459",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002480 | vital dye staining",
+ "title": "vital dye staining",
+ "value": "BAO:0002480 | vital dye staining $eecdbf26-b4bf-44b3-9354-fa00ba15d980",
+ "is_enabled": true,
+ "id": "0002480",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002483 | vital staining of cells",
+ "title": "vital staining of cells",
+ "value": "BAO:0002483 | vital staining of cells $c380777c-0f08-47f7-9d50-de989cc14f39",
+ "is_enabled": true,
+ "id": "0002483",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002481 | dye exclusion method",
+ "title": "dye exclusion method",
+ "value": "BAO:0002481 | dye exclusion method $891b21ee-71d2-45fe-91cf-9ed8fde1fa5d",
+ "is_enabled": true,
+ "id": "0002481",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002461 | trypan blue cell staining",
+ "title": "trypan blue cell staining",
+ "value": "BAO:0002461 | trypan blue cell staining $5139b698-35e5-49fd-9738-a717430a3f64",
+ "is_enabled": true,
+ "id": "0002461",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002482 | propidium iodide exclusion",
+ "title": "propidium iodide exclusion",
+ "value": "BAO:0002482 | propidium iodide exclusion $b57ce889-bffb-432f-ada0-5847dcfb6f10",
+ "is_enabled": true,
+ "id": "0002482",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002484 | vital staining of organelles",
+ "title": "vital staining of organelles",
+ "value": "BAO:0002484 | vital staining of organelles $ddbb9267-844f-4b38-a7c6-3afcd6da2333",
+ "is_enabled": true,
+ "id": "0002484",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002479 | photoaffinity labeling",
+ "title": "photoaffinity labeling",
+ "value": "BAO:0002479 | photoaffinity labeling $82ad0082-3aa2-49dd-9ce9-d01b9ec7c4a9",
+ "is_enabled": true,
+ "id": "0002479",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002478 | isotope labeling method",
+ "title": "isotope labeling method",
+ "value": "BAO:0002478 | isotope labeling method $659da5bc-206e-48d7-88aa-5067be63d38a",
+ "is_enabled": true,
+ "id": "0002478",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002485 | reconstitution method",
+ "title": "reconstitution method",
+ "value": "BAO:0002485 | reconstitution method $3e768dca-2f9f-498e-82cd-3be4ef27c510",
+ "is_enabled": true,
+ "id": "0002485",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002486 | complementation method",
+ "title": "complementation method",
+ "value": "BAO:0002486 | complementation method $4800f3ed-80a7-4f0c-8118-5b29a831c48d",
+ "is_enabled": true,
+ "id": "0002486",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002488 | genetic complementation",
+ "title": "genetic complementation",
+ "value": "BAO:0002488 | genetic complementation $b5c7b190-8f62-45e7-b1a2-4489af23ec9a",
+ "is_enabled": true,
+ "id": "0002488",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002489 | hybrid screening",
+ "title": "hybrid screening",
+ "value": "BAO:0002489 | hybrid screening $c1cbbc47-5ed7-456a-a66f-4f894cf42cb4",
+ "is_enabled": true,
+ "id": "0002489",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002491 | three-hybrid assay",
+ "title": "three-hybrid assay",
+ "value": "BAO:0002491 | three-hybrid assay $70ab60d4-0f20-460f-957a-4c7de1f91b19",
+ "is_enabled": true,
+ "id": "0002491",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002492 | two-hybrid assay",
+ "title": "two-hybrid assay",
+ "value": "BAO:0002492 | two-hybrid assay $36e02f84-d27a-4fb6-bb2f-f14a96e2cd89",
+ "is_enabled": true,
+ "id": "0002492",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002493 | mammalian two-hybrid assay",
+ "title": "mammalian two-hybrid assay",
+ "value": "BAO:0002493 | mammalian two-hybrid assay $9c72883d-056b-4ba7-a007-c5e286d90290",
+ "is_enabled": true,
+ "id": "0002493",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002494 | yeast two-hybrid assay",
+ "title": "yeast two-hybrid assay",
+ "value": "BAO:0002494 | yeast two-hybrid assay $a0da0b47-1f36-4348-ba56-ca179afb57e6",
+ "is_enabled": true,
+ "id": "0002494",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002490 | one-hybrid assay",
+ "title": "one-hybrid assay",
+ "value": "BAO:0002490 | one-hybrid assay $f7670f4c-bf6f-4d85-bba1-ca365bd4b441",
+ "is_enabled": true,
+ "id": "0002490",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002487 | chemical complementation",
+ "title": "chemical complementation",
+ "value": "BAO:0002487 | chemical complementation $20c0ba01-740a-4b6a-a57f-0a7e9b1006d2",
+ "is_enabled": true,
+ "id": "0002487",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002495 | protein complementation",
+ "title": "protein complementation",
+ "value": "BAO:0002495 | protein complementation $1182c111-fc34-4bda-81ec-067ec024e67a",
+ "is_enabled": true,
+ "id": "0002495",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002496 | enzyme complementation",
+ "title": "enzyme complementation",
+ "value": "BAO:0002496 | enzyme complementation $6a31feef-3ae5-4fc1-a564-b2a9bbbc30e4",
+ "is_enabled": true,
+ "id": "0002496",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002497 | enzyme fragment complementation",
+ "title": "enzyme fragment complementation",
+ "value": "BAO:0002497 | enzyme fragment complementation $76dd2a1f-418e-4a4c-82fd-aece1503be74",
+ "is_enabled": true,
+ "id": "0002497",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002499 | parallel artificial membrane permeation assay",
+ "title": "parallel artificial membrane permeation assay",
+ "value": "BAO:0002499 | parallel artificial membrane permeation assay $bfbf3e3f-3824-47e1-92cb-1ffdaa069f5a",
+ "is_enabled": true,
+ "id": "0002499",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002498 | liposome reconstitution",
+ "title": "liposome reconstitution",
+ "value": "BAO:0002498 | liposome reconstitution $77af37bc-8b7d-446b-9c2d-6d68a67cd05f",
+ "is_enabled": true,
+ "id": "0002498",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002197 | modification method",
+ "title": "modification method",
+ "value": "BAO:0002197 | modification method $ff0e26ee-8f0a-4dde-8d91-07cba525672f",
+ "is_enabled": true,
+ "id": "0002197",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000238 | cell line modification method",
+ "title": "cell line modification method",
+ "value": "BAO:0000238 | cell line modification method $5e9f3442-22dd-475b-b64a-bb64c25c1455",
+ "is_enabled": true,
+ "id": "0000238",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000241 | genetic modification method",
+ "title": "genetic modification method",
+ "value": "BAO:0000241 | genetic modification method $ffdbe8ff-e2e4-4cd5-9a18-6d76a133c488",
+ "is_enabled": true,
+ "id": "0000241",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000245 | transfection method",
+ "title": "transfection method",
+ "value": "BAO:0000245 | transfection method $4724539d-2e17-4e7b-a2f9-da8a3d147bee",
+ "is_enabled": true,
+ "id": "0000245",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000247 | transient transfection",
+ "title": "transient transfection",
+ "value": "BAO:0000247 | transient transfection $48ca3f2b-06b9-4f44-838d-f95af7f5f844",
+ "is_enabled": true,
+ "id": "0000247",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000246 | stable transfection",
+ "title": "stable transfection",
+ "value": "BAO:0000246 | stable transfection $180d522b-4804-4b38-863c-9e121faff766",
+ "is_enabled": true,
+ "id": "0000246",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000244 | viral transduction method",
+ "title": "viral transduction method",
+ "value": "BAO:0000244 | viral transduction method $5e248d3d-b164-4e21-9d21-6711d0554157",
+ "is_enabled": true,
+ "id": "0000244",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000546 | pathogenic virus transduction method",
+ "title": "pathogenic virus transduction method",
+ "value": "BAO:0000546 | pathogenic virus transduction method $6a509b5d-6371-405e-94f1-db71cec71d20",
+ "is_enabled": true,
+ "id": "0000546",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000545 | recombinant virus transduction method",
+ "title": "recombinant virus transduction method",
+ "value": "BAO:0000545 | recombinant virus transduction method $6a7650ee-c6d2-46eb-a982-8aabfc3f9924",
+ "is_enabled": true,
+ "id": "0000545",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000240 | cell fusion method",
+ "title": "cell fusion method",
+ "value": "BAO:0000240 | cell fusion method $a53ce0ec-7e73-483b-958a-9ef478b22edb",
+ "is_enabled": true,
+ "id": "0000240",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000243 | hybrid cell creation method",
+ "title": "hybrid cell creation method",
+ "value": "BAO:0000243 | hybrid cell creation method $dab25cbb-aee2-4cf7-a712-3455e9e023c7",
+ "is_enabled": true,
+ "id": "0000243",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000242 | cybrid cell creation method",
+ "title": "cybrid cell creation method",
+ "value": "BAO:0000242 | cybrid cell creation method $a543c1a3-07df-4b92-82a9-cbba8636c6fe",
+ "is_enabled": true,
+ "id": "0000242",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000547 | bacterial infection method",
+ "title": "bacterial infection method",
+ "value": "BAO:0000547 | bacterial infection method $2787e41c-a4f0-4fab-8631-2ad72321deb3",
+ "is_enabled": true,
+ "id": "0000547",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002632 | protein modification method",
+ "title": "protein modification method",
+ "value": "BAO:0002632 | protein modification method $8b71d945-2665-4a34-ab07-50611c95fc79",
+ "is_enabled": true,
+ "id": "0002632",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002631 | protein denaturation method",
+ "title": "protein denaturation method",
+ "value": "BAO:0002631 | protein denaturation method $c45ba1d4-24d2-4a56-b121-ecea7dffaef7",
+ "is_enabled": true,
+ "id": "0002631",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002633 | heat denaturation",
+ "title": "heat denaturation",
+ "value": "BAO:0002633 | heat denaturation $b757fc33-2034-4565-894e-db7b81ff0e16",
+ "is_enabled": true,
+ "id": "0002633",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002634 | chemical denaturation",
+ "title": "chemical denaturation",
+ "value": "BAO:0002634 | chemical denaturation $85976a32-6aa1-494b-9381-1e5c1fd24146",
+ "is_enabled": true,
+ "id": "0002634",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002635 | RNA modification method",
+ "title": "RNA modification method",
+ "value": "BAO:0002635 | RNA modification method $144a7e41-7a4c-408c-8831-ab3401fb582a",
+ "is_enabled": true,
+ "id": "0002635",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002165 | silencing RNA modification method",
+ "title": "silencing RNA modification method",
+ "value": "BAO:0002165 | silencing RNA modification method $26a51e17-c547-4df5-bf1d-bc1d9ebe1f3d",
+ "is_enabled": true,
+ "id": "0002165",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002198 | delivery method",
+ "title": "delivery method",
+ "value": "BAO:0002198 | delivery method $88a44977-c858-4a92-ad74-cf52878c4d64",
+ "is_enabled": true,
+ "id": "0002198",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000573 | perturbagen delivery method",
+ "title": "perturbagen delivery method",
+ "value": "BAO:0000573 | perturbagen delivery method $3c740155-c57f-48da-9896-a4d5610ce945",
+ "is_enabled": true,
+ "id": "0000573",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000575 | mixture of perturbagens",
+ "title": "mixture of perturbagens",
+ "value": "BAO:0000575 | mixture of perturbagens $f3e861c6-1aa8-4575-9564-40f4bfbea541",
+ "is_enabled": true,
+ "id": "0000575",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000574 | single perturbagen",
+ "title": "single perturbagen",
+ "value": "BAO:0000574 | single perturbagen $daf2a8a4-b891-461d-bcc1-20a2780a7d55",
+ "is_enabled": true,
+ "id": "0000574",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002155 | silencing RNA delivery method",
+ "title": "silencing RNA delivery method",
+ "value": "BAO:0002155 | silencing RNA delivery method $9516fb26-91e8-4393-b1f3-54bcb16e802e",
+ "is_enabled": true,
+ "id": "0002155",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000245 | transfection method",
+ "title": "transfection method",
+ "value": "BAO:0000245 | transfection method $6704bd9c-67a7-470f-bf44-2dd0f76e3e0e",
+ "is_enabled": true,
+ "id": "0000245",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000247 | transient transfection",
+ "title": "transient transfection",
+ "value": "BAO:0000247 | transient transfection $379de541-36ab-44fd-af37-ad2ccf153347",
+ "is_enabled": true,
+ "id": "0000247",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000246 | stable transfection",
+ "title": "stable transfection",
+ "value": "BAO:0000246 | stable transfection $52e8849b-4084-497c-a802-f6a49e798a93",
+ "is_enabled": true,
+ "id": "0000246",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000545 | recombinant virus transduction method",
+ "title": "recombinant virus transduction method",
+ "value": "BAO:0000545 | recombinant virus transduction method $43012dfd-5569-425e-a26a-bd47eb426fa6",
+ "is_enabled": true,
+ "id": "0000545",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002202 | assay design method",
+ "title": "assay design method",
+ "value": "BAO:0002202 | assay design method $0b1c5853-cfdf-411d-9ac4-645724e82807",
+ "is_enabled": true,
+ "id": "0002202",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000124 | enzyme activity measurement method",
+ "title": "enzyme activity measurement method",
+ "value": "BAO:0000124 | enzyme activity measurement method $0ac89440-062b-4506-b375-54b8de2c0ae3",
+ "is_enabled": true,
+ "id": "0000124",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000142 | coupled enzyme activity measurement method",
+ "title": "coupled enzyme activity measurement method",
+ "value": "BAO:0000142 | coupled enzyme activity measurement method $f3c1048d-d765-4e4a-b4ad-210550c3f6ca",
+ "is_enabled": true,
+ "id": "0000142",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002730 | cofactor coupled enzyme activity measurement method",
+ "title": "cofactor coupled enzyme activity measurement method",
+ "value": "BAO:0002730 | cofactor coupled enzyme activity measurement method $1c719a6a-58b2-4ae5-9229-1f1dfc7539f2",
+ "is_enabled": true,
+ "id": "0002730",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002592 | protease coupled enzyme activity measurement method",
+ "title": "protease coupled enzyme activity measurement method",
+ "value": "BAO:0002592 | protease coupled enzyme activity measurement method $2980ec08-e814-4d97-a682-4b4ac72e710c",
+ "is_enabled": true,
+ "id": "0002592",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002593 | substrate coupled enzyme activity measurement method",
+ "title": "substrate coupled enzyme activity measurement method",
+ "value": "BAO:0002593 | substrate coupled enzyme activity measurement method $b99dd474-371d-4637-a774-20df5008fe84",
+ "is_enabled": true,
+ "id": "0002593",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002791 | ADP coupled enzyme activity measurement method",
+ "title": "ADP coupled enzyme activity measurement method",
+ "value": "BAO:0002791 | ADP coupled enzyme activity measurement method $87e8adb2-a542-41e2-b31e-b5b79c4e0877",
+ "is_enabled": true,
+ "id": "0002791",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002594 | ATP coupled enzyme activity measurement method",
+ "title": "ATP coupled enzyme activity measurement method",
+ "value": "BAO:0002594 | ATP coupled enzyme activity measurement method $38578f82-b7f2-4fb8-854f-06e83739b87c",
+ "is_enabled": true,
+ "id": "0002594",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002595 | luciferin coupled enzyme activity measurement method",
+ "title": "luciferin coupled enzyme activity measurement method",
+ "value": "BAO:0002595 | luciferin coupled enzyme activity measurement method $82de7f75-e0b2-4b63-9921-b7ced5f98b3a",
+ "is_enabled": true,
+ "id": "0002595",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002591 | chaperone coupled enzyme activity measurement method",
+ "title": "chaperone coupled enzyme activity measurement method",
+ "value": "BAO:0002591 | chaperone coupled enzyme activity measurement method $1061f5c0-5912-480b-afdd-a0cea2b1dcb8",
+ "is_enabled": true,
+ "id": "0002591",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000139 | direct enzyme activity measurement method",
+ "title": "direct enzyme activity measurement method",
+ "value": "BAO:0000139 | direct enzyme activity measurement method $a9cd40a4-0c8b-42df-b3ac-22f3a4830862",
+ "is_enabled": true,
+ "id": "0000139",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002734 | luciferase enzyme activity measurement method",
+ "title": "luciferase enzyme activity measurement method",
+ "value": "BAO:0002734 | luciferase enzyme activity measurement method $8546b813-d499-4c65-bf3f-78b69733a5c3",
+ "is_enabled": true,
+ "id": "0002734",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040016 | Beta-galactosidase activity measurement method",
+ "title": "Beta-galactosidase activity measurement method",
+ "value": "BAO:0040016 | Beta-galactosidase activity measurement method $3c6d83d1-86aa-48f5-8871-9c4eb4178230",
+ "is_enabled": true,
+ "id": "0040016",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000123 | binding assessment method",
+ "title": "binding assessment method",
+ "value": "BAO:0000123 | binding assessment method $5cb21a10-9f86-43ec-954f-4fb1f0b497f0",
+ "is_enabled": true,
+ "id": "0000123",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002755 | fluorescent ligand binding method",
+ "title": "fluorescent ligand binding method",
+ "value": "BAO:0002755 | fluorescent ligand binding method $e2166005-af76-4354-a91b-439537da7a01",
+ "is_enabled": true,
+ "id": "0002755",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040032 | NanoBRET",
+ "title": "NanoBRET",
+ "value": "BAO:0040032 | NanoBRET $681c285c-12e9-49fb-bcf8-de5138e39834",
+ "is_enabled": true,
+ "id": "0040032",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000129 | immunoassay",
+ "title": "immunoassay",
+ "value": "BAO:0000129 | immunoassay $e7e83fde-1772-4a0c-aac0-a2205cd9852c",
+ "is_enabled": true,
+ "id": "0000129",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000128 | in situ immunoassay",
+ "title": "in situ immunoassay",
+ "value": "BAO:0000128 | in situ immunoassay $89efe4d8-759a-4c5b-8256-2e675ef71433",
+ "is_enabled": true,
+ "id": "0000128",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000416 | immunocytochemistry",
+ "title": "immunocytochemistry",
+ "value": "BAO:0000416 | immunocytochemistry $a79ac7b7-a86d-4f76-b5cb-6ce6b6240ca7",
+ "is_enabled": true,
+ "id": "0000416",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000415 | immunohistochemistry",
+ "title": "immunohistochemistry",
+ "value": "BAO:0000415 | immunohistochemistry $f72b0986-ead0-4432-ac9f-f004932939b7",
+ "is_enabled": true,
+ "id": "0000415",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000466 | ex situ immunoassay",
+ "title": "ex situ immunoassay",
+ "value": "BAO:0000466 | ex situ immunoassay $acb4c453-7abc-46cf-b48d-7d16f53270d4",
+ "is_enabled": true,
+ "id": "0000466",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000134 | ELISA",
+ "title": "ELISA",
+ "value": "BAO:0000134 | ELISA $acc01097-5d31-4a3b-8531-a787465f8351",
+ "is_enabled": true,
+ "id": "0000134",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000137 | antigen down assay",
+ "title": "antigen down assay",
+ "value": "BAO:0000137 | antigen down assay $921a9b80-94a7-4ec6-a21e-98450cc771be",
+ "is_enabled": true,
+ "id": "0000137",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000132 | competitive immunoassay",
+ "title": "competitive immunoassay",
+ "value": "BAO:0000132 | competitive immunoassay $1e03a56e-a804-450f-8a67-38a70fc01398",
+ "is_enabled": true,
+ "id": "0000132",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002420 | fluorescence-linked immunosorbent assay",
+ "title": "fluorescence-linked immunosorbent assay",
+ "value": "BAO:0002420 | fluorescence-linked immunosorbent assay $ce3856eb-03a2-473a-a870-879579fd2a0b",
+ "is_enabled": true,
+ "id": "0002420",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002421 | sandwich ELISA",
+ "title": "sandwich ELISA",
+ "value": "BAO:0002421 | sandwich ELISA $f6eb518f-02b2-43bc-9dcc-38bb55d89472",
+ "is_enabled": true,
+ "id": "0002421",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002419 | enzyme-linked immunosorbent spot assay",
+ "title": "enzyme-linked immunosorbent spot assay",
+ "value": "BAO:0002419 | enzyme-linked immunosorbent spot assay $7158e7c9-0238-4a24-9622-f52fb55f0a1f",
+ "is_enabled": true,
+ "id": "0002419",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002417 | chemiluminescence-linked immunosorbent assay",
+ "title": "chemiluminescence-linked immunosorbent assay",
+ "value": "BAO:0002417 | chemiluminescence-linked immunosorbent assay $956cfc3d-1807-4107-a721-408acd0f7ef5",
+ "is_enabled": true,
+ "id": "0002417",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0010266 | Epitope Mapping",
+ "title": "Epitope Mapping",
+ "value": "BAO:0010266 | Epitope Mapping $b04d0f70-5824-4281-8dd7-819c1a3e08d5",
+ "is_enabled": true,
+ "id": "0010266",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002401 | enzyme-multiplied immunoassay technique",
+ "title": "enzyme-multiplied immunoassay technique",
+ "value": "BAO:0002401 | enzyme-multiplied immunoassay technique $77d1f2fd-c288-4cd3-bf80-6772ec515b87",
+ "is_enabled": true,
+ "id": "0002401",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002422 | immunoblot",
+ "title": "immunoblot",
+ "value": "BAO:0002422 | immunoblot $8a1c79e9-51b8-4334-8050-b819c0feabb0",
+ "is_enabled": true,
+ "id": "0002422",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002424 | western blot",
+ "title": "western blot",
+ "value": "BAO:0002424 | western blot $03f82a0b-22f0-45d8-b205-78317203f141",
+ "is_enabled": true,
+ "id": "0002424",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002423 | in-cell western assay",
+ "title": "in-cell western assay",
+ "value": "BAO:0002423 | in-cell western assay $7febe2c3-daf3-478e-8914-c78c60090463",
+ "is_enabled": true,
+ "id": "0002423",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002428 | radioimmunoassay",
+ "title": "radioimmunoassay",
+ "value": "BAO:0002428 | radioimmunoassay $6e49080f-67bd-47a1-b470-1d686ab06be2",
+ "is_enabled": true,
+ "id": "0002428",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002411 | two site enzyme immunoassay",
+ "title": "two site enzyme immunoassay",
+ "value": "BAO:0002411 | two site enzyme immunoassay $d2a469b7-3c5d-4d93-9cb0-f75b0bfb12a2",
+ "is_enabled": true,
+ "id": "0002411",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002415 | dot immunobinding assay",
+ "title": "dot immunobinding assay",
+ "value": "BAO:0002415 | dot immunobinding assay $de083d56-65c8-4fc0-b970-4dc4acdcda16",
+ "is_enabled": true,
+ "id": "0002415",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002892 | second messenger competitive binding assessment method",
+ "title": "second messenger competitive binding assessment method",
+ "value": "BAO:0002892 | second messenger competitive binding assessment method $f388b58a-44b8-4bda-a1ac-852f537a579e",
+ "is_enabled": true,
+ "id": "0002892",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000406 | protein fragment complementation method",
+ "title": "protein fragment complementation method",
+ "value": "BAO:0000406 | protein fragment complementation method $cad09821-7461-41cc-a771-c59223de2f2d",
+ "is_enabled": true,
+ "id": "0000406",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000402 | radioligand binding method",
+ "title": "radioligand binding method",
+ "value": "BAO:0000402 | radioligand binding method $1e32178a-9edb-4e45-9ff6-4e793b6cf4eb",
+ "is_enabled": true,
+ "id": "0000402",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003033 | mobility shift assessment method",
+ "title": "mobility shift assessment method",
+ "value": "BAO:0003033 | mobility shift assessment method $3e8b9a91-6ab8-4b37-8d92-8efd3201f506",
+ "is_enabled": true,
+ "id": "0003033",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040033 | ligand covalent binding method",
+ "title": "ligand covalent binding method",
+ "value": "BAO:0040033 | ligand covalent binding method $913c85cd-44bd-4fa7-b42a-450a9a41eed6",
+ "is_enabled": true,
+ "id": "0040033",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040040 | unnatural amino acid ligand covalent binding method",
+ "title": "unnatural amino acid ligand covalent binding method",
+ "value": "BAO:0040040 | unnatural amino acid ligand covalent binding method $2bbcf401-d23e-45a7-9325-c600df11f88b",
+ "is_enabled": true,
+ "id": "0040040",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040034 | lysine ligand covalent binding method",
+ "title": "lysine ligand covalent binding method",
+ "value": "BAO:0040034 | lysine ligand covalent binding method $16da41f2-5419-44c6-babb-17408d4c666e",
+ "is_enabled": true,
+ "id": "0040034",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040041 | cysteine ligand covalent binding method",
+ "title": "cysteine ligand covalent binding method",
+ "value": "BAO:0040041 | cysteine ligand covalent binding method $e716d074-e6ce-4886-85df-412e7b8f32e0",
+ "is_enabled": true,
+ "id": "0040041",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040037 | tyrosine ligand covalent binding method",
+ "title": "tyrosine ligand covalent binding method",
+ "value": "BAO:0040037 | tyrosine ligand covalent binding method $ea52d662-da80-4f1e-a1a8-6f625b6595a7",
+ "is_enabled": true,
+ "id": "0040037",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040038 | N-terminal ligand covalent binding method",
+ "title": "N-terminal ligand covalent binding method",
+ "value": "BAO:0040038 | N-terminal ligand covalent binding method $1ae9b8cf-e251-4e45-9d10-9558a960e543",
+ "is_enabled": true,
+ "id": "0040038",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040035 | methionine ligand covalent binding method",
+ "title": "methionine ligand covalent binding method",
+ "value": "BAO:0040035 | methionine ligand covalent binding method $f2387d45-e81f-4174-a858-14a0ec01053e",
+ "is_enabled": true,
+ "id": "0040035",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040036 | serine ligand covalent binding method",
+ "title": "serine ligand covalent binding method",
+ "value": "BAO:0040036 | serine ligand covalent binding method $ff31997a-b673-47d6-8c11-bacf2d7f7108",
+ "is_enabled": true,
+ "id": "0040036",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040039 | threonine ligand covalent binding method",
+ "title": "threonine ligand covalent binding method",
+ "value": "BAO:0040039 | threonine ligand covalent binding method $18272b4b-3918-4e13-9e5a-11ea25dae40c",
+ "is_enabled": true,
+ "id": "0040039",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040024 | thermal shift assessment method",
+ "title": "thermal shift assessment method",
+ "value": "BAO:0040024 | thermal shift assessment method $e6f069ec-0674-4039-a647-3ed23a468e45",
+ "is_enabled": true,
+ "id": "0040024",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0010267 | equilibrium assay",
+ "title": "equilibrium assay",
+ "value": "BAO:0010267 | equilibrium assay $7f2697a5-cfa8-45d8-88aa-a7c64c6a725e",
+ "is_enabled": true,
+ "id": "0010267",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000126 | molecular redistribution determination method",
+ "title": "molecular redistribution determination method",
+ "value": "BAO:0000126 | molecular redistribution determination method $b5648167-defb-4e35-b25a-85bdf6f780c0",
+ "is_enabled": true,
+ "id": "0000126",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000129 | immunoassay",
+ "title": "immunoassay",
+ "value": "BAO:0000129 | immunoassay $147d6185-33be-4697-b462-c638130d10f5",
+ "is_enabled": true,
+ "id": "0000129",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000128 | in situ immunoassay",
+ "title": "in situ immunoassay",
+ "value": "BAO:0000128 | in situ immunoassay $d28f1c1d-b365-41be-ad2e-a44f919274b3",
+ "is_enabled": true,
+ "id": "0000128",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000416 | immunocytochemistry",
+ "title": "immunocytochemistry",
+ "value": "BAO:0000416 | immunocytochemistry $0cad7c4f-cae7-4ea9-afe6-e65db403f15a",
+ "is_enabled": true,
+ "id": "0000416",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000415 | immunohistochemistry",
+ "title": "immunohistochemistry",
+ "value": "BAO:0000415 | immunohistochemistry $d172b29a-a905-4669-918c-3a275c70184a",
+ "is_enabled": true,
+ "id": "0000415",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000466 | ex situ immunoassay",
+ "title": "ex situ immunoassay",
+ "value": "BAO:0000466 | ex situ immunoassay $11a4c55a-0acc-459b-8ecf-cc704f2960fa",
+ "is_enabled": true,
+ "id": "0000466",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000134 | ELISA",
+ "title": "ELISA",
+ "value": "BAO:0000134 | ELISA $8778b896-71e7-4fd5-a628-e85fff9bba56",
+ "is_enabled": true,
+ "id": "0000134",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000137 | antigen down assay",
+ "title": "antigen down assay",
+ "value": "BAO:0000137 | antigen down assay $ca58b5c2-ddd2-4275-b457-f3fa853e8b61",
+ "is_enabled": true,
+ "id": "0000137",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000132 | competitive immunoassay",
+ "title": "competitive immunoassay",
+ "value": "BAO:0000132 | competitive immunoassay $1fe38e64-c60e-4a69-8f84-0ff7583be33e",
+ "is_enabled": true,
+ "id": "0000132",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002420 | fluorescence-linked immunosorbent assay",
+ "title": "fluorescence-linked immunosorbent assay",
+ "value": "BAO:0002420 | fluorescence-linked immunosorbent assay $cba283ee-e7b4-45eb-bca7-0af9867c5baa",
+ "is_enabled": true,
+ "id": "0002420",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002421 | sandwich ELISA",
+ "title": "sandwich ELISA",
+ "value": "BAO:0002421 | sandwich ELISA $c66c0564-c324-47d4-8d47-8aa4ee030f35",
+ "is_enabled": true,
+ "id": "0002421",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002419 | enzyme-linked immunosorbent spot assay",
+ "title": "enzyme-linked immunosorbent spot assay",
+ "value": "BAO:0002419 | enzyme-linked immunosorbent spot assay $af09a5f0-7e63-4f56-a654-0383e8cbb3f0",
+ "is_enabled": true,
+ "id": "0002419",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002417 | chemiluminescence-linked immunosorbent assay",
+ "title": "chemiluminescence-linked immunosorbent assay",
+ "value": "BAO:0002417 | chemiluminescence-linked immunosorbent assay $c2ae362e-6fbb-4abc-b717-dd7eb2df30e3",
+ "is_enabled": true,
+ "id": "0002417",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0010266 | Epitope Mapping",
+ "title": "Epitope Mapping",
+ "value": "BAO:0010266 | Epitope Mapping $23a2cdab-48ee-4328-a9f3-503e3be3e963",
+ "is_enabled": true,
+ "id": "0010266",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002401 | enzyme-multiplied immunoassay technique",
+ "title": "enzyme-multiplied immunoassay technique",
+ "value": "BAO:0002401 | enzyme-multiplied immunoassay technique $662efe75-73e8-4cad-a74b-cd0bbe08fe93",
+ "is_enabled": true,
+ "id": "0002401",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002422 | immunoblot",
+ "title": "immunoblot",
+ "value": "BAO:0002422 | immunoblot $6cc9bca0-6c05-4005-bb66-1d67236b6c91",
+ "is_enabled": true,
+ "id": "0002422",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002424 | western blot",
+ "title": "western blot",
+ "value": "BAO:0002424 | western blot $a9d813f4-5dcd-43e4-9d44-f7a05fd318c9",
+ "is_enabled": true,
+ "id": "0002424",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002423 | in-cell western assay",
+ "title": "in-cell western assay",
+ "value": "BAO:0002423 | in-cell western assay $22ce08d2-b419-45cf-991c-5db0bb3195b6",
+ "is_enabled": true,
+ "id": "0002423",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002428 | radioimmunoassay",
+ "title": "radioimmunoassay",
+ "value": "BAO:0002428 | radioimmunoassay $add240c8-3fb9-4d5a-8a96-5d4701575ea5",
+ "is_enabled": true,
+ "id": "0002428",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002411 | two site enzyme immunoassay",
+ "title": "two site enzyme immunoassay",
+ "value": "BAO:0002411 | two site enzyme immunoassay $ff20f0ee-3773-462e-a98e-fb7e46145102",
+ "is_enabled": true,
+ "id": "0002411",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002415 | dot immunobinding assay",
+ "title": "dot immunobinding assay",
+ "value": "BAO:0002415 | dot immunobinding assay $450ecc38-33f9-44b6-a431-36eea21c7ffa",
+ "is_enabled": true,
+ "id": "0002415",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002888 | ion redistribution determination method",
+ "title": "ion redistribution determination method",
+ "value": "BAO:0002888 | ion redistribution determination method $e491a973-558c-46bc-806c-4da2b05c6148",
+ "is_enabled": true,
+ "id": "0002888",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000127 | viability measurement method",
+ "title": "viability measurement method",
+ "value": "BAO:0000127 | viability measurement method $19a6e2a9-03e5-44be-a52c-bf0f83b6e27c",
+ "is_enabled": true,
+ "id": "0000127",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000167 | membrane permeability assessment",
+ "title": "membrane permeability assessment",
+ "value": "BAO:0000167 | membrane permeability assessment $d4a093e2-d173-4d77-b427-6066541efee9",
+ "is_enabled": true,
+ "id": "0000167",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000169 | dna content estimation",
+ "title": "dna content estimation",
+ "value": "BAO:0000169 | dna content estimation $5d145d96-3b02-4103-92fe-81debfbafa4c",
+ "is_enabled": true,
+ "id": "0000169",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000164 | ATP quantitation",
+ "title": "ATP quantitation",
+ "value": "BAO:0000164 | ATP quantitation $dd2123f4-27d7-4640-994a-b33e7991f36e",
+ "is_enabled": true,
+ "id": "0000164",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002079 | ATP quantitation using luciferase",
+ "title": "ATP quantitation using luciferase",
+ "value": "BAO:0002079 | ATP quantitation using luciferase $6f78a07b-0372-4856-a5e7-7cac91cceaab",
+ "is_enabled": true,
+ "id": "0002079",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000166 | dehydrogenase activity determination",
+ "title": "dehydrogenase activity determination",
+ "value": "BAO:0000166 | dehydrogenase activity determination $128641d2-547e-43ca-bc8a-de41b9babfe3",
+ "is_enabled": true,
+ "id": "0000166",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000165 | caspase activity determination",
+ "title": "caspase activity determination",
+ "value": "BAO:0000165 | caspase activity determination $04b4eff7-821b-4fdc-ae7c-44010d3c30de",
+ "is_enabled": true,
+ "id": "0000165",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000159 | chromatin condensation visualization",
+ "title": "chromatin condensation visualization",
+ "value": "BAO:0000159 | chromatin condensation visualization $bf82e46f-a4b9-4919-b031-3b1cb88a12be",
+ "is_enabled": true,
+ "id": "0000159",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000158 | esterase activity determination",
+ "title": "esterase activity determination",
+ "value": "BAO:0000158 | esterase activity determination $1ad2b33e-d2ea-40e5-9268-8325153c3b21",
+ "is_enabled": true,
+ "id": "0000158",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000170 | protease activity determination",
+ "title": "protease activity determination",
+ "value": "BAO:0000170 | protease activity determination $c75232fa-447c-40e0-8b96-f1eeedf08e27",
+ "is_enabled": true,
+ "id": "0000170",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000073 | phospholipid redistribution estimation",
+ "title": "phospholipid redistribution estimation",
+ "value": "BAO:0000073 | phospholipid redistribution estimation $2bf3e0ff-428f-497a-8b2a-84bbc44e8fe2",
+ "is_enabled": true,
+ "id": "0000073",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000572 | cell number determination",
+ "title": "cell number determination",
+ "value": "BAO:0000572 | cell number determination $99e25475-7216-4fe4-831a-5c01a0922c55",
+ "is_enabled": true,
+ "id": "0000572",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000423 | mitochondrial membrane potential assessment",
+ "title": "mitochondrial membrane potential assessment",
+ "value": "BAO:0000423 | mitochondrial membrane potential assessment $04aafbfa-320e-4c91-beb1-3e672d09a1d0",
+ "is_enabled": true,
+ "id": "0000423",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040015 | cell density determination",
+ "title": "cell density determination",
+ "value": "BAO:0040015 | cell density determination $7e9e17e9-3113-490a-a893-83eeb888b16b",
+ "is_enabled": true,
+ "id": "0040015",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000048 | conformation determination method",
+ "title": "conformation determination method",
+ "value": "BAO:0000048 | conformation determination method $24a068d8-3032-45dd-96f4-eeb24ccd4c8d",
+ "is_enabled": true,
+ "id": "0000048",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000469 | nucleic acid conformation assessment",
+ "title": "nucleic acid conformation assessment",
+ "value": "BAO:0000469 | nucleic acid conformation assessment $7d6a005d-e052-411d-9a8b-7a4389e2f76d",
+ "is_enabled": true,
+ "id": "0000469",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000470 | protein conformation assessment",
+ "title": "protein conformation assessment",
+ "value": "BAO:0000470 | protein conformation assessment $82cac628-4bf2-4a0d-966f-76b8c884e080",
+ "is_enabled": true,
+ "id": "0000470",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000377 | membrane potential measurement method",
+ "title": "membrane potential measurement method",
+ "value": "BAO:0000377 | membrane potential measurement method $b4b97273-5f4e-45b6-a89a-f83ad2456bc6",
+ "is_enabled": true,
+ "id": "0000377",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000425 | dye binding method",
+ "title": "dye binding method",
+ "value": "BAO:0000425 | dye binding method $906df3e8-e10b-445d-82b1-6712335c56c0",
+ "is_enabled": true,
+ "id": "0000425",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000424 | electrophysiological method",
+ "title": "electrophysiological method",
+ "value": "BAO:0000424 | electrophysiological method $895cfbd4-5ef3-4eb2-ae3e-b7ef04d4b45a",
+ "is_enabled": true,
+ "id": "0000424",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000448 | morphology assessment method",
+ "title": "morphology assessment method",
+ "value": "BAO:0000448 | morphology assessment method $6216dcdf-701a-4e8a-aea1-6a6904e3b58a",
+ "is_enabled": true,
+ "id": "0000448",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000128 | in situ immunoassay",
+ "title": "in situ immunoassay",
+ "value": "BAO:0000128 | in situ immunoassay $c0219001-8133-4f84-8faf-38bd5f18680c",
+ "is_enabled": true,
+ "id": "0000128",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000416 | immunocytochemistry",
+ "title": "immunocytochemistry",
+ "value": "BAO:0000416 | immunocytochemistry $68978a3f-9019-4eed-8c28-050385fd17fd",
+ "is_enabled": true,
+ "id": "0000416",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000415 | immunohistochemistry",
+ "title": "immunohistochemistry",
+ "value": "BAO:0000415 | immunohistochemistry $598b0ba4-dba0-4c0b-9347-4b20c959c019",
+ "is_enabled": true,
+ "id": "0000415",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040020 | sub-cellular morphology assessment method",
+ "title": "sub-cellular morphology assessment method",
+ "value": "BAO:0040020 | sub-cellular morphology assessment method $90d5172f-a8d8-41f0-8a37-5fea56149e67",
+ "is_enabled": true,
+ "id": "0040020",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040019 | cellular morphology assessment method",
+ "title": "cellular morphology assessment method",
+ "value": "BAO:0040019 | cellular morphology assessment method $1b56acd7-a1df-4140-8e28-f9205087c479",
+ "is_enabled": true,
+ "id": "0040019",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "NCIT:C16681 | Histology",
+ "title": "Histology",
+ "value": "NCIT:C16681 | Histology $bdfa7cc1-3ecd-406e-9d0f-1c5758d6a2c0",
+ "is_enabled": true,
+ "id": "C16681",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000499 | cell movement measurement method",
+ "title": "cell movement measurement method",
+ "value": "BAO:0000499 | cell movement measurement method $d39b5a5c-da78-4934-adbf-083cf580da0e",
+ "is_enabled": true,
+ "id": "0000499",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002047 | cell cycle progression assessment method",
+ "title": "cell cycle progression assessment method",
+ "value": "BAO:0002047 | cell cycle progression assessment method $4b15bbf9-2dcf-4a7f-811e-268148b12f94",
+ "is_enabled": true,
+ "id": "0002047",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002741 | M phase assessment method",
+ "title": "M phase assessment method",
+ "value": "BAO:0002741 | M phase assessment method $699503af-0582-428e-860b-d1719e7faa1f",
+ "is_enabled": true,
+ "id": "0002741",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002740 | S phase assessment method",
+ "title": "S phase assessment method",
+ "value": "BAO:0002740 | S phase assessment method $9efc136f-7a00-4e60-97a1-75beddef69fe",
+ "is_enabled": true,
+ "id": "0002740",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002017 | cytokine quantitation method",
+ "title": "cytokine quantitation method",
+ "value": "BAO:0002017 | cytokine quantitation method $d3d9f6ef-c5b1-48a4-869f-d9f72ec74df3",
+ "is_enabled": true,
+ "id": "0002017",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000044 | cytokine-specific antibody bead-based method",
+ "title": "cytokine-specific antibody bead-based method",
+ "value": "BAO:0000044 | cytokine-specific antibody bead-based method $2277225b-c10d-43f7-8e3d-305a5f53bc83",
+ "is_enabled": true,
+ "id": "0000044",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002013 | phosphoprotein detection method",
+ "title": "phosphoprotein detection method",
+ "value": "BAO:0002013 | phosphoprotein detection method $93306ce4-b440-4719-b058-9db1d7b71412",
+ "is_enabled": true,
+ "id": "0002013",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003025 | phosphoprotein-specific antibody-coated bead based method",
+ "title": "phosphoprotein-specific antibody-coated bead based method",
+ "value": "BAO:0003025 | phosphoprotein-specific antibody-coated bead based method $5c5e9105-a302-4806-b01f-52ccc8ee0a35",
+ "is_enabled": true,
+ "id": "0003025",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003032 | kinase competitive binding method",
+ "title": "kinase competitive binding method",
+ "value": "BAO:0003032 | kinase competitive binding method $eae0b718-df14-45a9-a8c2-90dd9c98a978",
+ "is_enabled": true,
+ "id": "0003032",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003030 | kinase active-site binding method",
+ "title": "kinase active-site binding method",
+ "value": "BAO:0003030 | kinase active-site binding method $e7bd8dcc-dca3-4d95-96e2-8299df79e8b1",
+ "is_enabled": true,
+ "id": "0003030",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003024 | gene expression detection method",
+ "title": "gene expression detection method",
+ "value": "BAO:0003024 | gene expression detection method $be466e27-a7fa-4f09-893a-9157daec9911",
+ "is_enabled": true,
+ "id": "0003024",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000125 | reporter gene method",
+ "title": "reporter gene method",
+ "value": "BAO:0000125 | reporter gene method $9aa9523a-9ba9-41d8-9e8f-eb7e18fca51b",
+ "is_enabled": true,
+ "id": "0000125",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000151 | beta lactamase induction",
+ "title": "beta lactamase induction",
+ "value": "BAO:0000151 | beta lactamase induction $7042aed3-6daf-4e1d-941d-09fa040db065",
+ "is_enabled": true,
+ "id": "0000151",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000150 | beta galactosidase induction",
+ "title": "beta galactosidase induction",
+ "value": "BAO:0000150 | beta galactosidase induction $9cebb18c-4972-4bb1-be75-a8c16b0c400f",
+ "is_enabled": true,
+ "id": "0000150",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000153 | fluorescent protein induction",
+ "title": "fluorescent protein induction",
+ "value": "BAO:0000153 | fluorescent protein induction $03162dd6-cc35-473c-873d-bab43d4688e4",
+ "is_enabled": true,
+ "id": "0000153",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000152 | luciferase induction",
+ "title": "luciferase induction",
+ "value": "BAO:0000152 | luciferase induction $a763ff9b-97e8-4406-92ba-73942c2b4052",
+ "is_enabled": true,
+ "id": "0000152",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000494 | chloramphenicol acetyltransferase induction",
+ "title": "chloramphenicol acetyltransferase induction",
+ "value": "BAO:0000494 | chloramphenicol acetyltransferase induction $57f7d29e-50b5-4787-896b-298fa962da78",
+ "is_enabled": true,
+ "id": "0000494",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003034 | nucleic acid identification and quantitation method",
+ "title": "nucleic acid identification and quantitation method",
+ "value": "BAO:0003034 | nucleic acid identification and quantitation method $37c28538-62e2-437b-9562-896f767aa904",
+ "is_enabled": true,
+ "id": "0003034",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002022 | dna-coated bead based method",
+ "title": "dna-coated bead based method",
+ "value": "BAO:0002022 | dna-coated bead based method $62c65c0b-bd39-45af-9361-b8c493ba0298",
+ "is_enabled": true,
+ "id": "0002022",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003026 | nucleic acid array method",
+ "title": "nucleic acid array method",
+ "value": "BAO:0003026 | nucleic acid array method $46c2a70f-c4e0-4a44-9709-b24623d7ac4a",
+ "is_enabled": true,
+ "id": "0003026",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002447 | nucleic acid sequencing method",
+ "title": "nucleic acid sequencing method",
+ "value": "BAO:0002447 | nucleic acid sequencing method $50859290-b54d-421c-bc47-4d0046074370",
+ "is_enabled": true,
+ "id": "0002447",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003027 | rna-seq method",
+ "title": "rna-seq method",
+ "value": "BAO:0003027 | rna-seq method $dda47ec6-ef71-4d5e-a751-9895211a134b",
+ "is_enabled": true,
+ "id": "0003027",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040026 | dna-seq method",
+ "title": "dna-seq method",
+ "value": "BAO:0040026 | dna-seq method $b0ee32da-823e-49ff-a772-0f66f223a8f2",
+ "is_enabled": true,
+ "id": "0040026",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002430 | serial analysis of gene expression",
+ "title": "serial analysis of gene expression",
+ "value": "BAO:0002430 | serial analysis of gene expression $49b86c68-4a0a-4967-9d6b-bc5dcd1b174d",
+ "is_enabled": true,
+ "id": "0002430",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002450 | nucleic acid amplification method",
+ "title": "nucleic acid amplification method",
+ "value": "BAO:0002450 | nucleic acid amplification method $51ea9d0d-4e4c-4932-a1e7-16a19eb41408",
+ "is_enabled": true,
+ "id": "0002450",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002080 | polymerase chain reaction",
+ "title": "polymerase chain reaction",
+ "value": "BAO:0002080 | polymerase chain reaction $cca99456-c761-4986-8de9-afbc18657c47",
+ "is_enabled": true,
+ "id": "0002080",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002084 | real-time PCR ",
+ "title": "real-time PCR ",
+ "value": "BAO:0002084 | real-time PCR $38078529-8278-4aa9-af8e-6d0d49387ba0",
+ "is_enabled": true,
+ "id": "0002084",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002089 | reverse transcription PCR",
+ "title": "reverse transcription PCR",
+ "value": "BAO:0002089 | reverse transcription PCR $bed2e37a-11eb-4069-a876-87f5ab103bdc",
+ "is_enabled": true,
+ "id": "0002089",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002090 | quantitative reverse transcription PCR",
+ "title": "quantitative reverse transcription PCR",
+ "value": "BAO:0002090 | quantitative reverse transcription PCR $9260769f-a670-4dca-a1fe-c7b2c2912881",
+ "is_enabled": true,
+ "id": "0002090",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003031 | quantitative PCR",
+ "title": "quantitative PCR",
+ "value": "BAO:0003031 | quantitative PCR $9ff01461-21d2-4eab-aa45-e9e4fc14fe42",
+ "is_enabled": true,
+ "id": "0003031",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040031 | size separation method",
+ "title": "size separation method",
+ "value": "BAO:0040031 | size separation method $f3a51eca-0539-4289-94c1-2b08ac18d8bb",
+ "is_enabled": true,
+ "id": "0040031",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040042 | liquid chromatography-tandem mass spectrometry",
+ "title": "liquid chromatography-tandem mass spectrometry",
+ "value": "BAO:0040042 | liquid chromatography-tandem mass spectrometry $fe09e56c-d23f-4947-b16a-f9a8b0b80a5c",
+ "is_enabled": true,
+ "id": "0040042",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "ERO:0001500 | liquid chromatography ",
+ "title": "liquid chromatography ",
+ "value": "ERO:0001500 | liquid chromatography $895a26ed-fac3-41ad-827a-898f3492d58c",
+ "is_enabled": true,
+ "id": "0001500",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040021 | in vivo assay method",
+ "title": "in vivo assay method",
+ "value": "BAO:0040021 | in vivo assay method $8fbea934-3f23-4a62-9453-08db1a10c605",
+ "is_enabled": true,
+ "id": "0040021",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040022 | in vivo efficacy method",
+ "title": "in vivo efficacy method",
+ "value": "BAO:0040022 | in vivo efficacy method $d583b5df-8c2d-4e5a-a709-0171f9f9cc39",
+ "is_enabled": true,
+ "id": "0040022",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040023 | in vivo PK/PD/Tox method",
+ "title": "in vivo PK/PD/Tox method",
+ "value": "BAO:0040023 | in vivo PK/PD/Tox method $e2ac62e1-0978-45c0-a79b-ef6ee5fedeb7",
+ "is_enabled": true,
+ "id": "0040023",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040027 | chromatin acessibility method",
+ "title": "chromatin acessibility method",
+ "value": "BAO:0040027 | chromatin acessibility method $5fab6675-9d36-4524-a704-3674e4c447fb",
+ "is_enabled": true,
+ "id": "0040027",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040030 | transcription factor occupancy",
+ "title": "transcription factor occupancy",
+ "value": "BAO:0040030 | transcription factor occupancy $e99dae65-199c-419c-8289-b66ee984b450",
+ "is_enabled": true,
+ "id": "0040030",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040029 | epigenetic modification detection method",
+ "title": "epigenetic modification detection method",
+ "value": "BAO:0040029 | epigenetic modification detection method $129a3d82-dc00-470a-a014-987b1b985dae",
+ "is_enabled": true,
+ "id": "0040029",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040011 | molecular abundance method",
+ "title": "molecular abundance method",
+ "value": "BAO:0040011 | molecular abundance method $55bd6874-d92e-4c28-b398-2488ff818f83",
+ "is_enabled": true,
+ "id": "0040011",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040028 | metabolite abundance method",
+ "title": "metabolite abundance method",
+ "value": "BAO:0040028 | metabolite abundance method $a0889ab4-ec71-410c-881d-6e42f1cc5350",
+ "is_enabled": true,
+ "id": "0040028",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040012 | second messenger abundance",
+ "title": "second messenger abundance",
+ "value": "BAO:0040012 | second messenger abundance $d55bb828-7a98-4608-97dc-7e471e8b2bd0",
+ "is_enabled": true,
+ "id": "0040012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040013 | lipid abundance method",
+ "title": "lipid abundance method",
+ "value": "BAO:0040013 | lipid abundance method $6319d8f1-13da-4ebb-acae-0c5f7f20d7a0",
+ "is_enabled": true,
+ "id": "0040013",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040014 | protein abundance method",
+ "title": "protein abundance method",
+ "value": "BAO:0040014 | protein abundance method $2f8f8b06-311a-4027-8609-b281787cd26d",
+ "is_enabled": true,
+ "id": "0040014",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "ERO:0002176 | isobaric labeling@en",
+ "title": "isobaric labeling@en",
+ "value": "ERO:0002176 | isobaric labeling@en $1af65f8b-ec80-4f11-9c3e-e28572b8a604",
+ "is_enabled": true,
+ "id": "0002176",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040017 | DNA or RNA abundance method",
+ "title": "DNA or RNA abundance method",
+ "value": "BAO:0040017 | DNA or RNA abundance method $298ec88e-cc17-4b8b-85a5-6d4ec5b2a121",
+ "is_enabled": true,
+ "id": "0040017",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0040018 | small molecule abundance method",
+ "title": "small molecule abundance method",
+ "value": "BAO:0040018 | small molecule abundance method $fb7da162-d567-44ca-9050-725a12298a88",
+ "is_enabled": true,
+ "id": "0040018",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003118 | instrument",
+ "title": "instrument",
+ "value": "BAO:0003118 | instrument $beb66a1f-8b36-4fcf-bb3b-a553b60d536b",
+ "is_enabled": true,
+ "id": "0003118",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000697 | detection instrument",
+ "title": "detection instrument",
+ "value": "BAO:0000697 | detection instrument $9cd968c8-5ae5-488d-aa3d-3d69fcff76bf",
+ "is_enabled": true,
+ "id": "0000697",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002722 | CyAn Flow Cytometer",
+ "title": "CyAn Flow Cytometer",
+ "value": "BAO:0002722 | CyAn Flow Cytometer $b0c0e89f-dea9-423b-a08e-5e20abf6d494",
+ "is_enabled": true,
+ "id": "0002722",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002723 | MSD SECTOR instrument",
+ "title": "MSD SECTOR instrument",
+ "value": "BAO:0002723 | MSD SECTOR instrument $49b0a783-19b0-44ae-ab2d-8f0b066c89ce",
+ "is_enabled": true,
+ "id": "0002723",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002724 | AMINCO-Bowman Series 2 Luminescence Spectrometer",
+ "title": "AMINCO-Bowman Series 2 Luminescence Spectrometer",
+ "value": "BAO:0002724 | AMINCO-Bowman Series 2 Luminescence Spectrometer $91bd9046-8bb3-470d-8651-546723d3eae5",
+ "is_enabled": true,
+ "id": "0002724",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002719 | Avance III",
+ "title": "Avance III",
+ "value": "BAO:0002719 | Avance III $2b337388-271e-4b05-8877-6383826c3c40",
+ "is_enabled": true,
+ "id": "0002719",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002733 | HPLC System",
+ "title": "HPLC System",
+ "value": "BAO:0002733 | HPLC System $295ea2bc-1072-434d-8e1a-edf37f41a660",
+ "is_enabled": true,
+ "id": "0002733",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002935 | automated cytometer",
+ "title": "automated cytometer",
+ "value": "BAO:0002935 | automated cytometer $c609d9f0-d04e-4008-b1cc-3b6e10d7613f",
+ "is_enabled": true,
+ "id": "0002935",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002936 | Hypercyt",
+ "title": "Hypercyt",
+ "value": "BAO:0002936 | Hypercyt $3f7d33ee-42e3-47e0-a6b9-a3cbef81e791",
+ "is_enabled": true,
+ "id": "0002936",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002937 | imaging cytometer",
+ "title": "imaging cytometer",
+ "value": "BAO:0002937 | imaging cytometer $d5021529-9e6a-4f50-b958-c2af46f3e4d8",
+ "is_enabled": true,
+ "id": "0002937",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002949 | iCyte Automated Imaging Cytometer",
+ "title": "iCyte Automated Imaging Cytometer",
+ "value": "BAO:0002949 | iCyte Automated Imaging Cytometer $20ca4b87-f63a-4a17-987c-e5e7a7abbc55",
+ "is_enabled": true,
+ "id": "0002949",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002947 | Cell Voyager 7000",
+ "title": "Cell Voyager 7000",
+ "value": "BAO:0002947 | Cell Voyager 7000 $cdc31fe5-d470-485d-92d4-87b261cf4b58",
+ "is_enabled": true,
+ "id": "0002947",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002948 | FlowSight",
+ "title": "FlowSight",
+ "value": "BAO:0002948 | FlowSight $1c62471a-2fad-4a39-ad67-d0e1ea450409",
+ "is_enabled": true,
+ "id": "0002948",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002941 | BD Pathway 435",
+ "title": "BD Pathway 435",
+ "value": "BAO:0002941 | BD Pathway 435 $82209916-7725-4329-8874-5b03a3ab31cb",
+ "is_enabled": true,
+ "id": "0002941",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002942 | BD Pathway 855",
+ "title": "BD Pathway 855",
+ "value": "BAO:0002942 | BD Pathway 855 $2dc94396-8d4e-4787-bd29-e2ad16ed1d44",
+ "is_enabled": true,
+ "id": "0002942",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002940 | ArrayScan VTI HCS Reader",
+ "title": "ArrayScan VTI HCS Reader",
+ "value": "BAO:0002940 | ArrayScan VTI HCS Reader $a5606b79-bb40-44b2-beb0-ad65283b7092",
+ "is_enabled": true,
+ "id": "0002940",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002945 | Cell Voyager 1000",
+ "title": "Cell Voyager 1000",
+ "value": "BAO:0002945 | Cell Voyager 1000 $1da1c39c-c486-4a7f-9209-ec648967df71",
+ "is_enabled": true,
+ "id": "0002945",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002946 | Cell Voyager 6000",
+ "title": "Cell Voyager 6000",
+ "value": "BAO:0002946 | Cell Voyager 6000 $e271be60-2f0f-4daa-bfd5-35f92617cd57",
+ "is_enabled": true,
+ "id": "0002946",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002943 | BioFlux 1000",
+ "title": "BioFlux 1000",
+ "value": "BAO:0002943 | BioFlux 1000 $2b13f0ba-7c64-4ead-bba1-5d2fd1f6f131",
+ "is_enabled": true,
+ "id": "0002943",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002944 | Celigo S Imaging Cell Cytometer",
+ "title": "Celigo S Imaging Cell Cytometer",
+ "value": "BAO:0002944 | Celigo S Imaging Cell Cytometer $ac355fc3-a56a-48c6-91b6-32f06e13429d",
+ "is_enabled": true,
+ "id": "0002944",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002938 | 3i Marianas",
+ "title": "3i Marianas",
+ "value": "BAO:0002938 | 3i Marianas $d8fe5b0b-38d0-4760-9a3c-4abb8aeb049b",
+ "is_enabled": true,
+ "id": "0002938",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002939 | Acumen",
+ "title": "Acumen",
+ "value": "BAO:0002939 | Acumen $685f7bd4-f729-4258-9ba8-0bcc357510f4",
+ "is_enabled": true,
+ "id": "0002939",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150082 | IN Cell Analyzer 1000",
+ "title": "IN Cell Analyzer 1000",
+ "value": "BAO:0150082 | IN Cell Analyzer 1000 $81df4337-61cd-4938-9fbd-b2bb27d1a292",
+ "is_enabled": true,
+ "id": "0150082",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002958 | Tali Image Cytometer",
+ "title": "Tali Image Cytometer",
+ "value": "BAO:0002958 | Tali Image Cytometer $a415d8f1-c5e3-4935-8a12-175a58f337ca",
+ "is_enabled": true,
+ "id": "0002958",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002952 | ImageXpress Ultra",
+ "title": "ImageXpress Ultra",
+ "value": "BAO:0002952 | ImageXpress Ultra $97c11437-8c4d-4b5b-a818-8a0844b5d0a1",
+ "is_enabled": true,
+ "id": "0002952",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002953 | ImageXpress Velos Laser Scanning Cytometer",
+ "title": "ImageXpress Velos Laser Scanning Cytometer",
+ "value": "BAO:0002953 | ImageXpress Velos Laser Scanning Cytometer $42c4d71d-1bf9-467f-9782-c997d8844c02",
+ "is_enabled": true,
+ "id": "0002953",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002950 | ImageStreamX Mark II Imaging Flow Cytometer",
+ "title": "ImageStreamX Mark II Imaging Flow Cytometer",
+ "value": "BAO:0002950 | ImageStreamX Mark II Imaging Flow Cytometer $c93f27c5-79fb-47ef-8f1c-b51342bb8352",
+ "is_enabled": true,
+ "id": "0002950",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002951 | ImageXpress Micro",
+ "title": "ImageXpress Micro",
+ "value": "BAO:0002951 | ImageXpress Micro $4d44e998-dc92-4b81-85e1-5aca051c5006",
+ "is_enabled": true,
+ "id": "0002951",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002956 | Opera",
+ "title": "Opera",
+ "value": "BAO:0002956 | Opera $5749da92-1e8d-4d36-adfc-0beb5cecb778",
+ "is_enabled": true,
+ "id": "0002956",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002957 | Operetta",
+ "title": "Operetta",
+ "value": "BAO:0002957 | Operetta $e9dfb785-c86e-4b8f-9a29-9ea89b1a4550",
+ "is_enabled": true,
+ "id": "0002957",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002954 | IN Cell Analyzer 2000",
+ "title": "IN Cell Analyzer 2000",
+ "value": "BAO:0002954 | IN Cell Analyzer 2000 $34303fe8-19a3-4a73-979f-55f054537b9b",
+ "is_enabled": true,
+ "id": "0002954",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002955 | IN Cell Analyzer 6000",
+ "title": "IN Cell Analyzer 6000",
+ "value": "BAO:0002955 | IN Cell Analyzer 6000 $0e33d367-3815-4098-b8ea-ba0ca01ef639",
+ "is_enabled": true,
+ "id": "0002955",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150003 | CellInsight NXT HCS Platform",
+ "title": "CellInsight NXT HCS Platform",
+ "value": "BAO:0150003 | CellInsight NXT HCS Platform $95e57492-e03b-4b6c-afaf-a1d13b238672",
+ "is_enabled": true,
+ "id": "0150003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150002 | CellWoRx HCS Reader",
+ "title": "CellWoRx HCS Reader",
+ "value": "BAO:0150002 | CellWoRx HCS Reader $3fb5e9da-1e1d-4033-b758-eef1c8380dce",
+ "is_enabled": true,
+ "id": "0150002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150005 | ArrayScan 3.1 HCS Reader",
+ "title": "ArrayScan 3.1 HCS Reader",
+ "value": "BAO:0150005 | ArrayScan 3.1 HCS Reader $55a12ee9-98c0-4b93-b363-e2ff8b62e706",
+ "is_enabled": true,
+ "id": "0150005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150004 | ArrayScan II HCS Reader",
+ "title": "ArrayScan II HCS Reader",
+ "value": "BAO:0150004 | ArrayScan II HCS Reader $a1de1405-9f6b-45e9-9c75-6f6d795b0a6d",
+ "is_enabled": true,
+ "id": "0150004",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150001 | IN Cell Analyzer 3000",
+ "title": "IN Cell Analyzer 3000",
+ "value": "BAO:0150001 | IN Cell Analyzer 3000 $8c12a2e6-1d93-4f8f-a473-80d745eec24d",
+ "is_enabled": true,
+ "id": "0150001",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150000 | IN Cell Analyzer 2200",
+ "title": "IN Cell Analyzer 2200",
+ "value": "BAO:0150000 | IN Cell Analyzer 2200 $56fefa21-f1f2-4376-bd2b-7dc1e9c821a2",
+ "is_enabled": true,
+ "id": "0150000",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150007 | KineticScan HCS Reader",
+ "title": "KineticScan HCS Reader",
+ "value": "BAO:0150007 | KineticScan HCS Reader $d28683c1-daff-43f3-9e5b-1f731a61f571",
+ "is_enabled": true,
+ "id": "0150007",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150006 | ArrayScan 4.0 HCS Reader",
+ "title": "ArrayScan 4.0 HCS Reader",
+ "value": "BAO:0150006 | ArrayScan 4.0 HCS Reader $63f29646-9a25-45b5-a687-d9b85e3ba32f",
+ "is_enabled": true,
+ "id": "0150006",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150075 | iMIC platform/ Polychrome V imaging system, (TILL Photonics/ FEI Munic GmbH)",
+ "title": "iMIC platform/ Polychrome V imaging system, (TILL Photonics/ FEI Munic GmbH)",
+ "value": "BAO:0150075 | iMIC platform/ Polychrome V imaging system, (TILL Photonics/ FEI Munic GmbH) $a5612d44-77ed-4158-98da-3dbd74fa2746",
+ "is_enabled": true,
+ "id": "0150075",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002569 | LabChip EZ Reader",
+ "title": "LabChip EZ Reader",
+ "value": "BAO:0002569 | LabChip EZ Reader $85485cef-69e5-4480-ac8a-126ab1a45a13",
+ "is_enabled": true,
+ "id": "0002569",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002556 | ICRM12000 atomic absorption spectrometer",
+ "title": "ICRM12000 atomic absorption spectrometer",
+ "value": "BAO:0002556 | ICRM12000 atomic absorption spectrometer $a21d45b5-e829-4810-9828-ae6a87bb59e9",
+ "is_enabled": true,
+ "id": "0002556",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002557 | Sector imager 6000",
+ "title": "Sector imager 6000",
+ "value": "BAO:0002557 | Sector imager 6000 $86b756dd-839d-4771-a067-58e2afc3caa5",
+ "is_enabled": true,
+ "id": "0002557",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002578 | Tecan Ultra",
+ "title": "Tecan Ultra",
+ "value": "BAO:0002578 | Tecan Ultra $860df894-f12b-4deb-9cc0-0f27f37c91e4",
+ "is_enabled": true,
+ "id": "0002578",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002576 | IonWorks Quattro",
+ "title": "IonWorks Quattro",
+ "value": "BAO:0002576 | IonWorks Quattro $49e4ba5c-56f4-435d-8964-5e38856aad65",
+ "is_enabled": true,
+ "id": "0002576",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002577 | RapidFire Mass Spec",
+ "title": "RapidFire Mass Spec",
+ "value": "BAO:0002577 | RapidFire Mass Spec $a09a1c92-0244-42b1-b053-b269832837e4",
+ "is_enabled": true,
+ "id": "0002577",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002570 | Cellomics ArrayScan",
+ "title": "Cellomics ArrayScan",
+ "value": "BAO:0002570 | Cellomics ArrayScan $d6cd139c-8002-4e91-a73d-cdde6f2b755e",
+ "is_enabled": true,
+ "id": "0002570",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002571 | IN Cell Analyzer",
+ "title": "IN Cell Analyzer",
+ "value": "BAO:0002571 | IN Cell Analyzer $cfdfd5b3-f918-4460-9236-6c81df3ddc75",
+ "is_enabled": true,
+ "id": "0002571",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002574 | AlphaQuest reader",
+ "title": "AlphaQuest reader",
+ "value": "BAO:0002574 | AlphaQuest reader $68808f11-76e8-495b-b8bf-2fbbd2e80d51",
+ "is_enabled": true,
+ "id": "0002574",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002575 | LJL reader",
+ "title": "LJL reader",
+ "value": "BAO:0002575 | LJL reader $37151668-ef45-4781-8511-9f6fb4f2066c",
+ "is_enabled": true,
+ "id": "0002575",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002572 | Epic reader",
+ "title": "Epic reader",
+ "value": "BAO:0002572 | Epic reader $515d3b77-e62d-44dc-bb3c-9ed9c46a64d1",
+ "is_enabled": true,
+ "id": "0002572",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002573 | Applied biosystems 8200",
+ "title": "Applied biosystems 8200",
+ "value": "BAO:0002573 | Applied biosystems 8200 $a72e1ad5-e4db-4343-8049-86d4579e660e",
+ "is_enabled": true,
+ "id": "0002573",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000703 | HTFC Screening System",
+ "title": "HTFC Screening System",
+ "value": "BAO:0000703 | HTFC Screening System $50808834-65fa-4dcc-9db9-73584a520018",
+ "is_enabled": true,
+ "id": "0000703",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000706 | SpectraMax M5 Multi-Mode Microplate Reader",
+ "title": "SpectraMax M5 Multi-Mode Microplate Reader",
+ "value": "BAO:0000706 | SpectraMax M5 Multi-Mode Microplate Reader $6e82bfb7-7e95-489c-a3a0-6e6997ed7bf3",
+ "is_enabled": true,
+ "id": "0000706",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000705 | PHERAstar Plus",
+ "title": "PHERAstar Plus",
+ "value": "BAO:0000705 | PHERAstar Plus $12385951-bf13-4e1b-9428-8cb5c0948f3e",
+ "is_enabled": true,
+ "id": "0000705",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000708 | VP-ITC Isothermal Titration Calorimeter",
+ "title": "VP-ITC Isothermal Titration Calorimeter",
+ "value": "BAO:0000708 | VP-ITC Isothermal Titration Calorimeter $ec8e767e-f0cc-48e7-8cd2-83d799564e2e",
+ "is_enabled": true,
+ "id": "0000708",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000707 | VICTOR X2 Multilabel Plate Reader",
+ "title": "VICTOR X2 Multilabel Plate Reader",
+ "value": "BAO:0000707 | VICTOR X2 Multilabel Plate Reader $bb8c2215-a89f-497e-a9d7-5e487d4252fb",
+ "is_enabled": true,
+ "id": "0000707",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000700 | ELx808 Absorbance Microplate Reader",
+ "title": "ELx808 Absorbance Microplate Reader",
+ "value": "BAO:0000700 | ELx808 Absorbance Microplate Reader $1f03f70e-6709-44c1-80b3-674c0a6e7e7a",
+ "is_enabled": true,
+ "id": "0000700",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000702 | FLx800 Fluorescence Microplate Reader",
+ "title": "FLx800 Fluorescence Microplate Reader",
+ "value": "BAO:0000702 | FLx800 Fluorescence Microplate Reader $f8fe8925-69f0-4e48-8cd7-9e8e4050a41a",
+ "is_enabled": true,
+ "id": "0000702",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000701 | EnVision Multilabel Reader",
+ "title": "EnVision Multilabel Reader",
+ "value": "BAO:0000701 | EnVision Multilabel Reader $7913aeef-8168-48c0-be4a-7dfe5cb22cdf",
+ "is_enabled": true,
+ "id": "0000701",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000726 | Packard Fusion Microplate Reader",
+ "title": "Packard Fusion Microplate Reader",
+ "value": "BAO:0000726 | Packard Fusion Microplate Reader $fce16acd-c8c8-4f2c-a646-dd838bc830f7",
+ "is_enabled": true,
+ "id": "0000726",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000728 | Monolight 2010 Luminometer",
+ "title": "Monolight 2010 Luminometer",
+ "value": "BAO:0000728 | Monolight 2010 Luminometer $68c866f4-9803-4090-a74f-c7b53978a10a",
+ "is_enabled": true,
+ "id": "0000728",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000727 | Infinite PF200",
+ "title": "Infinite PF200",
+ "value": "BAO:0000727 | Infinite PF200 $a214ed0a-3291-4b1e-850a-1c51613e5197",
+ "is_enabled": true,
+ "id": "0000727",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000698 | 8453 UV-Visible Spectrophotometer",
+ "title": "8453 UV-Visible Spectrophotometer",
+ "value": "BAO:0000698 | 8453 UV-Visible Spectrophotometer $f39e341a-65ea-44e5-8859-9f5866fd9de2",
+ "is_enabled": true,
+ "id": "0000698",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150093 | NGS Instrument",
+ "title": "NGS Instrument",
+ "value": "BAO:0150093 | NGS Instrument $00c2c072-5f9c-4e52-bade-7d6ce52bf501",
+ "is_enabled": true,
+ "id": "0150093",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000699 | Analyst HT",
+ "title": "Analyst HT",
+ "value": "BAO:0000699 | Analyst HT $61806c7b-c6ef-45e3-a13d-71e8d4e8344b",
+ "is_enabled": true,
+ "id": "0000699",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150094 | Odyssey Plate Reader",
+ "title": "Odyssey Plate Reader",
+ "value": "BAO:0150094 | Odyssey Plate Reader $13e781a5-458b-4428-b045-fa4708a89015",
+ "is_enabled": true,
+ "id": "0150094",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000692 | Infinite F200",
+ "title": "Infinite F200",
+ "value": "BAO:0000692 | Infinite F200 $87e8a979-e622-4bde-a94d-5599d40e40c8",
+ "is_enabled": true,
+ "id": "0000692",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000691 | ViewLux ultraHTS Microplate Imager",
+ "title": "ViewLux ultraHTS Microplate Imager",
+ "value": "BAO:0000691 | ViewLux ultraHTS Microplate Imager $2b3622f2-0ffe-4ea5-bf08-5deaa7afabe1",
+ "is_enabled": true,
+ "id": "0000691",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150098 | IN Cell Analyzer 2500",
+ "title": "IN Cell Analyzer 2500",
+ "value": "BAO:0150098 | IN Cell Analyzer 2500 $b7c406e2-c3a4-467b-846c-517bb5151c0c",
+ "is_enabled": true,
+ "id": "0150098",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150097 | FlexStation III Microplate Reader",
+ "title": "FlexStation III Microplate Reader",
+ "value": "BAO:0150097 | FlexStation III Microplate Reader $800204a5-7382-4209-b46e-a8ac2b910aa9",
+ "is_enabled": true,
+ "id": "0150097",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150099 | IN Cell Analyzer 6500",
+ "title": "IN Cell Analyzer 6500",
+ "value": "BAO:0150099 | IN Cell Analyzer 6500 $ba5201ef-7f3f-40b5-bf90-afe9f2e28703",
+ "is_enabled": true,
+ "id": "0150099",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150096 | Luminex 200 Flow Cytometer",
+ "title": "Luminex 200 Flow Cytometer",
+ "value": "BAO:0150096 | Luminex 200 Flow Cytometer $ed067749-fe2a-43cc-92ef-9a6adb595eeb",
+ "is_enabled": true,
+ "id": "0150096",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150095 | Luminex 200 Flow Cytometer",
+ "title": "Luminex 200 Flow Cytometer",
+ "value": "BAO:0150095 | Luminex 200 Flow Cytometer $9a36352e-3d23-4842-b566-e5fae98bf849",
+ "is_enabled": true,
+ "id": "0150095",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150090 | Storm PhosphorImager (Molecular Dynamics/ GE)",
+ "title": "Storm PhosphorImager (Molecular Dynamics/ GE)",
+ "value": "BAO:0150090 | Storm PhosphorImager (Molecular Dynamics/ GE) $155a08cd-6f6e-48a1-9736-fb0552cd7eb8",
+ "is_enabled": true,
+ "id": "0150090",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150092 | Velos-MS",
+ "title": "Velos-MS",
+ "value": "BAO:0150092 | Velos-MS $6332b964-392a-4dc1-a3ce-4489402bfb38",
+ "is_enabled": true,
+ "id": "0150092",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150091 | Varioskan LUX multimode microplate reader (ThermoFisher)",
+ "title": "Varioskan LUX multimode microplate reader (ThermoFisher)",
+ "value": "BAO:0150091 | Varioskan LUX multimode microplate reader (ThermoFisher) $9c0eb0b2-0138-429e-bcec-e66e2ff7f5d7",
+ "is_enabled": true,
+ "id": "0150091",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150087 | FACScalibur flow cytometer (BD Biosciences)",
+ "title": "FACScalibur flow cytometer (BD Biosciences)",
+ "value": "BAO:0150087 | FACScalibur flow cytometer (BD Biosciences) $186527b5-3f8a-4eae-b816-ddda838def84",
+ "is_enabled": true,
+ "id": "0150087",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150086 | ChemiDoc XRS Imaging System (BioRad)",
+ "title": "ChemiDoc XRS Imaging System (BioRad)",
+ "value": "BAO:0150086 | ChemiDoc XRS Imaging System (BioRad) $e3bfdb53-8bde-48d0-990f-d028ec53dfa3",
+ "is_enabled": true,
+ "id": "0150086",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150089 | Pico patch clamp amplifier (Tecella)",
+ "title": "Pico patch clamp amplifier (Tecella)",
+ "value": "BAO:0150089 | Pico patch clamp amplifier (Tecella) $a27a10e2-3927-4f6a-95b1-79a03f591325",
+ "is_enabled": true,
+ "id": "0150089",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150088 | FLUOstar Omega microplate reader (BMG Labtech)",
+ "title": "FLUOstar Omega microplate reader (BMG Labtech)",
+ "value": "BAO:0150088 | FLUOstar Omega microplate reader (BMG Labtech) $e304660d-52dd-48ef-9644-6a3fd1aa214e",
+ "is_enabled": true,
+ "id": "0150088",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150083 | xCELLigence RTCA DP cellular impedance instrument (Acea Biosciences)",
+ "title": "xCELLigence RTCA DP cellular impedance instrument (Acea Biosciences)",
+ "value": "BAO:0150083 | xCELLigence RTCA DP cellular impedance instrument (Acea Biosciences) $fa5fc8bf-3d54-4540-ab4a-2123d68c3cca",
+ "is_enabled": true,
+ "id": "0150083",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150085 | Biacore 3000 SPR System (GE Healthcare)",
+ "title": "Biacore 3000 SPR System (GE Healthcare)",
+ "value": "BAO:0150085 | Biacore 3000 SPR System (GE Healthcare) $d44a5670-0384-45d5-bebb-070a92e70c86",
+ "is_enabled": true,
+ "id": "0150085",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150084 | BD FACSAria flow cytometer (BD Biosciences)",
+ "title": "BD FACSAria flow cytometer (BD Biosciences)",
+ "value": "BAO:0150084 | BD FACSAria flow cytometer (BD Biosciences) $f782ccea-6a4c-4501-85cd-92e8108819e4",
+ "is_enabled": true,
+ "id": "0150084",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150081 | Typhoon Trio variable-mode imager (Amersham/ GE LifeSciences)",
+ "title": "Typhoon Trio variable-mode imager (Amersham/ GE LifeSciences)",
+ "value": "BAO:0150081 | Typhoon Trio variable-mode imager (Amersham/ GE LifeSciences) $3b018076-bc8e-4589-b98e-3a72dc43881f",
+ "is_enabled": true,
+ "id": "0150081",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150080 | TSQ Quantum Triple Quadrupole LC-MS (Thermo Scientific)",
+ "title": "TSQ Quantum Triple Quadrupole LC-MS (Thermo Scientific)",
+ "value": "BAO:0150080 | TSQ Quantum Triple Quadrupole LC-MS (Thermo Scientific) $8c205fa2-a8ec-48af-b0ce-1259e22f2385",
+ "is_enabled": true,
+ "id": "0150080",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150008 | microscope",
+ "title": "microscope",
+ "value": "BAO:0150008 | microscope $0ccf9fd9-6adb-4836-95d9-7030c32d1419",
+ "is_enabled": true,
+ "id": "0150008",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150010 | confocal microscope",
+ "title": "confocal microscope",
+ "value": "BAO:0150010 | confocal microscope $5ff1a1c2-a01d-4b2e-bc4e-bf74c5a62b34",
+ "is_enabled": true,
+ "id": "0150010",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150012 | spinning-disk confocal microscope",
+ "title": "spinning-disk confocal microscope",
+ "value": "BAO:0150012 | spinning-disk confocal microscope $f55cec1d-d0eb-4fc3-9181-cebb8059465b",
+ "is_enabled": true,
+ "id": "0150012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150011 | laser scanning confocal microscope",
+ "title": "laser scanning confocal microscope",
+ "value": "BAO:0150011 | laser scanning confocal microscope $04f0cc50-e8f5-4d7f-9f72-6ed17660b632",
+ "is_enabled": true,
+ "id": "0150011",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150009 | optical microscope",
+ "title": "optical microscope",
+ "value": "BAO:0150009 | optical microscope $18bfc3ca-d43b-4dd9-9384-1ac79a6f12f3",
+ "is_enabled": true,
+ "id": "0150009",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150014 | scanning force microscope",
+ "title": "scanning force microscope",
+ "value": "BAO:0150014 | scanning force microscope $3686b435-293a-4a09-880b-5887da91b502",
+ "is_enabled": true,
+ "id": "0150014",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150013 | laser capture microdissection microscope",
+ "title": "laser capture microdissection microscope",
+ "value": "BAO:0150013 | laser capture microdissection microscope $ae30595d-62ce-4dca-a972-4782fb462831",
+ "is_enabled": true,
+ "id": "0150013",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150015 | wide-field microscope",
+ "title": "wide-field microscope",
+ "value": "BAO:0150015 | wide-field microscope $3ec8221a-4794-4876-ae9b-6883d9d8ce7b",
+ "is_enabled": true,
+ "id": "0150015",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150058 | Countess automatic cell counter",
+ "title": "Countess automatic cell counter",
+ "value": "BAO:0150058 | Countess automatic cell counter $d561f80d-f799-45c9-9664-cff2c8e8684e",
+ "is_enabled": true,
+ "id": "0150058",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150057 | BMG PHERAstar FSX plate reader (BMG Labtech, Cary NC)",
+ "title": "BMG PHERAstar FSX plate reader (BMG Labtech, Cary NC)",
+ "value": "BAO:0150057 | BMG PHERAstar FSX plate reader (BMG Labtech, Cary NC) $6aa1e429-ebce-4de1-8f1a-bf837becad66",
+ "is_enabled": true,
+ "id": "0150057",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150059 | FacSCAN flow cytometer",
+ "title": "FacSCAN flow cytometer",
+ "value": "BAO:0150059 | FacSCAN flow cytometer $20cb897a-32c8-4781-85b8-c17c1be7f9b6",
+ "is_enabled": true,
+ "id": "0150059",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150054 | Axopatch 200B amplifier (Molecular Devices)",
+ "title": "Axopatch 200B amplifier (Molecular Devices)",
+ "value": "BAO:0150054 | Axopatch 200B amplifier (Molecular Devices) $acb46a27-c3f4-48a4-8fce-b813cce18fcb",
+ "is_enabled": true,
+ "id": "0150054",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150053 | Analyst AD (Molecular Devices)",
+ "title": "Analyst AD (Molecular Devices)",
+ "value": "BAO:0150053 | Analyst AD (Molecular Devices) $30dabeb9-b4fb-4700-8638-4e2c97d5f579",
+ "is_enabled": true,
+ "id": "0150053",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150056 | Synergy 2 Multi-Mode Reader (BioTek)",
+ "title": "Synergy 2 Multi-Mode Reader (BioTek)",
+ "value": "BAO:0150056 | Synergy 2 Multi-Mode Reader (BioTek) $e5432bf0-1b4f-4ca1-bd0b-66ec1369f107",
+ "is_enabled": true,
+ "id": "0150056",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150055 | Becton Dickinson (BD) LSRII FACS",
+ "title": "Becton Dickinson (BD) LSRII FACS",
+ "value": "BAO:0150055 | Becton Dickinson (BD) LSRII FACS $7a3a75e8-e41b-428b-b5ac-84dda2871d02",
+ "is_enabled": true,
+ "id": "0150055",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150052 | IonWorks automated electrophysiology system (Molecular Devices)",
+ "title": "IonWorks automated electrophysiology system (Molecular Devices)",
+ "value": "BAO:0150052 | IonWorks automated electrophysiology system (Molecular Devices) $62a86130-08bd-49cb-bd19-aa4564d0ebcb",
+ "is_enabled": true,
+ "id": "0150052",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150079 | SpectraFluor Plus Microplate Reader (Tecan)",
+ "title": "SpectraFluor Plus Microplate Reader (Tecan)",
+ "value": "BAO:0150079 | SpectraFluor Plus Microplate Reader (Tecan) $20fad898-d424-4315-93b5-dedeabd9f3a4",
+ "is_enabled": true,
+ "id": "0150079",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150076 | Infinte M200 plate reader (Tecan)",
+ "title": "Infinte M200 plate reader (Tecan)",
+ "value": "BAO:0150076 | Infinte M200 plate reader (Tecan) $f4ac902d-7da3-4b65-a490-3aa9e3dc353d",
+ "is_enabled": true,
+ "id": "0150076",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150078 | Wallac 1420 (Victor2) Microplate reader (PerkinElmer)",
+ "title": "Wallac 1420 (Victor2) Microplate reader (PerkinElmer)",
+ "value": "BAO:0150078 | Wallac 1420 (Victor2) Microplate reader (PerkinElmer) $ae701c11-673b-4b01-aa2c-e9d3350127b1",
+ "is_enabled": true,
+ "id": "0150078",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150077 | Multiskan EX plate reader (Thermo Scientific)",
+ "title": "Multiskan EX plate reader (Thermo Scientific)",
+ "value": "BAO:0150077 | Multiskan EX plate reader (Thermo Scientific) $e74337fe-5894-40cc-8d69-b3200c12e830",
+ "is_enabled": true,
+ "id": "0150077",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150072 | SpectraMax Gemini XS microplate fluorometer (Molecular Devices)",
+ "title": "SpectraMax Gemini XS microplate fluorometer (Molecular Devices)",
+ "value": "BAO:0150072 | SpectraMax Gemini XS microplate fluorometer (Molecular Devices) $3c2cb1b7-0fc6-4af7-a375-8c20e8cf108d",
+ "is_enabled": true,
+ "id": "0150072",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150071 | micro-Quant Plate Reader (BioTek)",
+ "title": "micro-Quant Plate Reader (BioTek)",
+ "value": "BAO:0150071 | micro-Quant Plate Reader (BioTek) $74dbd3d9-32c3-4290-947d-a035684a7502",
+ "is_enabled": true,
+ "id": "0150071",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150074 | Fluoroskan Ascent FL Microplate Fluorometer and Luminometer (ThermoFisher)",
+ "title": "Fluoroskan Ascent FL Microplate Fluorometer and Luminometer (ThermoFisher)",
+ "value": "BAO:0150074 | Fluoroskan Ascent FL Microplate Fluorometer and Luminometer (ThermoFisher) $fde0ce41-03a6-4317-bc16-6ec249e80e8a",
+ "is_enabled": true,
+ "id": "0150074",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150073 | Typhoon FLA 9000 laser scanner (GE Healthcare)",
+ "title": "Typhoon FLA 9000 laser scanner (GE Healthcare)",
+ "value": "BAO:0150073 | Typhoon FLA 9000 laser scanner (GE Healthcare) $7b83fb0f-80ac-405c-b99d-be6389c0f01c",
+ "is_enabled": true,
+ "id": "0150073",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150070 | VE-2 whole-cell patch clamp amplifier (Alembic Instruments)",
+ "title": "VE-2 whole-cell patch clamp amplifier (Alembic Instruments)",
+ "value": "BAO:0150070 | VE-2 whole-cell patch clamp amplifier (Alembic Instruments) $6dcb8b0d-5acd-439f-adbe-9a4031f53765",
+ "is_enabled": true,
+ "id": "0150070",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150069 | Agilent 1100 series LC-MSD SL",
+ "title": "Agilent 1100 series LC-MSD SL",
+ "value": "BAO:0150069 | Agilent 1100 series LC-MSD SL $f57c005b-b5c4-4ab7-8f59-a74232adde0e",
+ "is_enabled": true,
+ "id": "0150069",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150068 | Appled Biosystems Real-Time PCR System (ThermoFisher)",
+ "title": "Appled Biosystems Real-Time PCR System (ThermoFisher)",
+ "value": "BAO:0150068 | Appled Biosystems Real-Time PCR System (ThermoFisher) $a6f80049-d56c-417e-b9c6-f69eec589643",
+ "is_enabled": true,
+ "id": "0150068",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150065 | Synergy HT Multi-Mode Reader (BioTek)",
+ "title": "Synergy HT Multi-Mode Reader (BioTek)",
+ "value": "BAO:0150065 | Synergy HT Multi-Mode Reader (BioTek) $3742638b-2ad2-4272-a8cd-e58e429ccde6",
+ "is_enabled": true,
+ "id": "0150065",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150064 | Mx3005P RT-PCR instrument (Agilent Technologies)",
+ "title": "Mx3005P RT-PCR instrument (Agilent Technologies)",
+ "value": "BAO:0150064 | Mx3005P RT-PCR instrument (Agilent Technologies) $a2cf92c4-3473-4b89-b863-7b7f53338afb",
+ "is_enabled": true,
+ "id": "0150064",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150067 | LTQ-Orbitrap Velos (Thermo Scientific)",
+ "title": "LTQ-Orbitrap Velos (Thermo Scientific)",
+ "value": "BAO:0150067 | LTQ-Orbitrap Velos (Thermo Scientific) $91293e91-ff07-472c-a047-905c125ec5ab",
+ "is_enabled": true,
+ "id": "0150067",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150066 | GloMax luminometer (Promega)",
+ "title": "GloMax luminometer (Promega)",
+ "value": "BAO:0150066 | GloMax luminometer (Promega) $e2a1c70f-ab42-42ea-a3e9-f53615d14192",
+ "is_enabled": true,
+ "id": "0150066",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150061 | Molecular Devices SpectraMax Plate reader",
+ "title": "Molecular Devices SpectraMax Plate reader",
+ "value": "BAO:0150061 | Molecular Devices SpectraMax Plate reader $2b583b9b-cafd-4d18-81f4-ca88aa1b444f",
+ "is_enabled": true,
+ "id": "0150061",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150060 | Molecular Devices Vmax plate reader",
+ "title": "Molecular Devices Vmax plate reader",
+ "value": "BAO:0150060 | Molecular Devices Vmax plate reader $ea25c899-ad98-4c79-9f09-ec49a8b8e504",
+ "is_enabled": true,
+ "id": "0150060",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150063 | LightCycler 480 Real-Time PCR detection instrument",
+ "title": "LightCycler 480 Real-Time PCR detection instrument",
+ "value": "BAO:0150063 | LightCycler 480 Real-Time PCR detection instrument $38a5dc67-aeed-4e41-8b0a-0c6be8b1c688",
+ "is_enabled": true,
+ "id": "0150063",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150062 | Qpatch automated patch clamp system (Biolin)",
+ "title": "Qpatch automated patch clamp system (Biolin)",
+ "value": "BAO:0150062 | Qpatch automated patch clamp system (Biolin) $9ed68ce3-181a-42df-98ff-7c6e4330022d",
+ "is_enabled": true,
+ "id": "0150062",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003099 | Infinite M1000",
+ "title": "Infinite M1000",
+ "value": "BAO:0003099 | Infinite M1000 $496f563a-9b14-4326-b50f-1b34f1572691",
+ "is_enabled": true,
+ "id": "0003099",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003098 | Infinite F500",
+ "title": "Infinite F500",
+ "value": "BAO:0003098 | Infinite F500 $25a811cd-3f94-4987-bab0-d7e71a27c9f0",
+ "is_enabled": true,
+ "id": "0003098",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003097 | Safire",
+ "title": "Safire",
+ "value": "BAO:0003097 | Safire $189734d6-57f7-44f0-91ab-9f7b2583e11e",
+ "is_enabled": true,
+ "id": "0003097",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003096 | LabChip 3000",
+ "title": "LabChip 3000",
+ "value": "BAO:0003096 | LabChip 3000 $df48a841-6e91-48b6-8821-c27fd856a980",
+ "is_enabled": true,
+ "id": "0003096",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003095 | SpectraMax Plus384",
+ "title": "SpectraMax Plus384",
+ "value": "BAO:0003095 | SpectraMax Plus384 $48e5dd8e-594f-4a56-adb2-15ff85c3aca4",
+ "is_enabled": true,
+ "id": "0003095",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003094 | MicroBeta TriLux",
+ "title": "MicroBeta TriLux",
+ "value": "BAO:0003094 | MicroBeta TriLux $54e86e90-12e4-4cd6-829b-1a642bddb55c",
+ "is_enabled": true,
+ "id": "0003094",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003093 | ICR 8000 Ion Channel Reader",
+ "title": "ICR 8000 Ion Channel Reader",
+ "value": "BAO:0003093 | ICR 8000 Ion Channel Reader $935ee2d6-b9a6-47ba-aaa6-6fe7e68679ae",
+ "is_enabled": true,
+ "id": "0003093",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000857 | AxioVert 200M Fluorescence Light Microscope",
+ "title": "AxioVert 200M Fluorescence Light Microscope",
+ "value": "BAO:0000857 | AxioVert 200M Fluorescence Light Microscope $88ab24fd-8bc9-46ba-9267-4f245a67eb8a",
+ "is_enabled": true,
+ "id": "0000857",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000850 | API 4000 LC/MS/MS System",
+ "title": "API 4000 LC/MS/MS System",
+ "value": "BAO:0000850 | API 4000 LC/MS/MS System $8cd8c0d3-a91d-491f-b600-308bdff2b607",
+ "is_enabled": true,
+ "id": "0000850",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000878 | CCD Luminometer",
+ "title": "CCD Luminometer",
+ "value": "BAO:0000878 | CCD Luminometer $6081f4e2-f36e-499b-93fc-c75720d34a3d",
+ "is_enabled": true,
+ "id": "0000878",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000903 | FDSS6000",
+ "title": "FDSS6000",
+ "value": "BAO:0000903 | FDSS6000 $2c4d7818-dcdf-452b-8174-ab9e86cd05ee",
+ "is_enabled": true,
+ "id": "0000903",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000904 | FDSS7000",
+ "title": "FDSS7000",
+ "value": "BAO:0000904 | FDSS7000 $28ae976f-3015-4050-a82b-b929f3483e7f",
+ "is_enabled": true,
+ "id": "0000904",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000905 | FlexStation II Microplate Reader",
+ "title": "FlexStation II Microplate Reader",
+ "value": "BAO:0000905 | FlexStation II Microplate Reader $45232ce8-9b82-4e46-ab01-123b736c597d",
+ "is_enabled": true,
+ "id": "0000905",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000906 | FLIPR TETRA",
+ "title": "FLIPR TETRA",
+ "value": "BAO:0000906 | FLIPR TETRA $bca56a35-2f93-456f-b459-1b1d61bdca9a",
+ "is_enabled": true,
+ "id": "0000906",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000913 | Fluorometer",
+ "title": "Fluorometer",
+ "value": "BAO:0000913 | Fluorometer $c77024af-f0ad-4559-89d9-853457761102",
+ "is_enabled": true,
+ "id": "0000913",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000943 | HyperCyt High Throughput Flow Cytometry System",
+ "title": "HyperCyt High Throughput Flow Cytometry System",
+ "value": "BAO:0000943 | HyperCyt High Throughput Flow Cytometry System $fcddaf95-a1e3-4571-b6cf-50adddbaaa83",
+ "is_enabled": true,
+ "id": "0000943",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000981 | Odyssey Infrared Imager",
+ "title": "Odyssey Infrared Imager",
+ "value": "BAO:0000981 | Odyssey Infrared Imager $5e7446b5-d631-4a24-809e-233a9392bf3c",
+ "is_enabled": true,
+ "id": "0000981",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000982 | Opera QEHS",
+ "title": "Opera QEHS",
+ "value": "BAO:0000982 | Opera QEHS $b4530db0-f178-4c8f-9172-49cc813ed7ef",
+ "is_enabled": true,
+ "id": "0000982",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000971 | Mx3005P qPCR System",
+ "title": "Mx3005P qPCR System",
+ "value": "BAO:0000971 | Mx3005P qPCR System $65c33155-78d0-4955-a792-e84556ad48ee",
+ "is_enabled": true,
+ "id": "0000971",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003100 | LEADseeker Imaging system",
+ "title": "LEADseeker Imaging system",
+ "value": "BAO:0003100 | LEADseeker Imaging system $27b343d4-1222-49b7-b580-c98bb870a9ca",
+ "is_enabled": true,
+ "id": "0003100",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001019 | SpectraMax 190 Microplate Reader",
+ "title": "SpectraMax 190 Microplate Reader",
+ "value": "BAO:0001019 | SpectraMax 190 Microplate Reader $dc26d56a-ad48-4592-8b0e-3e7796dcb898",
+ "is_enabled": true,
+ "id": "0001019",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001036 | TopCount NXT Microplate Scintillation Luminescence Counter",
+ "title": "TopCount NXT Microplate Scintillation Luminescence Counter",
+ "value": "BAO:0001036 | TopCount NXT Microplate Scintillation Luminescence Counter $c84b48e9-85da-46a6-9f11-dc5d90dcc846",
+ "is_enabled": true,
+ "id": "0001036",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001048 | Wallac MicroBeta Liquid Scintillation Counter",
+ "title": "Wallac MicroBeta Liquid Scintillation Counter",
+ "value": "BAO:0001048 | Wallac MicroBeta Liquid Scintillation Counter $6cb6e660-f312-4927-91ac-2e677754551e",
+ "is_enabled": true,
+ "id": "0001048",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001045 | VICTOR X3 Multilabel Plate Reader",
+ "title": "VICTOR X3 Multilabel Plate Reader",
+ "value": "BAO:0001045 | VICTOR X3 Multilabel Plate Reader $66ca14d8-29c7-4aaa-8e5e-38b1eda17a6a",
+ "is_enabled": true,
+ "id": "0001045",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001046 | ViewLux CCD Imager",
+ "title": "ViewLux CCD Imager",
+ "value": "BAO:0001046 | ViewLux CCD Imager $f6689672-6ffd-4631-90a5-3c1936e7d729",
+ "is_enabled": true,
+ "id": "0001046",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150101 | PHERAstar FSX",
+ "title": "PHERAstar FSX",
+ "value": "BAO:0150101 | PHERAstar FSX $81c1d86c-6a69-4657-9623-7ee1bbac068d",
+ "is_enabled": true,
+ "id": "0150101",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150100 | Spectramax L",
+ "title": "Spectramax L",
+ "value": "BAO:0150100 | Spectramax L $8c599c15-86ed-41b5-b57c-01e09c90fb41",
+ "is_enabled": true,
+ "id": "0150100",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150016 | objective lens",
+ "title": "objective lens",
+ "value": "BAO:0150016 | objective lens $f3c15471-51ec-4583-b95b-9e19f158a0e1",
+ "is_enabled": true,
+ "id": "0150016",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150018 | glycerin immersion lens",
+ "title": "glycerin immersion lens",
+ "value": "BAO:0150018 | glycerin immersion lens $2a2f2499-701c-46f5-908b-326486975b67",
+ "is_enabled": true,
+ "id": "0150018",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150017 | air interface objective lens",
+ "title": "air interface objective lens",
+ "value": "BAO:0150017 | air interface objective lens $5ca9f267-8ef3-490f-b45b-bb2e117ccee4",
+ "is_enabled": true,
+ "id": "0150017",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150019 | oil immersion lens",
+ "title": "oil immersion lens",
+ "value": "BAO:0150019 | oil immersion lens $6d4db33c-6683-494b-a221-4a02ea18b51d",
+ "is_enabled": true,
+ "id": "0150019",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150020 | water immersion lens",
+ "title": "water immersion lens",
+ "value": "BAO:0150020 | water immersion lens $d7aa4ba0-e61e-4830-82f0-d601c939d26e",
+ "is_enabled": true,
+ "id": "0150020",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150021 | image acquisition device",
+ "title": "image acquisition device",
+ "value": "BAO:0150021 | image acquisition device $f2745d01-1c51-4b4b-9ee6-815790e2dcf6",
+ "is_enabled": true,
+ "id": "0150021",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150026 | spot detector",
+ "title": "spot detector",
+ "value": "BAO:0150026 | spot detector $48ba0474-e222-4404-9a62-6b0c9e90063d",
+ "is_enabled": true,
+ "id": "0150026",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150027 | photodiode",
+ "title": "photodiode",
+ "value": "BAO:0150027 | photodiode $1641b75a-90ba-4d8f-aca2-50361f1e1706",
+ "is_enabled": true,
+ "id": "0150027",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150028 | photomultiplier tube",
+ "title": "photomultiplier tube",
+ "value": "BAO:0150028 | photomultiplier tube $c743ee22-51d2-4b76-b973-315df503e80c",
+ "is_enabled": true,
+ "id": "0150028",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150022 | area detector",
+ "title": "area detector",
+ "value": "BAO:0150022 | area detector $2caaa15e-e94a-484e-a381-86f7f5e535fc",
+ "is_enabled": true,
+ "id": "0150022",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150025 | electron multiplying charge coupled device",
+ "title": "electron multiplying charge coupled device",
+ "value": "BAO:0150025 | electron multiplying charge coupled device $b95987a9-b3ba-4fbd-8cf8-144b65923f73",
+ "is_enabled": true,
+ "id": "0150025",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150024 | complementary metal oxide semiconductor",
+ "title": "complementary metal oxide semiconductor",
+ "value": "BAO:0150024 | complementary metal oxide semiconductor $d093ef1b-c64b-4249-8d94-dc286e0a4a4f",
+ "is_enabled": true,
+ "id": "0150024",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150023 | charge coupled device",
+ "title": "charge coupled device",
+ "value": "BAO:0150023 | charge coupled device $9a78e094-0138-440a-a0a3-79db88a6947e",
+ "is_enabled": true,
+ "id": "0150023",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150029 | light source",
+ "title": "light source",
+ "value": "BAO:0150029 | light source $6813fb28-56d1-4a4c-a499-f7369fdcde25",
+ "is_enabled": true,
+ "id": "0150029",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150033 | laser",
+ "title": "laser",
+ "value": "BAO:0150033 | laser $c8c9ce85-c42b-4818-a895-94da04df5dd0",
+ "is_enabled": true,
+ "id": "0150033",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150036 | gas laser",
+ "title": "gas laser",
+ "value": "BAO:0150036 | gas laser $846d7fc5-af3a-4352-abb2-d221f898fffe",
+ "is_enabled": true,
+ "id": "0150036",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150037 | ion laser",
+ "title": "ion laser",
+ "value": "BAO:0150037 | ion laser $932a1b50-72a1-4852-94c5-e5adf23292f2",
+ "is_enabled": true,
+ "id": "0150037",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150038 | argon-ion laser",
+ "title": "argon-ion laser",
+ "value": "BAO:0150038 | argon-ion laser $17483f1c-57cc-498c-ac82-40139cb7b59c",
+ "is_enabled": true,
+ "id": "0150038",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150039 | helium-neon laser",
+ "title": "helium-neon laser",
+ "value": "BAO:0150039 | helium-neon laser $db97849b-caf8-49e1-8348-8655527fa15b",
+ "is_enabled": true,
+ "id": "0150039",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150041 | mixed argon-krypton gas laser",
+ "title": "mixed argon-krypton gas laser",
+ "value": "BAO:0150041 | mixed argon-krypton gas laser $35aff9ea-8b9f-4afc-aa5c-fff621210885",
+ "is_enabled": true,
+ "id": "0150041",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150040 | krypton-ion laser",
+ "title": "krypton-ion laser",
+ "value": "BAO:0150040 | krypton-ion laser $45f27203-e9e6-438e-bf8e-b24b283e584a",
+ "is_enabled": true,
+ "id": "0150040",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150042 | metal vapor laser",
+ "title": "metal vapor laser",
+ "value": "BAO:0150042 | metal vapor laser $d7b5ddf5-eb31-4c8e-8b20-c62af3116c7b",
+ "is_enabled": true,
+ "id": "0150042",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150043 | helium-cadmium laser",
+ "title": "helium-cadmium laser",
+ "value": "BAO:0150043 | helium-cadmium laser $db789cfd-d678-4e30-888c-788d651679c7",
+ "is_enabled": true,
+ "id": "0150043",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150044 | nitrogen laser",
+ "title": "nitrogen laser",
+ "value": "BAO:0150044 | nitrogen laser $d61350c1-8053-45b8-bad0-f14864dd3e18",
+ "is_enabled": true,
+ "id": "0150044",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150035 | dye laser",
+ "title": "dye laser",
+ "value": "BAO:0150035 | dye laser $9c42434c-a9be-4edd-b248-c209dea1900d",
+ "is_enabled": true,
+ "id": "0150035",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150034 | diode laser",
+ "title": "diode laser",
+ "value": "BAO:0150034 | diode laser $a58d63d5-1ca9-4a79-ae45-e33ebeac21a6",
+ "is_enabled": true,
+ "id": "0150034",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150045 | solid state laser",
+ "title": "solid state laser",
+ "value": "BAO:0150045 | solid state laser $29559e37-5bcf-41c1-820f-e2c0f1aaac77",
+ "is_enabled": true,
+ "id": "0150045",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150047 | neodymium-yttrium aluminum garnet laser",
+ "title": "neodymium-yttrium aluminum garnet laser",
+ "value": "BAO:0150047 | neodymium-yttrium aluminum garnet laser $90ff94a9-fa93-4986-a170-dbbad44229a5",
+ "is_enabled": true,
+ "id": "0150047",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150046 | chromium-doped lithium strontium aluminum fluoride laser",
+ "title": "chromium-doped lithium strontium aluminum fluoride laser",
+ "value": "BAO:0150046 | chromium-doped lithium strontium aluminum fluoride laser $383a7704-e0c7-487c-bf73-bd39e871750f",
+ "is_enabled": true,
+ "id": "0150046",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150048 | titanium-doped sapphire laser",
+ "title": "titanium-doped sapphire laser",
+ "value": "BAO:0150048 | titanium-doped sapphire laser $a799ea30-a648-4a2f-b4e6-295d61e135e4",
+ "is_enabled": true,
+ "id": "0150048",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150030 | arc lamp",
+ "title": "arc lamp",
+ "value": "BAO:0150030 | arc lamp $a1cc14ae-9fdc-4c02-902f-e64f63b920bb",
+ "is_enabled": true,
+ "id": "0150030",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150032 | xenon lamp",
+ "title": "xenon lamp",
+ "value": "BAO:0150032 | xenon lamp $585c160e-7af2-4dd5-a83e-7ef8a992faba",
+ "is_enabled": true,
+ "id": "0150032",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150031 | mercury-vapor lamp",
+ "title": "mercury-vapor lamp",
+ "value": "BAO:0150031 | mercury-vapor lamp $c583c014-038c-47b1-a749-7a5c97418795",
+ "is_enabled": true,
+ "id": "0150031",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150050 | tungsten halogen lamp",
+ "title": "tungsten halogen lamp",
+ "value": "BAO:0150050 | tungsten halogen lamp $23d45abd-6721-4755-a768-2bb605431ebb",
+ "is_enabled": true,
+ "id": "0150050",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0150049 | light-emitting diode",
+ "title": "light-emitting diode",
+ "value": "BAO:0150049 | light-emitting diode $514fcfb8-6380-494a-9b43-016236492159",
+ "is_enabled": true,
+ "id": "0150049",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002110 | fluorescence microscope filter",
+ "title": "fluorescence microscope filter",
+ "value": "BAO:0002110 | fluorescence microscope filter $c481e7a0-a721-426f-b687-793fc37d8e33",
+ "is_enabled": true,
+ "id": "0002110",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002112 | emission filter",
+ "title": "emission filter",
+ "value": "BAO:0002112 | emission filter $beb5a8fd-c450-4e93-a215-54ada1a061d3",
+ "is_enabled": true,
+ "id": "0002112",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002111 | excitation filter",
+ "title": "excitation filter",
+ "value": "BAO:0002111 | excitation filter $53037e58-e621-4bcc-ba1d-6f5ccbe29f5b",
+ "is_enabled": true,
+ "id": "0002111",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003116 | material entity",
+ "title": "material entity",
+ "value": "BAO:0003116 | material entity $24250b39-0f53-4729-b088-93b3a2d0991d",
+ "is_enabled": true,
+ "id": "0003116",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000114 | culture medium",
+ "title": "culture medium",
+ "value": "BAO:0000114 | culture medium $dca71040-a700-4a12-831e-90300f129024",
+ "is_enabled": true,
+ "id": "0000114",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002596 | culture serum",
+ "title": "culture serum",
+ "value": "BAO:0002596 | culture serum $20638472-9095-4e7e-8acb-da31cf49737f",
+ "is_enabled": true,
+ "id": "0002596",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002597 | assay serum",
+ "title": "assay serum",
+ "value": "BAO:0002597 | assay serum $ae498187-3d64-467f-a49f-29d34b00c485",
+ "is_enabled": true,
+ "id": "0002597",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000025 | bead",
+ "title": "bead",
+ "value": "BAO:0000025 | bead $c0ccfed3-671b-4c3e-a9a1-48a79a446753",
+ "is_enabled": true,
+ "id": "0000025",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002725 | AlphaScreen Beads",
+ "title": "AlphaScreen Beads",
+ "value": "BAO:0002725 | AlphaScreen Beads $5f6536e1-a5f4-4570-8441-73ad17b676a9",
+ "is_enabled": true,
+ "id": "0002725",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:23367 | molecular entity",
+ "title": "molecular entity",
+ "value": "CHEBI:23367 | molecular entity $6b7f8be8-91a0-4ec4-a1fd-025af9f8a6fb",
+ "is_enabled": true,
+ "id": "23367",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:17347 | testosterone",
+ "title": "testosterone",
+ "value": "CHEBI:17347 | testosterone $6a82a638-2300-45e4-b554-9b920810a8d8",
+ "is_enabled": true,
+ "id": "17347",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:44915 | propofol",
+ "title": "propofol",
+ "value": "CHEBI:44915 | propofol $c1c4ba2c-da2c-459e-b883-51140e714313",
+ "is_enabled": true,
+ "id": "44915",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:73472 | kynuramine",
+ "title": "kynuramine",
+ "value": "CHEBI:73472 | kynuramine $7948fa64-be82-44d0-b627-08e52b2b3b43",
+ "is_enabled": true,
+ "id": "73472",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:165840 | Furafylline",
+ "title": "Furafylline",
+ "value": "CHEBI:165840 | Furafylline $57f3c278-95f3-4796-82c6-ed0521c8dd56",
+ "is_enabled": true,
+ "id": "165840",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:50730 | montelukast",
+ "title": "montelukast",
+ "value": "CHEBI:50730 | montelukast $e524e2f1-5a9f-4b9e-b29f-eb4b55ad3d2c",
+ "is_enabled": true,
+ "id": "50730",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:10110 | zidovudine",
+ "title": "zidovudine",
+ "value": "CHEBI:10110 | zidovudine $aaf7c4a0-e8eb-401d-b73c-2624fce85644",
+ "is_enabled": true,
+ "id": "10110",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:47381 | diclofenac",
+ "title": "diclofenac",
+ "value": "CHEBI:47381 | diclofenac $f8b1d9fe-4d99-46ca-a335-e028cd1fa233",
+ "is_enabled": true,
+ "id": "47381",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:7823 | oxazepam",
+ "title": "oxazepam",
+ "value": "CHEBI:7823 | oxazepam $60623528-d981-4346-91a9-2f72a432a68b",
+ "is_enabled": true,
+ "id": "7823",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:6801 | metformin",
+ "title": "metformin",
+ "value": "CHEBI:6801 | metformin $2cfb7ee4-7136-4211-aaab-7eac4c92d3d8",
+ "is_enabled": true,
+ "id": "6801",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:179062 | (S)-Mephenytoin",
+ "title": "(S)-Mephenytoin",
+ "value": "CHEBI:179062 | (S)-Mephenytoin $23667129-f723-4719-86f7-e2122672c0a1",
+ "is_enabled": true,
+ "id": "179062",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:4470 | dextromethorphan",
+ "title": "dextromethorphan",
+ "value": "CHEBI:4470 | dextromethorphan $755d527b-d9ba-4b25-b9a6-9cbd1ad77330",
+ "is_enabled": true,
+ "id": "4470",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:28593 | quinidine",
+ "title": "quinidine",
+ "value": "CHEBI:28593 | quinidine $dd709334-545b-44d1-a75b-5004383a2146",
+ "is_enabled": true,
+ "id": "28593",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:6931 | midazolam",
+ "title": "midazolam",
+ "value": "CHEBI:6931 | midazolam $53df4944-9f43-4052-a44f-38c8670796c2",
+ "is_enabled": true,
+ "id": "6931",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:23965 | estradiol",
+ "title": "estradiol",
+ "value": "CHEBI:23965 | estradiol $e234ccb0-e42f-4f70-ac10-d31de3bd7346",
+ "is_enabled": true,
+ "id": "23965",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:77780 | sulfaphenazole",
+ "title": "sulfaphenazole",
+ "value": "CHEBI:77780 | sulfaphenazole $8495ad06-d549-43cf-a5ca-8854e59dfe36",
+ "is_enabled": true,
+ "id": "77780",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:3219 | bupropion",
+ "title": "bupropion",
+ "value": "CHEBI:3219 | bupropion $7cd754f4-b72f-4a7d-8644-b59892087cf6",
+ "is_enabled": true,
+ "id": "3219",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:8050 | phenacetin",
+ "title": "phenacetin",
+ "value": "CHEBI:8050 | phenacetin $a89534ea-a995-499b-b9e9-a4ab3af1e362",
+ "is_enabled": true,
+ "id": "8050",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:38545 | rosuvastatin",
+ "title": "rosuvastatin",
+ "value": "CHEBI:38545 | rosuvastatin $6a23266a-181a-4d19-8e65-d379fc99bf34",
+ "is_enabled": true,
+ "id": "38545",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:4873 | estropipate",
+ "title": "estropipate",
+ "value": "CHEBI:4873 | estropipate $bc608ce2-8ffe-46b7-a5a4-cb3d666aeff0",
+ "is_enabled": true,
+ "id": "4873",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:45735 | troleandomycin",
+ "title": "troleandomycin",
+ "value": "CHEBI:45735 | troleandomycin $fec6567f-287f-4cd9-aa4c-f51969b2266b",
+ "is_enabled": true,
+ "id": "45735",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:7565 | nifedipine",
+ "title": "nifedipine",
+ "value": "CHEBI:7565 | nifedipine $179c4b6a-2ab6-4aba-b093-27af120ce5e2",
+ "is_enabled": true,
+ "id": "7565",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:2674 | amodiaquine",
+ "title": "amodiaquine",
+ "value": "CHEBI:2674 | amodiaquine $8058fba7-acac-472a-bf9a-3cd1320583e8",
+ "is_enabled": true,
+ "id": "2674",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:45951 | trifluoperazine",
+ "title": "trifluoperazine",
+ "value": "CHEBI:45951 | trifluoperazine $a9823947-68e5-4214-b6f6-e2a9f796df24",
+ "is_enabled": true,
+ "id": "45951",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "CHEBI:36257 | taurocholate",
+ "title": "taurocholate",
+ "value": "CHEBI:36257 | taurocholate $c213c7b8-25a8-4b74-b0f0-da77769499a1",
+ "is_enabled": true,
+ "id": "36257",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000596 | assay medium",
+ "title": "assay medium",
+ "value": "BAO:0000596 | assay medium $4f05ab1b-c2bd-458e-b892-dd7dd3cd7da7",
+ "is_enabled": true,
+ "id": "0000596",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003043 | molecular entity",
+ "title": "molecular entity",
+ "value": "BAO:0003043 | molecular entity $06243266-b5ed-44ef-b65a-13ced7e95ac2",
+ "is_enabled": true,
+ "id": "0003043",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002720 | MES",
+ "title": "MES",
+ "value": "BAO:0002720 | MES $16890f3d-bbbb-489c-bee7-d6e09f9c1895",
+ "is_enabled": true,
+ "id": "0002720",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002784 | phosphatidylinositol (3,4,5)-triphosphate",
+ "title": "phosphatidylinositol (3,4,5)-triphosphate",
+ "value": "BAO:0002784 | phosphatidylinositol (3,4,5)-triphosphate $eff4d409-8146-4080-b0e1-58158bc083c7",
+ "is_enabled": true,
+ "id": "0002784",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002781 | inositol 1,4,5-trisphosphate",
+ "title": "inositol 1,4,5-trisphosphate",
+ "value": "BAO:0002781 | inositol 1,4,5-trisphosphate $20187c7e-c06a-4469-a9ee-85f3ad844f3f",
+ "is_enabled": true,
+ "id": "0002781",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000116 | Hoechst",
+ "title": "Hoechst",
+ "value": "BAO:0000116 | Hoechst $980431f5-3d0c-45c3-9650-2874e1d7caf6",
+ "is_enabled": true,
+ "id": "0000116",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000115 | Hoechst 33342",
+ "title": "Hoechst 33342",
+ "value": "BAO:0000115 | Hoechst 33342 $c432c456-285c-48b4-9187-94cc9a87d1f7",
+ "is_enabled": true,
+ "id": "0000115",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000118 | DMSO",
+ "title": "DMSO",
+ "value": "BAO:0000118 | DMSO $b43b8045-279c-42fd-a11e-1f6a962de496",
+ "is_enabled": true,
+ "id": "0000118",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000171 | lipid",
+ "title": "lipid",
+ "value": "BAO:0000171 | lipid $ef240ff1-a279-473e-a62a-e7c21db43efb",
+ "is_enabled": true,
+ "id": "0000171",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001020 | Sphingosine 1-phosphate",
+ "title": "Sphingosine 1-phosphate",
+ "value": "BAO:0001020 | Sphingosine 1-phosphate $993bfc8e-e942-459d-87fe-ee7ed434fa69",
+ "is_enabled": true,
+ "id": "0001020",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000172 | ACTOne Membrane Potential Dye",
+ "title": "ACTOne Membrane Potential Dye",
+ "value": "BAO:0000172 | ACTOne Membrane Potential Dye $b70cbeea-8d7e-4fb8-be3f-a3b8fee22df0",
+ "is_enabled": true,
+ "id": "0000172",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000175 | protein",
+ "title": "protein",
+ "value": "BAO:0000175 | protein $23dace73-a4eb-46e8-bf0a-5977382a7fa6",
+ "is_enabled": true,
+ "id": "0000175",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030003 | Retinoblastoma-associated protein",
+ "title": "Retinoblastoma-associated protein",
+ "value": "BAO:0030003 | Retinoblastoma-associated protein $11b3ae41-018c-4b7b-9ec2-0c6e5230ad98",
+ "is_enabled": true,
+ "id": "0030003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030000 | Histone H3.3",
+ "title": "Histone H3.3",
+ "value": "BAO:0030000 | Histone H3.3 $f78d9156-bac9-4c03-b437-bfcfd74793e8",
+ "is_enabled": true,
+ "id": "0030000",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030001 | G2/mitotic-specific cyclin-B1",
+ "title": "G2/mitotic-specific cyclin-B1",
+ "value": "BAO:0030001 | G2/mitotic-specific cyclin-B1 $5fda3fdd-00d8-4ac9-8e6d-45b436247743",
+ "is_enabled": true,
+ "id": "0030001",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030002 | Antigen KI-67",
+ "title": "Antigen KI-67",
+ "value": "BAO:0030002 | Antigen KI-67 $986746ff-a31d-4038-a753-52479581263f",
+ "is_enabled": true,
+ "id": "0030002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030008 | Microtubule-associated proteins 1A/1B light chain 3B",
+ "title": "Microtubule-associated proteins 1A/1B light chain 3B",
+ "value": "BAO:0030008 | Microtubule-associated proteins 1A/1B light chain 3B $5f97127b-b2fe-4f48-8dcc-acec1e510f1a",
+ "is_enabled": true,
+ "id": "0030008",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000237 | adhesion",
+ "title": "adhesion",
+ "value": "BAO:0000237 | adhesion $521f5aed-d3e8-4a76-950f-e414070cb70c",
+ "is_enabled": true,
+ "id": "0000237",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030006 | E-selectin",
+ "title": "E-selectin",
+ "value": "BAO:0030006 | E-selectin $6b904743-9ce3-41c3-b39d-f8d66d002de1",
+ "is_enabled": true,
+ "id": "0030006",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030007 | Vascular cell adhesion protein 1",
+ "title": "Vascular cell adhesion protein 1",
+ "value": "BAO:0030007 | Vascular cell adhesion protein 1 $fc707309-c44b-431a-a65d-67eeea8cd5a8",
+ "is_enabled": true,
+ "id": "0030007",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000281 | receptor",
+ "title": "receptor",
+ "value": "BAO:0000281 | receptor $30187fe5-275c-4246-99c3-20ccf62a9361",
+ "is_enabled": true,
+ "id": "0000281",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000285 | transmembrane receptor",
+ "title": "transmembrane receptor",
+ "value": "BAO:0000285 | transmembrane receptor $2c5486d5-beb1-4acc-aad7-0076d025d66b",
+ "is_enabled": true,
+ "id": "0000285",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000280 | ion channel",
+ "title": "ion channel",
+ "value": "BAO:0000280 | ion channel $abbd1859-c28d-4308-87cc-fd85ea8ce994",
+ "is_enabled": true,
+ "id": "0000280",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000284 | G protein coupled receptor",
+ "title": "G protein coupled receptor",
+ "value": "BAO:0000284 | G protein coupled receptor $cf8c45ce-7390-46a2-9595-88d08ab645a3",
+ "is_enabled": true,
+ "id": "0000284",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000719 | CD4-TLR4",
+ "title": "CD4-TLR4",
+ "value": "BAO:0000719 | CD4-TLR4 $ad83d7fa-35dd-436f-a6ca-1f1a415aac15",
+ "is_enabled": true,
+ "id": "0000719",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000718 | CD40",
+ "title": "CD40",
+ "value": "BAO:0000718 | CD40 $968d9b35-d825-4c1b-9dc3-1a5b41ad83bc",
+ "is_enabled": true,
+ "id": "0000718",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000286 | nuclear receptor",
+ "title": "nuclear receptor",
+ "value": "BAO:0000286 | nuclear receptor $496f66ba-aa7e-45ac-b8bf-3467d7a06a5d",
+ "is_enabled": true,
+ "id": "0000286",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000283 | transporter",
+ "title": "transporter",
+ "value": "BAO:0000283 | transporter $02131783-2c1a-49aa-99e8-34de1f19822c",
+ "is_enabled": true,
+ "id": "0000283",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030040 | Solute carrier family 22 member 6",
+ "title": "Solute carrier family 22 member 6",
+ "value": "BAO:0030040 | Solute carrier family 22 member 6 $a0b0410b-be98-44e6-896d-68c52d846015",
+ "is_enabled": true,
+ "id": "0030040",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030041 | Solute carrier family 22 member 7",
+ "title": "Solute carrier family 22 member 7",
+ "value": "BAO:0030041 | Solute carrier family 22 member 7 $e003d46f-22a4-43b7-8d0f-c47ef9eb0f30",
+ "is_enabled": true,
+ "id": "0030041",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030042 | Solute carrier family 22 member 8",
+ "title": "Solute carrier family 22 member 8",
+ "value": "BAO:0030042 | Solute carrier family 22 member 8 $46b01e92-5543-4413-a340-b26182f34f24",
+ "is_enabled": true,
+ "id": "0030042",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030047 | Steroid transmembrane transporter SLC22A24",
+ "title": "Steroid transmembrane transporter SLC22A24",
+ "value": "BAO:0030047 | Steroid transmembrane transporter SLC22A24 $d7bbf08a-687c-4de7-8610-79c7e99dfb91",
+ "is_enabled": true,
+ "id": "0030047",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030043 | Solute carrier organic anion transporter family member 1B1",
+ "title": "Solute carrier organic anion transporter family member 1B1",
+ "value": "BAO:0030043 | Solute carrier organic anion transporter family member 1B1 $9ce5b239-e4a7-4ec0-af32-0b984bc9da54",
+ "is_enabled": true,
+ "id": "0030043",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030044 | Solute carrier organic anion transporter family member 1B3",
+ "title": "Solute carrier organic anion transporter family member 1B3",
+ "value": "BAO:0030044 | Solute carrier organic anion transporter family member 1B3 $136883bc-6f4a-4441-851a-756196350556",
+ "is_enabled": true,
+ "id": "0030044",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030045 | Solute carrier organic anion transporter family member 2B1",
+ "title": "Solute carrier organic anion transporter family member 2B1",
+ "value": "BAO:0030045 | Solute carrier organic anion transporter family member 2B1 $a8f72ab3-7b0b-4b32-9953-c7acb24a9d16",
+ "is_enabled": true,
+ "id": "0030045",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030046 | Solute carrier family 22 member 1",
+ "title": "Solute carrier family 22 member 1",
+ "value": "BAO:0030046 | Solute carrier family 22 member 1 $e5b20f7e-03d1-4c82-b01c-18da4ca28510",
+ "is_enabled": true,
+ "id": "0030046",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030031 | Multidrug and toxin extrusion protein 1",
+ "title": "Multidrug and toxin extrusion protein 1",
+ "value": "BAO:0030031 | Multidrug and toxin extrusion protein 1 $082d57e6-2ef8-4b37-9caa-cd3095c990df",
+ "is_enabled": true,
+ "id": "0030031",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030036 | Solute carrier family 15 member 1",
+ "title": "Solute carrier family 15 member 1",
+ "value": "BAO:0030036 | Solute carrier family 15 member 1 $7461ee28-962e-4704-b2e0-50d09e1cbf0b",
+ "is_enabled": true,
+ "id": "0030036",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030032 | Multidrug and toxin extrusion protein 2",
+ "title": "Multidrug and toxin extrusion protein 2",
+ "value": "BAO:0030032 | Multidrug and toxin extrusion protein 2 $d1c3cad3-9366-42ad-ad9a-39d2afec1f09",
+ "is_enabled": true,
+ "id": "0030032",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030034 | ATP-binding cassette sub-family C member 2",
+ "title": "ATP-binding cassette sub-family C member 2",
+ "value": "BAO:0030034 | ATP-binding cassette sub-family C member 2 $c06d65ec-a400-40a6-a125-399c89893a98",
+ "is_enabled": true,
+ "id": "0030034",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030035 | ATP-binding cassette sub-family C member 3",
+ "title": "ATP-binding cassette sub-family C member 3",
+ "value": "BAO:0030035 | ATP-binding cassette sub-family C member 3 $9ff2f8c5-f0d7-4bd9-a9cd-7f9b86229e11",
+ "is_enabled": true,
+ "id": "0030035",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030014 | Bile salt export pump",
+ "title": "Bile salt export pump",
+ "value": "BAO:0030014 | Bile salt export pump $274b066f-a2a9-4beb-ac94-dfc0a4452235",
+ "is_enabled": true,
+ "id": "0030014",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030013 | Broad substrate specificity ATP-binding cassette transporter ABCG2",
+ "title": "Broad substrate specificity ATP-binding cassette transporter ABCG2",
+ "value": "BAO:0030013 | Broad substrate specificity ATP-binding cassette transporter ABCG2 $ed417810-e190-4e63-89d6-e4c06a9ed206",
+ "is_enabled": true,
+ "id": "0030013",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030061 | Sodium/bile acid cotransporter",
+ "title": "Sodium/bile acid cotransporter",
+ "value": "BAO:0030061 | Sodium/bile acid cotransporter $a48ab40c-5f1f-4b15-ba48-d6bebc336f02",
+ "is_enabled": true,
+ "id": "0030061",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000282 | transcription factor",
+ "title": "transcription factor",
+ "value": "BAO:0000282 | transcription factor $0ddfa499-4ded-46ec-ae7c-08aa7f98625b",
+ "is_enabled": true,
+ "id": "0000282",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030004 | Transcription factor AP-1",
+ "title": "Transcription factor AP-1",
+ "value": "BAO:0030004 | Transcription factor AP-1 $7b2e3eed-1376-4eed-96e9-3194facd8bc5",
+ "is_enabled": true,
+ "id": "0030004",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030010 | Transcription factor p65",
+ "title": "Transcription factor p65",
+ "value": "BAO:0030010 | Transcription factor p65 $c1cc1186-6b9d-4680-a003-7d0275d4e75f",
+ "is_enabled": true,
+ "id": "0030010",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000278 | enzyme regulator",
+ "title": "enzyme regulator",
+ "value": "BAO:0000278 | enzyme regulator $5436347e-60ac-47cd-87e9-d0729943337f",
+ "is_enabled": true,
+ "id": "0000278",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000279 | enzyme",
+ "title": "enzyme",
+ "value": "BAO:0000279 | enzyme $f42ca9f1-e4e9-41f7-b1fc-45deaa168c98",
+ "is_enabled": true,
+ "id": "0000279",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030048 | UDP-glucuronosyltransferase 1A1",
+ "title": "UDP-glucuronosyltransferase 1A1",
+ "value": "BAO:0030048 | UDP-glucuronosyltransferase 1A1 $d16e4310-0a2f-4dbb-a9a8-238311589cfd",
+ "is_enabled": true,
+ "id": "0030048",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030049 | UDP-glucuronosyltransferase 1A3",
+ "title": "UDP-glucuronosyltransferase 1A3",
+ "value": "BAO:0030049 | UDP-glucuronosyltransferase 1A3 $7e454271-903e-4dcd-9f30-879ef1c94f62",
+ "is_enabled": true,
+ "id": "0030049",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030030 | Cytochrome P450 2D11",
+ "title": "Cytochrome P450 2D11",
+ "value": "BAO:0030030 | Cytochrome P450 2D11 $cd79148f-144c-4936-8d16-95c0e3247dc5",
+ "is_enabled": true,
+ "id": "0030030",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030037 | FMO3",
+ "title": "FMO3",
+ "value": "BAO:0030037 | FMO3 $0948e9ed-0075-4438-a2d7-6a71099908c2",
+ "is_enabled": true,
+ "id": "0030037",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030038 | Amine oxidase [flavin-containing] A",
+ "title": "Amine oxidase [flavin-containing] A",
+ "value": "BAO:0030038 | Amine oxidase [flavin-containing] A $adc6b50f-8631-4063-83a7-cd29772f06b9",
+ "is_enabled": true,
+ "id": "0030038",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030039 | Amine oxidase [flavin-containing] B",
+ "title": "Amine oxidase [flavin-containing] B",
+ "value": "BAO:0030039 | Amine oxidase [flavin-containing] B $17cf2fbe-c842-4b42-a92f-435c46fa1eaf",
+ "is_enabled": true,
+ "id": "0030039",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030033 | ATP-dependent translocase ABCB1",
+ "title": "ATP-dependent translocase ABCB1",
+ "value": "BAO:0030033 | ATP-dependent translocase ABCB1 $902f770c-abd6-414d-b6d5-639fdda1007f",
+ "is_enabled": true,
+ "id": "0030033",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030020 | Cytochrome P450 2C8",
+ "title": "Cytochrome P450 2C8",
+ "value": "BAO:0030020 | Cytochrome P450 2C8 $0a28e4b8-8c86-4ad5-a72b-f97ea66a5c84",
+ "is_enabled": true,
+ "id": "0030020",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030025 | Cytochrome P450 2D6",
+ "title": "Cytochrome P450 2D6",
+ "value": "BAO:0030025 | Cytochrome P450 2D6 $00514b3e-82cd-4324-a726-33f31f404106",
+ "is_enabled": true,
+ "id": "0030025",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030026 | Cytochrome P450 3A7",
+ "title": "Cytochrome P450 3A7",
+ "value": "BAO:0030026 | Cytochrome P450 3A7 $7059aeea-9f5c-4bfc-bd22-4368e11225ad",
+ "is_enabled": true,
+ "id": "0030026",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030027 | Epoxide hydrolase 1",
+ "title": "Epoxide hydrolase 1",
+ "value": "BAO:0030027 | Epoxide hydrolase 1 $10c664cc-1f11-4b0f-9436-f793878dc31e",
+ "is_enabled": true,
+ "id": "0030027",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030028 | Cytochrome P450 3A5",
+ "title": "Cytochrome P450 3A5",
+ "value": "BAO:0030028 | Cytochrome P450 3A5 $a974cad0-e844-4016-9f0b-1161b270be5b",
+ "is_enabled": true,
+ "id": "0030028",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030021 | Cytochrome P450 2C9",
+ "title": "Cytochrome P450 2C9",
+ "value": "BAO:0030021 | Cytochrome P450 2C9 $7f1edaca-f1f8-4128-92cc-111a663112e5",
+ "is_enabled": true,
+ "id": "0030021",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030022 | Cytochrome P450 3A4",
+ "title": "Cytochrome P450 3A4",
+ "value": "BAO:0030022 | Cytochrome P450 3A4 $e07d2553-20f2-4ba4-9a1f-f7ea65a0b51d",
+ "is_enabled": true,
+ "id": "0030022",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030023 | Cytochrome P450 2D12",
+ "title": "Cytochrome P450 2D12",
+ "value": "BAO:0030023 | Cytochrome P450 2D12 $8661ec4a-5850-453e-b262-931a7886cc91",
+ "is_enabled": true,
+ "id": "0030023",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030024 | Cytochrome P450 2D9",
+ "title": "Cytochrome P450 2D9",
+ "value": "BAO:0030024 | Cytochrome P450 2D9 $fd3b6e3f-dcda-4f57-b748-277b2de9fe87",
+ "is_enabled": true,
+ "id": "0030024",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030029 | Cytochrome P450 3A10",
+ "title": "Cytochrome P450 3A10",
+ "value": "BAO:0030029 | Cytochrome P450 3A10 $680fe353-ace5-4248-99c7-604d60f0f9a0",
+ "is_enabled": true,
+ "id": "0030029",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030015 | EST1",
+ "title": "EST1",
+ "value": "BAO:0030015 | EST1 $a362d23d-ff8b-4bda-864e-4364b9150ca8",
+ "is_enabled": true,
+ "id": "0030015",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030016 | EST2",
+ "title": "EST2",
+ "value": "BAO:0030016 | EST2 $f376f47c-747d-47dd-aea3-6dda0bc9fab4",
+ "is_enabled": true,
+ "id": "0030016",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030017 | Cytochrome P450 1A2",
+ "title": "Cytochrome P450 1A2",
+ "value": "BAO:0030017 | Cytochrome P450 1A2 $2f479656-0d3c-485a-9604-21d4585847e7",
+ "is_enabled": true,
+ "id": "0030017",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030012 | Aldehyde oxidase",
+ "title": "Aldehyde oxidase",
+ "value": "BAO:0030012 | Aldehyde oxidase $48fbb819-2582-496b-a8d3-73c26aa6bb28",
+ "is_enabled": true,
+ "id": "0030012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030018 | Cytochrome P450 2B6",
+ "title": "Cytochrome P450 2B6",
+ "value": "BAO:0030018 | Cytochrome P450 2B6 $88eca300-8731-4251-ac34-712f4c7f0252",
+ "is_enabled": true,
+ "id": "0030018",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030019 | Cytochrome P450 2C19",
+ "title": "Cytochrome P450 2C19",
+ "value": "BAO:0030019 | Cytochrome P450 2C19 $89eda678-b5c9-46d7-9032-80f0d3159188",
+ "is_enabled": true,
+ "id": "0030019",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030062 | UDP-glucuronosyltransferase 2B17",
+ "title": "UDP-glucuronosyltransferase 2B17",
+ "value": "BAO:0030062 | UDP-glucuronosyltransferase 2B17 $45b189ee-4e0d-4d3b-9a2f-837e3314a6a5",
+ "is_enabled": true,
+ "id": "0030062",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030060 | UDP-glucuronosyltransferase 2B23",
+ "title": "UDP-glucuronosyltransferase 2B23",
+ "value": "BAO:0030060 | UDP-glucuronosyltransferase 2B23 $7b45baf9-a1b4-4810-9340-9ef8eedd4c91",
+ "is_enabled": true,
+ "id": "0030060",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030050 | UDP-glucuronosyltransferase 1A4",
+ "title": "UDP-glucuronosyltransferase 1A4",
+ "value": "BAO:0030050 | UDP-glucuronosyltransferase 1A4 $48b73f47-0352-426b-b61c-02347c8654ca",
+ "is_enabled": true,
+ "id": "0030050",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030051 | UDP-glucuronosyltransferase 1-6",
+ "title": "UDP-glucuronosyltransferase 1-6",
+ "value": "BAO:0030051 | UDP-glucuronosyltransferase 1-6 $ce7f5f70-77e4-4d7c-8055-48ae762a933b",
+ "is_enabled": true,
+ "id": "0030051",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030052 | UDP-glucuronosyltransferase 1A7",
+ "title": "UDP-glucuronosyltransferase 1A7",
+ "value": "BAO:0030052 | UDP-glucuronosyltransferase 1A7 $50950221-8e68-4e0b-bd17-7e9a9aec03b7",
+ "is_enabled": true,
+ "id": "0030052",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030053 | UDP-glucuronosyltransferase 1A8",
+ "title": "UDP-glucuronosyltransferase 1A8",
+ "value": "BAO:0030053 | UDP-glucuronosyltransferase 1A8 $653a5bfb-6167-4c37-868b-0bcef48fe62b",
+ "is_enabled": true,
+ "id": "0030053",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030058 | UDP-glucuronosyltransferase 2B10",
+ "title": "UDP-glucuronosyltransferase 2B10",
+ "value": "BAO:0030058 | UDP-glucuronosyltransferase 2B10 $8c8e40eb-0f09-43fe-9db2-37403630d6cb",
+ "is_enabled": true,
+ "id": "0030058",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030059 | UDP-glucuronosyltransferase 2B15",
+ "title": "UDP-glucuronosyltransferase 2B15",
+ "value": "BAO:0030059 | UDP-glucuronosyltransferase 2B15 $f89010fd-1b65-4dbc-a832-d5cdeb5ab573",
+ "is_enabled": true,
+ "id": "0030059",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030054 | UDP-glucuronosyltransferase 1A9",
+ "title": "UDP-glucuronosyltransferase 1A9",
+ "value": "BAO:0030054 | UDP-glucuronosyltransferase 1A9 $d742f005-676b-4b90-b0a0-aed47366f183",
+ "is_enabled": true,
+ "id": "0030054",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030055 | UDP-glucuronosyltransferase 1A10",
+ "title": "UDP-glucuronosyltransferase 1A10",
+ "value": "BAO:0030055 | UDP-glucuronosyltransferase 1A10 $8a78a72b-6f3c-4be6-8076-a5a84d1759e5",
+ "is_enabled": true,
+ "id": "0030055",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030056 | UDP-glucuronosyltransferase 2B4",
+ "title": "UDP-glucuronosyltransferase 2B4",
+ "value": "BAO:0030056 | UDP-glucuronosyltransferase 2B4 $22fd86e8-d88a-46b7-92d9-aa0e73cf7dc4",
+ "is_enabled": true,
+ "id": "0030056",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030057 | UDP-glucuronosyltransferase 2B7",
+ "title": "UDP-glucuronosyltransferase 2B7",
+ "value": "BAO:0030057 | UDP-glucuronosyltransferase 2B7 $b6fd4d00-c0e8-40ee-82be-46d34968edbe",
+ "is_enabled": true,
+ "id": "0030057",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000289 | ligase",
+ "title": "ligase",
+ "value": "BAO:0000289 | ligase $509d21a6-75eb-4346-8f06-eecbbaae8d6b",
+ "is_enabled": true,
+ "id": "0000289",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000288 | isomerase",
+ "title": "isomerase",
+ "value": "BAO:0000288 | isomerase $93811e05-daaa-481b-97da-f8630845ad6a",
+ "is_enabled": true,
+ "id": "0000288",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000287 | hydrolase",
+ "title": "hydrolase",
+ "value": "BAO:0000287 | hydrolase $e6f1005f-7871-4235-94a2-c4250c2c27d1",
+ "is_enabled": true,
+ "id": "0000287",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000222 | generic hydrolase",
+ "title": "generic hydrolase",
+ "value": "BAO:0000222 | generic hydrolase $d66cb317-e8b2-4725-ae4e-701a76589492",
+ "is_enabled": true,
+ "id": "0000222",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000751 | Beta-lactamase",
+ "title": "Beta-lactamase",
+ "value": "BAO:0000751 | Beta-lactamase $2ed3975e-5064-4bc4-bf6b-65bf47565a0f",
+ "is_enabled": true,
+ "id": "0000751",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000750 | Beta-galactosidase",
+ "title": "Beta-galactosidase",
+ "value": "BAO:0000750 | Beta-galactosidase $0d3d46d4-1776-43de-bbc5-eaaaea35627f",
+ "is_enabled": true,
+ "id": "0000750",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003049 | Caspase-3",
+ "title": "Caspase-3",
+ "value": "BAO:0003049 | Caspase-3 $e566e3ba-204d-4f9d-9f30-59a4343545b2",
+ "is_enabled": true,
+ "id": "0003049",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000295 | phosphatase",
+ "title": "phosphatase",
+ "value": "BAO:0000295 | phosphatase $0de8c91d-eae2-40d5-91f6-45ffd70546ae",
+ "is_enabled": true,
+ "id": "0000295",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000652 | protease",
+ "title": "protease",
+ "value": "BAO:0000652 | protease $d868a24e-91a1-40c9-bdcb-19aab447a3b0",
+ "is_enabled": true,
+ "id": "0000652",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000292 | transferase",
+ "title": "transferase",
+ "value": "BAO:0000292 | transferase $66fd0811-ae0f-48fa-88ed-d86f378f04c0",
+ "is_enabled": true,
+ "id": "0000292",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000294 | kinase",
+ "title": "kinase",
+ "value": "BAO:0000294 | kinase $252788f1-5cdc-464e-adac-59a8fb6e6441",
+ "is_enabled": true,
+ "id": "0000294",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002789 | Mitogen-activated protein kinase 1",
+ "title": "Mitogen-activated protein kinase 1",
+ "value": "BAO:0002789 | Mitogen-activated protein kinase 1 $d0c6f7aa-52b1-4e9d-a74a-5ddc3daf1934",
+ "is_enabled": true,
+ "id": "0002789",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000779 | Creatine kinase",
+ "title": "Creatine kinase",
+ "value": "BAO:0000779 | Creatine kinase $9a3585f4-c636-4d73-b38e-78e9bfc4907d",
+ "is_enabled": true,
+ "id": "0000779",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002109 | Mitogen-activated protein kinase 14",
+ "title": "Mitogen-activated protein kinase 14",
+ "value": "BAO:0002109 | Mitogen-activated protein kinase 14 $48895e1b-c780-43f2-b626-81a8552a6ed2",
+ "is_enabled": true,
+ "id": "0002109",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000293 | generic transferase",
+ "title": "generic transferase",
+ "value": "BAO:0000293 | generic transferase $6f1f6a55-7321-49ad-b656-2b774044bc93",
+ "is_enabled": true,
+ "id": "0000293",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000291 | oxidoreductase",
+ "title": "oxidoreductase",
+ "value": "BAO:0000291 | oxidoreductase $090730ed-0971-4f6f-b444-f1fddb129fd8",
+ "is_enabled": true,
+ "id": "0000291",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000141 | Luciferin 4-monooxygenase",
+ "title": "Luciferin 4-monooxygenase",
+ "value": "BAO:0000141 | Luciferin 4-monooxygenase $e590da3f-1d58-443c-bd4b-d7b890e0dfee",
+ "is_enabled": true,
+ "id": "0000141",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000290 | lyase",
+ "title": "lyase",
+ "value": "BAO:0000290 | lyase $52906e45-f21f-4ef4-aea5-c97dfb530df9",
+ "is_enabled": true,
+ "id": "0000290",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000365 | cytosolic protein",
+ "title": "cytosolic protein",
+ "value": "BAO:0000365 | cytosolic protein $0cc4f421-2c31-4444-bda1-ad552acce64e",
+ "is_enabled": true,
+ "id": "0000365",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030005 | Annexin A5",
+ "title": "Annexin A5",
+ "value": "BAO:0030005 | Annexin A5 $8db6ea91-a9de-4a30-b35d-326448b62995",
+ "is_enabled": true,
+ "id": "0030005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000277 | chaperone",
+ "title": "chaperone",
+ "value": "BAO:0000277 | chaperone $5a702b20-83d9-4ee5-9ffb-aea0f3fa7d05",
+ "is_enabled": true,
+ "id": "0000277",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000766 | NOD1",
+ "title": "NOD1",
+ "value": "BAO:0000766 | NOD1 $4f73418a-6ed9-464f-a884-7b673b5bf5de",
+ "is_enabled": true,
+ "id": "0000766",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000767 | NOD2",
+ "title": "NOD2",
+ "value": "BAO:0000767 | NOD2 $6fc19229-9470-47d0-b3e3-3ffc42fb0bf1",
+ "is_enabled": true,
+ "id": "0000767",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001039 | Ubiquitin-AMC",
+ "title": "Ubiquitin-AMC",
+ "value": "BAO:0001039 | Ubiquitin-AMC $43364377-a0f5-4740-a6c8-ea02ef467731",
+ "is_enabled": true,
+ "id": "0001039",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001041 | Ubiquitin vinyl sulfone",
+ "title": "Ubiquitin vinyl sulfone",
+ "value": "BAO:0001041 | Ubiquitin vinyl sulfone $8170b7da-db40-4ad8-bf9b-f232b1666d52",
+ "is_enabled": true,
+ "id": "0001041",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001040 | Ubiquitin-Rho",
+ "title": "Ubiquitin-Rho",
+ "value": "BAO:0001040 | Ubiquitin-Rho $a01eddf1-181e-42b6-978b-e882fb2cacc5",
+ "is_enabled": true,
+ "id": "0001040",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002108 | Microtubule-associated protein tau",
+ "title": "Microtubule-associated protein tau",
+ "value": "BAO:0002108 | Microtubule-associated protein tau $5005a993-3af3-45fb-9a1b-4a16ee0fffe2",
+ "is_enabled": true,
+ "id": "0002108",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000367 | membrane protein",
+ "title": "membrane protein",
+ "value": "BAO:0000367 | membrane protein $1dc6bad2-91a3-4175-93cd-ccebde4ca7f7",
+ "is_enabled": true,
+ "id": "0000367",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000368 | G protein",
+ "title": "G protein",
+ "value": "BAO:0000368 | G protein $fd799b3f-9af5-4d3d-95fe-67aa4ce16cc7",
+ "is_enabled": true,
+ "id": "0000368",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000919 | G alpha O-Alexa Fluor 488",
+ "title": "G alpha O-Alexa Fluor 488",
+ "value": "BAO:0000919 | G alpha O-Alexa Fluor 488 $f17eea14-b722-489a-9db0-93d22252b31e",
+ "is_enabled": true,
+ "id": "0000919",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000392 | generic membrane protein",
+ "title": "generic membrane protein",
+ "value": "BAO:0000392 | generic membrane protein $297a0309-452c-4bda-b07e-c21332e637d0",
+ "is_enabled": true,
+ "id": "0000392",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002782 | P-selectin glycoprotein ligand 1",
+ "title": "P-selectin glycoprotein ligand 1",
+ "value": "BAO:0002782 | P-selectin glycoprotein ligand 1 $07f081e6-b276-4a69-a45a-0eeaff9d5fbc",
+ "is_enabled": true,
+ "id": "0002782",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000369 | secreted",
+ "title": "secreted",
+ "value": "BAO:0000369 | secreted $25b63923-6858-49e4-8a8a-9ba4cd90995a",
+ "is_enabled": true,
+ "id": "0000369",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000204 | Interleukin-6",
+ "title": "Interleukin-6",
+ "value": "BAO:0000204 | Interleukin-6 $f9322a65-2dc1-404f-a744-2a4430b49039",
+ "is_enabled": true,
+ "id": "0000204",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000236 | Tumor necrosis factor",
+ "title": "Tumor necrosis factor",
+ "value": "BAO:0000236 | Tumor necrosis factor $b8bb0cf7-c254-4eee-a01c-d7b7b9a6cd42",
+ "is_enabled": true,
+ "id": "0000236",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000271 | Interferon gamma",
+ "title": "Interferon gamma",
+ "value": "BAO:0000271 | Interferon gamma $f54d04ef-4f6f-434a-b4c1-958a2056f414",
+ "is_enabled": true,
+ "id": "0000271",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000762 | Interleukin-3",
+ "title": "Interleukin-3",
+ "value": "BAO:0000762 | Interleukin-3 $b36cfe8b-2b25-4bca-acfc-86c0656bb265",
+ "is_enabled": true,
+ "id": "0000762",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002066 | Serum albumin",
+ "title": "Serum albumin",
+ "value": "BAO:0002066 | Serum albumin $12ddc03f-0626-4b66-a69b-11c525d49e9b",
+ "is_enabled": true,
+ "id": "0002066",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000852 | Pancreatic trypsin inhibitor",
+ "title": "Pancreatic trypsin inhibitor",
+ "value": "BAO:0000852 | Pancreatic trypsin inhibitor $340cf57b-c34f-47d1-872f-b0901ea5f8cc",
+ "is_enabled": true,
+ "id": "0000852",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000771 | Thrombopoietin",
+ "title": "Thrombopoietin",
+ "value": "BAO:0000771 | Thrombopoietin $8fe2a3ce-544d-4512-a0dd-a4df2b8bc567",
+ "is_enabled": true,
+ "id": "0000771",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000947 | Interleukin-8",
+ "title": "Interleukin-8",
+ "value": "BAO:0000947 | Interleukin-8 $f3287b2b-d487-4569-9650-ce75b9d9cfa3",
+ "is_enabled": true,
+ "id": "0000947",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000963 | Macrophage inflammatory protein 3 alpha",
+ "title": "Macrophage inflammatory protein 3 alpha",
+ "value": "BAO:0000963 | Macrophage inflammatory protein 3 alpha $9543e721-dee0-430b-8826-5b1949c52c3c",
+ "is_enabled": true,
+ "id": "0000963",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001033 | Thyroid-stimulating hormone",
+ "title": "Thyroid-stimulating hormone",
+ "value": "BAO:0001033 | Thyroid-stimulating hormone $5a274e78-8465-4d15-9891-bdb5d3573868",
+ "is_enabled": true,
+ "id": "0001033",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000370 | structural",
+ "title": "structural",
+ "value": "BAO:0000370 | structural $acc7b7f2-7cee-43dd-8b58-56f01ea9cbdd",
+ "is_enabled": true,
+ "id": "0000370",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0030009 | Tubulin beta-3 chain",
+ "title": "Tubulin beta-3 chain",
+ "value": "BAO:0030009 | Tubulin beta-3 chain $713d5a8f-716c-4bb3-a85d-52c0a53623c6",
+ "is_enabled": true,
+ "id": "0030009",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000174 | peptoid",
+ "title": "peptoid",
+ "value": "BAO:0000174 | peptoid $6eb7be7e-ea89-4b89-b720-4c8db8d999ec",
+ "is_enabled": true,
+ "id": "0000174",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002904 | HBSS",
+ "title": "HBSS",
+ "value": "BAO:0002904 | HBSS $2224dacc-229a-40f5-b238-b32b7df8c636",
+ "is_enabled": true,
+ "id": "0002904",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001215 | Fluormone ES2 Green",
+ "title": "Fluormone ES2 Green",
+ "value": "BAO:0001215 | Fluormone ES2 Green $10923d5c-43c6-4496-82de-ec9a74653ee0",
+ "is_enabled": true,
+ "id": "0001215",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001213 | Fluormone PL Far Red",
+ "title": "Fluormone PL Far Red",
+ "value": "BAO:0001213 | Fluormone PL Far Red $c1d729c8-718f-4977-835e-6b2a299aa1a6",
+ "is_enabled": true,
+ "id": "0001213",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001218 | Atto 495",
+ "title": "Atto 495",
+ "value": "BAO:0001218 | Atto 495 $c549c194-10b2-4fdd-8c85-6badbfe479c6",
+ "is_enabled": true,
+ "id": "0001218",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002547 | GST tag",
+ "title": "GST tag",
+ "value": "BAO:0002547 | GST tag $7145751e-9696-42e3-9f9b-f724c0c039e7",
+ "is_enabled": true,
+ "id": "0002547",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001216 | Fluorescein",
+ "title": "Fluorescein",
+ "value": "BAO:0001216 | Fluorescein $ae9993da-4cf8-4edc-ad50-749134b1dd4d",
+ "is_enabled": true,
+ "id": "0001216",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001217 | Amplex red reagent",
+ "title": "Amplex red reagent",
+ "value": "BAO:0001217 | Amplex red reagent $a60849b5-0df6-443c-aadf-a80f3a35d302",
+ "is_enabled": true,
+ "id": "0001217",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002538 | ethylenediaminetetraacetic acid",
+ "title": "ethylenediaminetetraacetic acid",
+ "value": "BAO:0002538 | ethylenediaminetetraacetic acid $315b4683-efa9-4829-af09-92ce008c4aff",
+ "is_enabled": true,
+ "id": "0002538",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002537 | ethyleneglycol-bis(?-aminoethyl)-N,N,N?,N?-tetraacetic acid",
+ "title": "ethyleneglycol-bis(?-aminoethyl)-N,N,N?,N?-tetraacetic acid",
+ "value": "BAO:0002537 | ethyleneglycol-bis(?-aminoethyl)-N,N,N?,N?-tetraacetic acid $6181acf4-d9dd-4518-8b54-50d3b8da4c75",
+ "is_enabled": true,
+ "id": "0002537",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001234 | ACP-tag",
+ "title": "ACP-tag",
+ "value": "BAO:0001234 | ACP-tag $aaa947d5-9fde-46ad-8b1a-3c31014431d4",
+ "is_enabled": true,
+ "id": "0001234",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001223 | 3H",
+ "title": "3H",
+ "value": "BAO:0001223 | 3H $dfd1c4ca-71ec-4579-9d88-9e037cbf59cc",
+ "is_enabled": true,
+ "id": "0001223",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001224 | 35S",
+ "title": "35S",
+ "value": "BAO:0001224 | 35S $9470c382-1dcb-434b-a216-81db87ea5ac6",
+ "is_enabled": true,
+ "id": "0001224",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001221 | Sytox Orange",
+ "title": "Sytox Orange",
+ "value": "BAO:0001221 | Sytox Orange $be4a1f82-f11a-40b8-8882-37fbe0fbb269",
+ "is_enabled": true,
+ "id": "0001221",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001222 | Ellman and apos's reagent",
+ "title": "Ellman and apos's reagent",
+ "value": "BAO:0001222 | Ellman and apos's reagent $1685790a-a250-4b01-badb-4eded9be75e6",
+ "is_enabled": true,
+ "id": "0001222",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001220 | QuantaBlu",
+ "title": "QuantaBlu",
+ "value": "BAO:0001220 | QuantaBlu $7bcefd09-adf4-45e3-8e9b-033beab142ba",
+ "is_enabled": true,
+ "id": "0001220",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002581 | 5/6 TAMRA",
+ "title": "5/6 TAMRA",
+ "value": "BAO:0002581 | 5/6 TAMRA $c06f47ac-10d9-43ed-99c3-315f9159186f",
+ "is_enabled": true,
+ "id": "0002581",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002580 | malachite green",
+ "title": "malachite green",
+ "value": "BAO:0002580 | malachite green $8e0169b0-47ef-471b-ae80-6b8284d7d2ef",
+ "is_enabled": true,
+ "id": "0002580",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002579 | XTT red",
+ "title": "XTT red",
+ "value": "BAO:0002579 | XTT red $27e3112d-332b-4782-91f0-833fdf68a030",
+ "is_enabled": true,
+ "id": "0002579",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002641 | cyclin B1-luciferin 4-monooxygenase",
+ "title": "cyclin B1-luciferin 4-monooxygenase",
+ "value": "BAO:0002641 | cyclin B1-luciferin 4-monooxygenase $4a736d91-b0c8-4c4b-b1d5-625abdfea669",
+ "is_enabled": true,
+ "id": "0002641",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002651 | FuGENE 6",
+ "title": "FuGENE 6",
+ "value": "BAO:0002651 | FuGENE 6 $d9642d53-c2cc-4800-945f-4614e581d882",
+ "is_enabled": true,
+ "id": "0002651",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000021 | LysoTracker Red",
+ "title": "LysoTracker Red",
+ "value": "BAO:0000021 | LysoTracker Red $d9fa060d-86f1-40ed-b650-bb0060626ce2",
+ "is_enabled": true,
+ "id": "0000021",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000012 | phosphate buffered saline",
+ "title": "phosphate buffered saline",
+ "value": "BAO:0000012 | phosphate buffered saline $87f13f0d-ad0e-4bd0-9583-8b83e3179182",
+ "is_enabled": true,
+ "id": "0000012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002672 | fluo-8 calcium indicator",
+ "title": "fluo-8 calcium indicator",
+ "value": "BAO:0002672 | fluo-8 calcium indicator $46c7d6a2-a116-4517-884d-1f397b839e20",
+ "is_enabled": true,
+ "id": "0002672",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000011 | nucleic acid",
+ "title": "nucleic acid",
+ "value": "BAO:0000011 | nucleic acid $17b89f1a-3791-4bdd-8cdd-5b221d3c8bc8",
+ "is_enabled": true,
+ "id": "0000011",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000269 | DNA",
+ "title": "DNA",
+ "value": "BAO:0000269 | DNA $65a90eef-9cbe-4566-8b96-295d2851a40c",
+ "is_enabled": true,
+ "id": "0000269",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000315 | cDNA",
+ "title": "cDNA",
+ "value": "BAO:0000315 | cDNA $b1bc34a0-7f3c-4159-b067-a223d8d6bdf5",
+ "is_enabled": true,
+ "id": "0000315",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000317 | plasmid DNA",
+ "title": "plasmid DNA",
+ "value": "BAO:0000317 | plasmid DNA $8143fbb4-19a8-415c-a614-b87a3e592073",
+ "is_enabled": true,
+ "id": "0000317",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000316 | genomic DNA",
+ "title": "genomic DNA",
+ "value": "BAO:0000316 | genomic DNA $d421ed28-0862-4207-b12d-d25190d80ea3",
+ "is_enabled": true,
+ "id": "0000316",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000270 | RNA",
+ "title": "RNA",
+ "value": "BAO:0000270 | RNA $04fde587-f6d9-4eb9-915a-7652e218e229",
+ "is_enabled": true,
+ "id": "0000270",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000226 | PNA",
+ "title": "PNA",
+ "value": "BAO:0000226 | PNA $38ecd515-d001-4650-8841-1f120a6e6795",
+ "is_enabled": true,
+ "id": "0000226",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000274 | mRNA",
+ "title": "mRNA",
+ "value": "BAO:0000274 | mRNA $94c0e6f0-ff94-4705-810a-78cf5dfc3132",
+ "is_enabled": true,
+ "id": "0000274",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000276 | tRNA",
+ "title": "tRNA",
+ "value": "BAO:0000276 | tRNA $df7539a3-f4c1-424c-9169-287684c11340",
+ "is_enabled": true,
+ "id": "0000276",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000275 | rRNA",
+ "title": "rRNA",
+ "value": "BAO:0000275 | rRNA $bd16e53c-2fa6-4f9c-a153-97808c5ba3fc",
+ "is_enabled": true,
+ "id": "0000275",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000544 | esiRNA",
+ "title": "esiRNA",
+ "value": "BAO:0000544 | esiRNA $ce0af80e-80f8-4660-ab5c-c95073a1fd11",
+ "is_enabled": true,
+ "id": "0000544",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000322 | miRNA",
+ "title": "miRNA",
+ "value": "BAO:0000322 | miRNA $14e6a2d5-3aa1-492e-a4fa-20dd6a685319",
+ "is_enabled": true,
+ "id": "0000322",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000324 | siRNA",
+ "title": "siRNA",
+ "value": "BAO:0000324 | siRNA $ed02e785-4e7c-475f-8e40-5117661dfd7c",
+ "is_enabled": true,
+ "id": "0000324",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000323 | shRNA",
+ "title": "shRNA",
+ "value": "BAO:0000323 | shRNA $625e64e0-ed55-4708-a868-ca10b099b655",
+ "is_enabled": true,
+ "id": "0000323",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000412 | LNA",
+ "title": "LNA",
+ "value": "BAO:0000412 | LNA $5c28e4f2-0021-47b7-b902-d68d1cdf743d",
+ "is_enabled": true,
+ "id": "0000412",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000498 | riboswitch",
+ "title": "riboswitch",
+ "value": "BAO:0000498 | riboswitch $2df6b028-78a0-443d-afd3-c77b43d6e45e",
+ "is_enabled": true,
+ "id": "0000498",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000496 | RNA aptamer",
+ "title": "RNA aptamer",
+ "value": "BAO:0000496 | RNA aptamer $8f95d9eb-52cd-455d-b05d-2a400e95472b",
+ "is_enabled": true,
+ "id": "0000496",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000047 | Syto 60",
+ "title": "Syto 60",
+ "value": "BAO:0000047 | Syto 60 $2af149b4-56ca-487c-b472-c956bc616875",
+ "is_enabled": true,
+ "id": "0000047",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000076 | screened entity",
+ "title": "screened entity",
+ "value": "BAO:0000076 | screened entity $e25fe365-5bab-4cc5-b4df-a12bc47c870c",
+ "is_enabled": true,
+ "id": "0000076",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000176 | small molecule",
+ "title": "small molecule",
+ "value": "BAO:0000176 | small molecule $60eb6310-1799-4e4e-9469-c68c4db79f11",
+ "is_enabled": true,
+ "id": "0000176",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000215 | small molecule probe",
+ "title": "small molecule probe",
+ "value": "BAO:0000215 | small molecule probe $f9795374-6da2-4a47-9258-7b44cdc697bf",
+ "is_enabled": true,
+ "id": "0000215",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000544 | esiRNA",
+ "title": "esiRNA",
+ "value": "BAO:0000544 | esiRNA $4194c850-32e7-4799-ac8c-cba471a28b31",
+ "is_enabled": true,
+ "id": "0000544",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000322 | miRNA",
+ "title": "miRNA",
+ "value": "BAO:0000322 | miRNA $2796f584-8b15-4454-8f2e-93d8b6080a28",
+ "is_enabled": true,
+ "id": "0000322",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000324 | siRNA",
+ "title": "siRNA",
+ "value": "BAO:0000324 | siRNA $965ceb66-b6bf-44f7-83b5-2bc40c0a2e99",
+ "is_enabled": true,
+ "id": "0000324",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000323 | shRNA",
+ "title": "shRNA",
+ "value": "BAO:0000323 | shRNA $ca91817d-309c-4fef-91bc-80dcabe78caa",
+ "is_enabled": true,
+ "id": "0000323",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000313 | morpholino oligonucleotide",
+ "title": "morpholino oligonucleotide",
+ "value": "BAO:0000313 | morpholino oligonucleotide $ef915233-f1fb-430c-a10e-77a54ba3d2b9",
+ "is_enabled": true,
+ "id": "0000313",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0700003 | bivalent small molecule-peptide",
+ "title": "bivalent small molecule-peptide",
+ "value": "BAO:0700003 | bivalent small molecule-peptide $2d766afc-9757-410c-9a74-df9872ca2c22",
+ "is_enabled": true,
+ "id": "0700003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002016 | lipopolysaccharide",
+ "title": "lipopolysaccharide",
+ "value": "BAO:0002016 | lipopolysaccharide $0dee43d3-c2f6-44dd-8238-6b9fd4c076c6",
+ "is_enabled": true,
+ "id": "0002016",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000638 | forskolin",
+ "title": "forskolin",
+ "value": "BAO:0000638 | forskolin $1a726e8d-c88b-4365-b14f-f764fee14e56",
+ "is_enabled": true,
+ "id": "0000638",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000639 | doxorubicin",
+ "title": "doxorubicin",
+ "value": "BAO:0000639 | doxorubicin $231db69f-04cd-4f1e-9015-cd70ab2b1308",
+ "is_enabled": true,
+ "id": "0000639",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000550 | DNA construct",
+ "title": "DNA construct",
+ "value": "BAO:0000550 | DNA construct $1588050f-c41e-433a-9ec9-4cf32211ecc7",
+ "is_enabled": true,
+ "id": "0000550",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002925 | plasmid DNA construct",
+ "title": "plasmid DNA construct",
+ "value": "BAO:0002925 | plasmid DNA construct $afe645ca-f90d-4cea-96e7-63a08f892c3e",
+ "is_enabled": true,
+ "id": "0002925",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000582 | gene",
+ "title": "gene",
+ "value": "BAO:0000582 | gene $f0af4caf-558e-43ae-a912-f2b50e4c1d56",
+ "is_enabled": true,
+ "id": "0000582",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003044 | beta galactosidase gene",
+ "title": "beta galactosidase gene",
+ "value": "BAO:0003044 | beta galactosidase gene $8c7e2159-3580-418d-9b77-2a3becac9e0e",
+ "is_enabled": true,
+ "id": "0003044",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003047 | luciferase gene",
+ "title": "luciferase gene",
+ "value": "BAO:0003047 | luciferase gene $d6da2418-6f73-4117-90a9-8271ade32398",
+ "is_enabled": true,
+ "id": "0003047",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003046 | green flourescent protein gene",
+ "title": "green flourescent protein gene",
+ "value": "BAO:0003046 | green flourescent protein gene $e61d6c77-6255-4a30-99d7-4158374c30f7",
+ "is_enabled": true,
+ "id": "0003046",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003045 | chloramphenicol acetyl transferase gene",
+ "title": "chloramphenicol acetyl transferase gene",
+ "value": "BAO:0003045 | chloramphenicol acetyl transferase gene $01b7cbaa-5fd2-4e62-896c-62a7dd32877a",
+ "is_enabled": true,
+ "id": "0003045",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000748 | tetracycline",
+ "title": "tetracycline",
+ "value": "BAO:0000748 | tetracycline $462b5f52-ac62-4f62-ba98-b6dabe8ca0d1",
+ "is_enabled": true,
+ "id": "0000748",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000747 | saponin",
+ "title": "saponin",
+ "value": "BAO:0000747 | saponin $50a58636-eaa8-4d3c-8f62-f558d695333c",
+ "is_enabled": true,
+ "id": "0000747",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000749 | NADPH",
+ "title": "NADPH",
+ "value": "BAO:0000749 | NADPH $dbc98a09-f5ea-4365-a3aa-57ce95775acd",
+ "is_enabled": true,
+ "id": "0000749",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000736 | 1-aminoanthracene",
+ "title": "1-aminoanthracene",
+ "value": "BAO:0000736 | 1-aminoanthracene $a3f33164-4f68-445d-a434-8009be34841a",
+ "is_enabled": true,
+ "id": "0000736",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000769 | retinoic acid",
+ "title": "retinoic acid",
+ "value": "BAO:0000769 | retinoic acid $1019381b-591a-46b9-859f-f06fc246f34b",
+ "is_enabled": true,
+ "id": "0000769",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000761 | 3-isobutyl-1-methylanxthine",
+ "title": "3-isobutyl-1-methylanxthine",
+ "value": "BAO:0000761 | 3-isobutyl-1-methylanxthine $e4904d30-53bd-4388-bdfa-1be8d911a5bf",
+ "is_enabled": true,
+ "id": "0000761",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000763 | ionomycin",
+ "title": "ionomycin",
+ "value": "BAO:0000763 | ionomycin $6ead8aad-87c4-4856-9bf1-650e85ccc5d8",
+ "is_enabled": true,
+ "id": "0000763",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000765 | NHK 477",
+ "title": "NHK 477",
+ "value": "BAO:0000765 | NHK 477 $322e74fc-c967-4913-9235-986a190bbcfc",
+ "is_enabled": true,
+ "id": "0000765",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000760 | estrogen",
+ "title": "estrogen",
+ "value": "BAO:0000760 | estrogen $03e70809-da45-4a94-bb2e-38887c36ccbb",
+ "is_enabled": true,
+ "id": "0000760",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000759 | doxycycline",
+ "title": "doxycycline",
+ "value": "BAO:0000759 | doxycycline $54f8c470-7821-47a1-9586-af17b29bc5c4",
+ "is_enabled": true,
+ "id": "0000759",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000755 | coenzyme Q",
+ "title": "coenzyme Q",
+ "value": "BAO:0000755 | coenzyme Q $bf6fb196-20cb-4cfc-a482-3c824b6e0e04",
+ "is_enabled": true,
+ "id": "0000755",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000754 | S-adenosyl methionine",
+ "title": "S-adenosyl methionine",
+ "value": "BAO:0000754 | S-adenosyl methionine $8f13b123-570f-42ac-9ade-0f604a8b091b",
+ "is_enabled": true,
+ "id": "0000754",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000666 | metal salt",
+ "title": "metal salt",
+ "value": "BAO:0000666 | metal salt $50eaa683-9e64-43f4-aa10-2da3b2ffd813",
+ "is_enabled": true,
+ "id": "0000666",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000957 | lithium chloride",
+ "title": "lithium chloride",
+ "value": "BAO:0000957 | lithium chloride $19c7581f-f9f0-4f78-94fc-b181576f7491",
+ "is_enabled": true,
+ "id": "0000957",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100012 | sodium chloride",
+ "title": "sodium chloride",
+ "value": "BAO:0100012 | sodium chloride $5821ff99-00ef-4e01-99e3-aaba163c530e",
+ "is_enabled": true,
+ "id": "0100012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100013 | GPCR arrestin complex",
+ "title": "GPCR arrestin complex",
+ "value": "BAO:0100013 | GPCR arrestin complex $7474bff6-6ff6-451f-92ba-2ce254bcba96",
+ "is_enabled": true,
+ "id": "0100013",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100010 | magnesium chloride",
+ "title": "magnesium chloride",
+ "value": "BAO:0100010 | magnesium chloride $ef613235-73f0-44d1-882b-2b167cac115e",
+ "is_enabled": true,
+ "id": "0100010",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100011 | potassium chloride",
+ "title": "potassium chloride",
+ "value": "BAO:0100011 | potassium chloride $cfcd2f6a-53dd-4b53-a134-71a4b5963e37",
+ "is_enabled": true,
+ "id": "0100011",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100014 | GPCR complex",
+ "title": "GPCR complex",
+ "value": "BAO:0100014 | GPCR complex $5cbd5121-95df-41a6-8f74-f145944be607",
+ "is_enabled": true,
+ "id": "0100014",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100001 | DiFMUP (Molecular Probes)",
+ "title": "DiFMUP (Molecular Probes)",
+ "value": "BAO:0100001 | DiFMUP (Molecular Probes) $2251c1a1-287a-444b-a14a-7d048d74fde9",
+ "is_enabled": true,
+ "id": "0100001",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100002 | alamarBlue",
+ "title": "alamarBlue",
+ "value": "BAO:0100002 | alamarBlue $87865e42-b90b-455c-be2c-0b429382a0cc",
+ "is_enabled": true,
+ "id": "0100002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100009 | formamide",
+ "title": "formamide",
+ "value": "BAO:0100009 | formamide $a8416c73-4a6f-45c0-bed9-95c34aa05d99",
+ "is_enabled": true,
+ "id": "0100009",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100007 | BIS-TRIS",
+ "title": "BIS-TRIS",
+ "value": "BAO:0100007 | BIS-TRIS $3c27d64e-48a0-4431-92f3-9a66e61fb8e9",
+ "is_enabled": true,
+ "id": "0100007",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100005 | ammonium acetate",
+ "title": "ammonium acetate",
+ "value": "BAO:0100005 | ammonium acetate $03c9c9c7-a3b3-4877-b62a-f50cff8f2646",
+ "is_enabled": true,
+ "id": "0100005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0100006 | beta-mercaptoethanol",
+ "title": "beta-mercaptoethanol",
+ "value": "BAO:0100006 | beta-mercaptoethanol $d310b0d9-4398-4857-ac05-7a24ba6fd286",
+ "is_enabled": true,
+ "id": "0100006",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000696 | phosphate buffer",
+ "title": "phosphate buffer",
+ "value": "BAO:0000696 | phosphate buffer $ede192ab-d244-4643-a284-a81058ff025c",
+ "is_enabled": true,
+ "id": "0000696",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000695 | MOPS",
+ "title": "MOPS",
+ "value": "BAO:0000695 | MOPS $d0ef45e5-e826-423f-b276-0247ced4ef6b",
+ "is_enabled": true,
+ "id": "0000695",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000694 | tris",
+ "title": "tris",
+ "value": "BAO:0000694 | tris $62e529ea-9163-4215-8406-fab90bd04944",
+ "is_enabled": true,
+ "id": "0000694",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000693 | HEPES",
+ "title": "HEPES",
+ "value": "BAO:0000693 | HEPES $e48d6b28-85d0-4bbd-81b7-b420d5674064",
+ "is_enabled": true,
+ "id": "0000693",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000325 | peptide",
+ "title": "peptide",
+ "value": "BAO:0000325 | peptide $b8c6ec54-6b9c-4b88-b9c9-471de2f6ab4b",
+ "is_enabled": true,
+ "id": "0000325",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002545 | myc tag",
+ "title": "myc tag",
+ "value": "BAO:0002545 | myc tag $e38d58aa-619a-41b1-ad3d-d550ca0a2014",
+ "is_enabled": true,
+ "id": "0002545",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002546 | HA tag",
+ "title": "HA tag",
+ "value": "BAO:0002546 | HA tag $c14b70b5-6b1a-49f1-80a4-879a6ad416cf",
+ "is_enabled": true,
+ "id": "0002546",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002544 | his tag",
+ "title": "his tag",
+ "value": "BAO:0002544 | his tag $519b3ec3-3525-4129-84ec-d51526c8180a",
+ "is_enabled": true,
+ "id": "0002544",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000745 | FITC-RGS12-GoLoco peptide",
+ "title": "FITC-RGS12-GoLoco peptide",
+ "value": "BAO:0000745 | FITC-RGS12-GoLoco peptide $3e11722f-e9c6-4410-b492-4d0a5bceb36e",
+ "is_enabled": true,
+ "id": "0000745",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000764 | MurNAc-L-Ala-gamma-D-Glu-mDAP",
+ "title": "MurNAc-L-Ala-gamma-D-Glu-mDAP",
+ "value": "BAO:0000764 | MurNAc-L-Ala-gamma-D-Glu-mDAP $c88666eb-bd87-454f-9ced-b053e26bcdc2",
+ "is_enabled": true,
+ "id": "0000764",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003057 | Glutathione",
+ "title": "Glutathione",
+ "value": "BAO:0003057 | Glutathione $03c42663-8c03-4f8d-aab8-87c34f5727a1",
+ "is_enabled": true,
+ "id": "0003057",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003050 | DEVD-NucView 488",
+ "title": "DEVD-NucView 488",
+ "value": "BAO:0003050 | DEVD-NucView 488 $5431d983-2981-4754-83f1-b792b5c3d1b0",
+ "is_enabled": true,
+ "id": "0003050",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000828 | [125I]Y10-neuropeptide S",
+ "title": "[125I]Y10-neuropeptide S",
+ "value": "BAO:0000828 | [125I]Y10-neuropeptide S $f7291a06-5232-4041-9be0-389935c1adc2",
+ "is_enabled": true,
+ "id": "0000828",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000821 | 14LckpCAP394 peptide",
+ "title": "14LckpCAP394 peptide",
+ "value": "BAO:0000821 | 14LckpCAP394 peptide $5ac729aa-a754-4393-9afa-0adce819d98a",
+ "is_enabled": true,
+ "id": "0000821",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000849 | Apelin-13",
+ "title": "Apelin-13",
+ "value": "BAO:0000849 | Apelin-13 $7d83e6d0-9247-4fac-957e-ea08b0a2c075",
+ "is_enabled": true,
+ "id": "0000849",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000843 | AK295 peptide",
+ "title": "AK295 peptide",
+ "value": "BAO:0000843 | AK295 peptide $33cf838f-36fc-4d62-aa18-4d3a132eea04",
+ "is_enabled": true,
+ "id": "0000843",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000837 | Ac-WEHD-CHO",
+ "title": "Ac-WEHD-CHO",
+ "value": "BAO:0000837 | Ac-WEHD-CHO $32968277-01d6-4775-ac95-71ea1e1357de",
+ "is_enabled": true,
+ "id": "0000837",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000835 | Ac-LEHD-AMC",
+ "title": "Ac-LEHD-AMC",
+ "value": "BAO:0000835 | Ac-LEHD-AMC $ecc4c4b6-41aa-48b3-aaf3-4fa7608f93ca",
+ "is_enabled": true,
+ "id": "0000835",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000836 | Ac-WEHD-AFC",
+ "title": "Ac-WEHD-AFC",
+ "value": "BAO:0000836 | Ac-WEHD-AFC $ed226817-c79f-488a-8cea-01ae2b1bead1",
+ "is_enabled": true,
+ "id": "0000836",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000833 | Ac-DEVD-AFC",
+ "title": "Ac-DEVD-AFC",
+ "value": "BAO:0000833 | Ac-DEVD-AFC $3d2ddf1d-ddfb-42a7-b2f1-62b7a9500d04",
+ "is_enabled": true,
+ "id": "0000833",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000834 | Ac-DEVD-CHO",
+ "title": "Ac-DEVD-CHO",
+ "value": "BAO:0000834 | Ac-DEVD-CHO $071a21cd-f792-48b0-a13f-a78011815860",
+ "is_enabled": true,
+ "id": "0000834",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000866 | Boc-Val-Pro-Arg-AMC",
+ "title": "Boc-Val-Pro-Arg-AMC",
+ "value": "BAO:0000866 | Boc-Val-Pro-Arg-AMC $c4ef9b74-da22-4778-99a7-983b9055db37",
+ "is_enabled": true,
+ "id": "0000866",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000864 | Boc-Gln-Gly-Arg-AMC",
+ "title": "Boc-Gln-Gly-Arg-AMC",
+ "value": "BAO:0000864 | Boc-Gln-Gly-Arg-AMC $ed90d883-cef1-4435-85ef-5ea9186dd96a",
+ "is_enabled": true,
+ "id": "0000864",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000865 | Boc-Leu-Gly-Arg-AMC",
+ "title": "Boc-Leu-Gly-Arg-AMC",
+ "value": "BAO:0000865 | Boc-Leu-Gly-Arg-AMC $be06ef71-1899-4183-93ea-1f22df166a40",
+ "is_enabled": true,
+ "id": "0000865",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000888 | DABCYL-Thr-Pro-Leu-Lys~Ser-Pro-Pro-Pro-Ser-Pro-Arg-EDANS",
+ "title": "DABCYL-Thr-Pro-Leu-Lys~Ser-Pro-Pro-Pro-Ser-Pro-Arg-EDANS",
+ "value": "BAO:0000888 | DABCYL-Thr-Pro-Leu-Lys~Ser-Pro-Pro-Pro-Ser-Pro-Arg-EDANS $ad63a3a9-ab2a-4159-8cf2-c046f1c14765",
+ "is_enabled": true,
+ "id": "0000888",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000785 | Kemptide peptide",
+ "title": "Kemptide peptide",
+ "value": "BAO:0000785 | Kemptide peptide $f6d2ea21-14b1-40a2-8105-a6cea2928574",
+ "is_enabled": true,
+ "id": "0000785",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000783 | DYRKtide peptide",
+ "title": "DYRKtide peptide",
+ "value": "BAO:0000783 | DYRKtide peptide $5ec7ed74-5ece-4507-b8fe-07be8a47571a",
+ "is_enabled": true,
+ "id": "0000783",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000774 | Z-Leu-Leu-Leu-al",
+ "title": "Z-Leu-Leu-Leu-al",
+ "value": "BAO:0000774 | Z-Leu-Leu-Leu-al $29ef0c17-b66a-4b8b-a38a-909e52fda3f5",
+ "is_enabled": true,
+ "id": "0000774",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000770 | Thrombin Receptor Activator Peptide 6",
+ "title": "Thrombin Receptor Activator Peptide 6",
+ "value": "BAO:0000770 | Thrombin Receptor Activator Peptide 6 $b8997e18-eea5-4de7-a6fa-d4fcdf3d94dc",
+ "is_enabled": true,
+ "id": "0000770",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000794 | Z-RLRGG-aminoluciferin",
+ "title": "Z-RLRGG-aminoluciferin",
+ "value": "BAO:0000794 | Z-RLRGG-aminoluciferin $6228a24e-7a2f-4e9a-a4dc-165662c68c70",
+ "is_enabled": true,
+ "id": "0000794",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000792 | S6 peptide",
+ "title": "S6 peptide",
+ "value": "BAO:0000792 | S6 peptide $766aa582-a32b-498e-9343-2126e8be6e5c",
+ "is_enabled": true,
+ "id": "0000792",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000793 | Suc-LLVY-aminoluciferin",
+ "title": "Suc-LLVY-aminoluciferin",
+ "value": "BAO:0000793 | Suc-LLVY-aminoluciferin $97897ee0-2dbd-4b6f-8302-9556e58fb8ae",
+ "is_enabled": true,
+ "id": "0000793",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000928 | GM-TriDAP peptide",
+ "title": "GM-TriDAP peptide",
+ "value": "BAO:0000928 | GM-TriDAP peptide $bd56022e-f8d9-4378-8e01-53fceaa386a2",
+ "is_enabled": true,
+ "id": "0000928",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000920 | Galanin",
+ "title": "Galanin",
+ "value": "BAO:0000920 | Galanin $78280c9d-5488-41be-a464-bed5f96a4085",
+ "is_enabled": true,
+ "id": "0000920",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000912 | Fluorogenic triple-helical peptide 3",
+ "title": "Fluorogenic triple-helical peptide 3",
+ "value": "BAO:0000912 | Fluorogenic triple-helical peptide 3 $76639d83-9ce1-4de9-a169-2c35ea3076d3",
+ "is_enabled": true,
+ "id": "0000912",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000918 | fMLFF peptide",
+ "title": "fMLFF peptide",
+ "value": "BAO:0000918 | fMLFF peptide $78ae717c-785c-4f45-aa88-57d5788a6e93",
+ "is_enabled": true,
+ "id": "0000918",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000909 | fMLFK-FITC",
+ "title": "fMLFK-FITC",
+ "value": "BAO:0000909 | fMLFK-FITC $43ef16d8-7571-4743-b25d-18fc2d79c4aa",
+ "is_enabled": true,
+ "id": "0000909",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000934 | H-Leu-NHMec",
+ "title": "H-Leu-NHMec",
+ "value": "BAO:0000934 | H-Leu-NHMec $54d4116d-d406-492e-bc6c-4c2e6a762091",
+ "is_enabled": true,
+ "id": "0000934",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000965 | Melanin-concentrating hormone",
+ "title": "Melanin-concentrating hormone",
+ "value": "BAO:0000965 | Melanin-concentrating hormone $590a051f-648d-47fc-a93a-846c22f9a399",
+ "is_enabled": true,
+ "id": "0000965",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000954 | LDV peptide",
+ "title": "LDV peptide",
+ "value": "BAO:0000954 | LDV peptide $ca7f9061-5cd3-4ae0-a4b8-317c2b1d3532",
+ "is_enabled": true,
+ "id": "0000954",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000984 | Orexin A",
+ "title": "Orexin A",
+ "value": "BAO:0000984 | Orexin A $d3b3b920-1b9c-4181-9029-de2e8f31c896",
+ "is_enabled": true,
+ "id": "0000984",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000985 | Oxytocin",
+ "title": "Oxytocin",
+ "value": "BAO:0000985 | Oxytocin $c6be435c-2c60-4037-922f-541b4443b7c4",
+ "is_enabled": true,
+ "id": "0000985",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000970 | Muramyl dipeptide",
+ "title": "Muramyl dipeptide",
+ "value": "BAO:0000970 | Muramyl dipeptide $bd95b57e-b80f-4d43-ad35-c8ff25230f2e",
+ "is_enabled": true,
+ "id": "0000970",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000976 | Neuropeptide Y",
+ "title": "Neuropeptide Y",
+ "value": "BAO:0000976 | Neuropeptide Y $8cdda47f-d622-4f0a-9a3f-88c9abb99332",
+ "is_enabled": true,
+ "id": "0000976",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000974 | Neuropeptide W",
+ "title": "Neuropeptide W",
+ "value": "BAO:0000974 | Neuropeptide W $af9096e7-976f-4858-aaac-29f9de71408f",
+ "is_enabled": true,
+ "id": "0000974",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000975 | Neuropeptide S",
+ "title": "Neuropeptide S",
+ "value": "BAO:0000975 | Neuropeptide S $4ff7b5a0-f99a-4e6e-8ac3-30b5fa2f42ea",
+ "is_enabled": true,
+ "id": "0000975",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000896 | Dy647-pS136-Bad peptide",
+ "title": "Dy647-pS136-Bad peptide",
+ "value": "BAO:0000896 | Dy647-pS136-Bad peptide $4ffa5ae3-e10e-4129-9eea-fab2f53d5ad1",
+ "is_enabled": true,
+ "id": "0000896",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001014 | RS repeat peptide",
+ "title": "RS repeat peptide",
+ "value": "BAO:0001014 | RS repeat peptide $ce0a83be-46d3-4619-8b15-9e4c79d794f8",
+ "is_enabled": true,
+ "id": "0001014",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001011 | Rhodamine-RGS12-GoLoco peptide",
+ "title": "Rhodamine-RGS12-GoLoco peptide",
+ "value": "BAO:0001011 | Rhodamine-RGS12-GoLoco peptide $d601bb3a-b448-4634-8669-17c0e944e333",
+ "is_enabled": true,
+ "id": "0001011",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001004 | R18 peptide",
+ "title": "R18 peptide",
+ "value": "BAO:0001004 | R18 peptide $d33ff9ec-98da-47c1-8186-de3bb07445df",
+ "is_enabled": true,
+ "id": "0001004",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001002 | Pyr-RTKR-AMC",
+ "title": "Pyr-RTKR-AMC",
+ "value": "BAO:0001002 | Pyr-RTKR-AMC $f578afc7-c8a9-4a86-9811-d561e411e12f",
+ "is_enabled": true,
+ "id": "0001002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001034 | Thyrotropin-releasing hormone",
+ "title": "Thyrotropin-releasing hormone",
+ "value": "BAO:0001034 | Thyrotropin-releasing hormone $47928785-acfd-41c8-ab90-d29843fcfcac",
+ "is_enabled": true,
+ "id": "0001034",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001035 | TMR-pS259-Raf peptide",
+ "title": "TMR-pS259-Raf peptide",
+ "value": "BAO:0001035 | TMR-pS259-Raf peptide $100c1603-2535-477b-b179-39d46f2425e8",
+ "is_enabled": true,
+ "id": "0001035",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001023 | Suc-Ala-Ala-Pro-Phe-AMC",
+ "title": "Suc-Ala-Ala-Pro-Phe-AMC",
+ "value": "BAO:0001023 | Suc-Ala-Ala-Pro-Phe-AMC $47204c6a-267c-4275-8608-bc016db14a28",
+ "is_enabled": true,
+ "id": "0001023",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001052 | Z-Arg-Arg-AMC",
+ "title": "Z-Arg-Arg-AMC",
+ "value": "BAO:0001052 | Z-Arg-Arg-AMC $bc507d7d-8360-466b-bcba-2631b84c1305",
+ "is_enabled": true,
+ "id": "0001052",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001053 | Z-Phe-Arg-AMC",
+ "title": "Z-Phe-Arg-AMC",
+ "value": "BAO:0001053 | Z-Phe-Arg-AMC $08d5c355-4e35-410f-8016-8ebcc54917be",
+ "is_enabled": true,
+ "id": "0001053",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001051 | WKYMVm peptide",
+ "title": "WKYMVm peptide",
+ "value": "BAO:0001051 | WKYMVm peptide $053e96f9-6115-4aab-96c0-9d021fac5b4d",
+ "is_enabled": true,
+ "id": "0001051",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001042 | ULight poly-GT",
+ "title": "ULight poly-GT",
+ "value": "BAO:0001042 | ULight poly-GT $659d6118-4a7f-4ba4-8f5c-d2db5d2d7ee5",
+ "is_enabled": true,
+ "id": "0001042",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000313 | morpholino oligonucleotide",
+ "title": "morpholino oligonucleotide",
+ "value": "BAO:0000313 | morpholino oligonucleotide $fdf7e03d-edad-404f-bb94-13da5e91a278",
+ "is_enabled": true,
+ "id": "0000313",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000500 | molecular beacon",
+ "title": "molecular beacon",
+ "value": "BAO:0000500 | molecular beacon $c5e7fb9d-6a1c-4e10-9390-1266f63e28dd",
+ "is_enabled": true,
+ "id": "0000500",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000497 | peptide aptamer",
+ "title": "peptide aptamer",
+ "value": "BAO:0000497 | peptide aptamer $e6240748-edd3-471f-9010-c96024ffbff7",
+ "is_enabled": true,
+ "id": "0000497",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000495 | DNA aptamer",
+ "title": "DNA aptamer",
+ "value": "BAO:0000495 | DNA aptamer $81e83879-5c94-4539-b0d3-442b829e1aa3",
+ "is_enabled": true,
+ "id": "0000495",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002051 | DNA vector",
+ "title": "DNA vector",
+ "value": "BAO:0002051 | DNA vector $98b0b6fb-6de1-4598-b660-ef89a6eaf486",
+ "is_enabled": true,
+ "id": "0002051",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002015 | carbohydrate",
+ "title": "carbohydrate",
+ "value": "BAO:0002015 | carbohydrate $36574dcd-b159-46c4-99da-e7e27fae49b9",
+ "is_enabled": true,
+ "id": "0002015",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002016 | lipopolysaccharide",
+ "title": "lipopolysaccharide",
+ "value": "BAO:0002016 | lipopolysaccharide $16f73ebc-4141-424a-8742-6add024680d8",
+ "is_enabled": true,
+ "id": "0002016",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000845 | Alpha-D-glucose",
+ "title": "Alpha-D-glucose",
+ "value": "BAO:0000845 | Alpha-D-glucose $0b779c0e-e91a-4314-b9d1-595009cc7d64",
+ "is_enabled": true,
+ "id": "0000845",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000782 | D-galactose",
+ "title": "D-galactose",
+ "value": "BAO:0000782 | D-galactose $3776f643-a578-4fea-ad7d-32e9a532ec72",
+ "is_enabled": true,
+ "id": "0000782",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000925 | Glucose-6-phosphate",
+ "title": "Glucose-6-phosphate",
+ "value": "BAO:0000925 | Glucose-6-phosphate $717c5665-dd4f-41a1-8921-3159a56cecac",
+ "is_enabled": true,
+ "id": "0000925",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000924 | Glucose",
+ "title": "Glucose",
+ "value": "BAO:0000924 | Glucose $8127f23f-bebe-410f-a2db-822cf9512960",
+ "is_enabled": true,
+ "id": "0000924",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000927 | Glycogen",
+ "title": "Glycogen",
+ "value": "BAO:0000927 | Glycogen $e5bea263-5c0b-4384-bd10-c120d632f2b5",
+ "is_enabled": true,
+ "id": "0000927",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000910 | Fluorescein Di-beta-D-Glucopyranoside",
+ "title": "Fluorescein Di-beta-D-Glucopyranoside",
+ "value": "BAO:0000910 | Fluorescein Di-beta-D-Glucopyranoside $28d47f3e-be4e-4bf0-8d7a-5eabc946fa49",
+ "is_enabled": true,
+ "id": "0000910",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000964 | Mannose-6-phosphate",
+ "title": "Mannose-6-phosphate",
+ "value": "BAO:0000964 | Mannose-6-phosphate $d45cc98f-a159-49f0-8232-e61c3f91995c",
+ "is_enabled": true,
+ "id": "0000964",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001007 | Resorufin alpha-D-pyranoside",
+ "title": "Resorufin alpha-D-pyranoside",
+ "value": "BAO:0001007 | Resorufin alpha-D-pyranoside $72c506c3-6ce7-4540-9e80-d5cd91f361ec",
+ "is_enabled": true,
+ "id": "0001007",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001008 | Resorufin beta-D-glucopyranoside",
+ "title": "Resorufin beta-D-glucopyranoside",
+ "value": "BAO:0001008 | Resorufin beta-D-glucopyranoside $8b8dc9a8-4a79-4a5b-9294-1747b33af254",
+ "is_enabled": true,
+ "id": "0001008",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002010 | nucleotide",
+ "title": "nucleotide",
+ "value": "BAO:0002010 | nucleotide $c3e525e2-7638-4b8b-88ad-40eeb98d7be5",
+ "is_enabled": true,
+ "id": "0002010",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002742 | EdU",
+ "title": "EdU",
+ "value": "BAO:0002742 | EdU $2ff00a77-95c8-457a-9e45-66246b5c209a",
+ "is_enabled": true,
+ "id": "0002742",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002757 | Cyclic guanosine monophosphate",
+ "title": "Cyclic guanosine monophosphate",
+ "value": "BAO:0002757 | Cyclic guanosine monophosphate $6d50ebbd-6bb9-4267-a95b-0d0d9610d401",
+ "is_enabled": true,
+ "id": "0002757",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002783 | [35S]GTP-gamma S",
+ "title": "[35S]GTP-gamma S",
+ "value": "BAO:0002783 | [35S]GTP-gamma S $6354ec73-087c-4f2d-86b0-ab19c2836385",
+ "is_enabled": true,
+ "id": "0002783",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000875 | Cyclic adenosine monophosphate",
+ "title": "Cyclic adenosine monophosphate",
+ "value": "BAO:0000875 | Cyclic adenosine monophosphate $ae9569f7-a9e2-48b9-b8f5-e0ddb5751c11",
+ "is_enabled": true,
+ "id": "0000875",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000775 | Adenosine diphosphate",
+ "title": "Adenosine diphosphate",
+ "value": "BAO:0000775 | Adenosine diphosphate $ce16c8c1-19c9-4c83-8f87-c1d49cb499b5",
+ "is_enabled": true,
+ "id": "0000775",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000776 | Adenosine triphosphate",
+ "title": "Adenosine triphosphate",
+ "value": "BAO:0000776 | Adenosine triphosphate $b6a7fe8d-62f9-4c98-a273-a4abf1186d5d",
+ "is_enabled": true,
+ "id": "0000776",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000931 | BODIPY GTP",
+ "title": "BODIPY GTP",
+ "value": "BAO:0000931 | BODIPY GTP $7262e592-bfcc-41a2-b266-d3fbd47faacc",
+ "is_enabled": true,
+ "id": "0000931",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001061 | guanosine triphosphate",
+ "title": "guanosine triphosphate",
+ "value": "BAO:0001061 | guanosine triphosphate $bcd6d643-8d60-4b00-afaa-4223e1b41db4",
+ "is_enabled": true,
+ "id": "0001061",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001060 | guanosine diphosphate",
+ "title": "guanosine diphosphate",
+ "value": "BAO:0001060 | guanosine diphosphate $c8dcc00d-15ce-4017-a757-9a6ae8cc6bb1",
+ "is_enabled": true,
+ "id": "0001060",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003055 | octyl glucoside",
+ "title": "octyl glucoside",
+ "value": "BAO:0003055 | octyl glucoside $465a8963-dea6-4602-a886-4b10d7d89eee",
+ "is_enabled": true,
+ "id": "0003055",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003054 | tricine",
+ "title": "tricine",
+ "value": "BAO:0003054 | tricine $449f5518-3e09-488f-81c5-d8848e3c7672",
+ "is_enabled": true,
+ "id": "0003054",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003053 | PIPES",
+ "title": "PIPES",
+ "value": "BAO:0003053 | PIPES $69790e0f-6414-446e-a9ad-6f47c8bc7d58",
+ "is_enabled": true,
+ "id": "0003053",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003056 | tris(2-carboxyethyl)phosphine hydrochloride",
+ "title": "tris(2-carboxyethyl)phosphine hydrochloride",
+ "value": "BAO:0003056 | tris(2-carboxyethyl)phosphine hydrochloride $fdf714c5-4fef-4bee-98d1-55d85620e922",
+ "is_enabled": true,
+ "id": "0003056",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003051 | TO-PRO3",
+ "title": "TO-PRO3",
+ "value": "BAO:0003051 | TO-PRO3 $78f66b85-7d93-4872-a7b5-4cfbe18f8b9a",
+ "is_enabled": true,
+ "id": "0003051",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000800 | TransIT-CHO kit",
+ "title": "TransIT-CHO kit",
+ "value": "BAO:0000800 | TransIT-CHO kit $2c10b020-557b-4999-81d8-28c49785310d",
+ "is_enabled": true,
+ "id": "0000800",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000801 | TransIT-LT1",
+ "title": "TransIT-LT1",
+ "value": "BAO:0000801 | TransIT-LT1 $403975a9-514d-49cb-b96a-fd8fec350a2e",
+ "is_enabled": true,
+ "id": "0000801",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000826 | 6,8-difluoro-4-methylumbelliferyl phosphate",
+ "title": "6,8-difluoro-4-methylumbelliferyl phosphate",
+ "value": "BAO:0000826 | 6,8-difluoro-4-methylumbelliferyl phosphate $c79d3066-fa33-44be-8fd5-53669a2d672f",
+ "is_enabled": true,
+ "id": "0000826",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000827 | 6,8-difluoro-7-hydroxy-4-methylcoumarin",
+ "title": "6,8-difluoro-7-hydroxy-4-methylcoumarin",
+ "value": "BAO:0000827 | 6,8-difluoro-7-hydroxy-4-methylcoumarin $a24a2aa4-0232-43c8-ae06-93e651f02cc0",
+ "is_enabled": true,
+ "id": "0000827",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000824 | 4 methylumbelliferyl-D-pyranoside",
+ "title": "4 methylumbelliferyl-D-pyranoside",
+ "value": "BAO:0000824 | 4 methylumbelliferyl-D-pyranoside $bd082277-9cfd-4e22-9b46-194f4af9ecea",
+ "is_enabled": true,
+ "id": "0000824",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000825 | 5-carboxamidotryptamine",
+ "title": "5-carboxamidotryptamine",
+ "value": "BAO:0000825 | 5-carboxamidotryptamine $b29f1746-5f0c-4d18-9924-9c6c75516fe6",
+ "is_enabled": true,
+ "id": "0000825",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000829 | [3H]N-methylscopolamine",
+ "title": "[3H]N-methylscopolamine",
+ "value": "BAO:0000829 | [3H]N-methylscopolamine $e9fc7245-b35b-4376-87a0-ee26ca497ae5",
+ "is_enabled": true,
+ "id": "0000829",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000822 | 3-O-methyl-fluorescein",
+ "title": "3-O-methyl-fluorescein",
+ "value": "BAO:0000822 | 3-O-methyl-fluorescein $cdfedecd-8b59-4c7d-9c3b-02c8dd561bf4",
+ "is_enabled": true,
+ "id": "0000822",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000823 | 3-O-methylfluorescein phosphate",
+ "title": "3-O-methylfluorescein phosphate",
+ "value": "BAO:0000823 | 3-O-methylfluorescein phosphate $5855b742-13dc-4822-b0b5-4df5e0a37dfd",
+ "is_enabled": true,
+ "id": "0000823",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000820 | 1, 4 methyllumbelliferone",
+ "title": "1, 4 methyllumbelliferone",
+ "value": "BAO:0000820 | 1, 4 methyllumbelliferone $9e111220-d3dc-4138-b627-31a88dfdebac",
+ "is_enabled": true,
+ "id": "0000820",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000811 | wee1-like protein-luciferin 4-monooxygenase",
+ "title": "wee1-like protein-luciferin 4-monooxygenase",
+ "value": "BAO:0000811 | wee1-like protein-luciferin 4-monooxygenase $79abce28-2615-4742-b6d6-ba46fc5d76af",
+ "is_enabled": true,
+ "id": "0000811",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000848 | angiotensin II",
+ "title": "angiotensin II",
+ "value": "BAO:0000848 | angiotensin II $29a7be51-e8cf-4feb-af19-96d8e2af7fcf",
+ "is_enabled": true,
+ "id": "0000848",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000846 | 7-amino-4-methylcoumarin",
+ "title": "7-amino-4-methylcoumarin",
+ "value": "BAO:0000846 | 7-amino-4-methylcoumarin $a3a614da-a7c9-4405-9fb3-daf5a1d40657",
+ "is_enabled": true,
+ "id": "0000846",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000840 | 7-amino-4-trifluoromethylcoumarin",
+ "title": "7-amino-4-trifluoromethylcoumarin",
+ "value": "BAO:0000840 | 7-amino-4-trifluoromethylcoumarin $fccf972e-fda6-482b-9938-c3e8f7f9e051",
+ "is_enabled": true,
+ "id": "0000840",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000844 | alkaline phosphatase-cAMP",
+ "title": "alkaline phosphatase-cAMP",
+ "value": "BAO:0000844 | alkaline phosphatase-cAMP $937c8c1c-ef62-4a85-92e1-8417b9193e19",
+ "is_enabled": true,
+ "id": "0000844",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000838 | acetylcholine",
+ "title": "acetylcholine",
+ "value": "BAO:0000838 | acetylcholine $69ed4dae-d9f8-4cb4-8cd9-ca8808c30835",
+ "is_enabled": true,
+ "id": "0000838",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000830 | A23187",
+ "title": "A23187",
+ "value": "BAO:0000830 | A23187 $fffc61b3-371d-4b91-ab25-5ed4e200a760",
+ "is_enabled": true,
+ "id": "0000830",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000868 | BRL-54443",
+ "title": "BRL-54443",
+ "value": "BAO:0000868 | BRL-54443 $8c7b9f82-ab7c-46bb-ae39-99b856e3cc70",
+ "is_enabled": true,
+ "id": "0000868",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000862 | bisindolylmaleimide",
+ "title": "bisindolylmaleimide",
+ "value": "BAO:0000862 | bisindolylmaleimide $544a0dd0-1d86-4f69-a690-f1cfa1af1c62",
+ "is_enabled": true,
+ "id": "0000862",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000860 | beta-hydroxybutyryl coenzyme A",
+ "title": "beta-hydroxybutyryl coenzyme A",
+ "value": "BAO:0000860 | beta-hydroxybutyryl coenzyme A $6d43d3d2-533e-4419-b528-7a8d906cb1a4",
+ "is_enabled": true,
+ "id": "0000860",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000867 | Brij-35",
+ "title": "Brij-35",
+ "value": "BAO:0000867 | Brij-35 $49a67d82-eaec-4b78-b819-8163701621ba",
+ "is_enabled": true,
+ "id": "0000867",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000853 | arachidonic acid",
+ "title": "arachidonic acid",
+ "value": "BAO:0000853 | arachidonic acid $cef5ec79-f9eb-41a5-83dd-6ad2a78efad6",
+ "is_enabled": true,
+ "id": "0000853",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000854 | arrestin-GFP",
+ "title": "arrestin-GFP",
+ "value": "BAO:0000854 | arrestin-GFP $569b4667-e623-42ca-8b15-3be2b159746a",
+ "is_enabled": true,
+ "id": "0000854",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000885 | cysteine",
+ "title": "cysteine",
+ "value": "BAO:0000885 | cysteine $996bb42a-1362-4f60-b7d7-2f7f3f958bc2",
+ "is_enabled": true,
+ "id": "0000885",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000882 | coenzyme A",
+ "title": "coenzyme A",
+ "value": "BAO:0000882 | coenzyme A $c10b2607-548d-4142-a16e-781b17c9056c",
+ "is_enabled": true,
+ "id": "0000882",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000883 | Cy5",
+ "title": "Cy5",
+ "value": "BAO:0000883 | Cy5 $7fe7dbb8-5888-4429-90f9-df98e7ae91e7",
+ "is_enabled": true,
+ "id": "0000883",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000886 | inositol-1-phosphate",
+ "title": "inositol-1-phosphate",
+ "value": "BAO:0000886 | inositol-1-phosphate $545e7aec-2e32-414f-baf3-d9bbbd969d52",
+ "is_enabled": true,
+ "id": "0000886",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000880 | CHAPS",
+ "title": "CHAPS",
+ "value": "BAO:0000880 | CHAPS $1a961096-5085-4ba8-97b3-6f7a3b6aaeca",
+ "is_enabled": true,
+ "id": "0000880",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000874 | calcium",
+ "title": "calcium",
+ "value": "BAO:0000874 | calcium $8aabe4bc-49b4-43fb-8aa0-f9cb39c14170",
+ "is_enabled": true,
+ "id": "0000874",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000876 | carbachol",
+ "title": "carbachol",
+ "value": "BAO:0000876 | carbachol $3a914813-7cce-4e2b-a631-b407a50981b2",
+ "is_enabled": true,
+ "id": "0000876",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000870 | BTC AM Fluorescent Dye Indicator",
+ "title": "BTC AM Fluorescent Dye Indicator",
+ "value": "BAO:0000870 | BTC AM Fluorescent Dye Indicator $6b4e34d8-8199-460e-b5f0-f07bfc3174f4",
+ "is_enabled": true,
+ "id": "0000870",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000786 | luciferin 6-ME",
+ "title": "luciferin 6-ME",
+ "value": "BAO:0000786 | luciferin 6-ME $1732fe47-103e-4e9e-a693-4e0f7303b42b",
+ "is_enabled": true,
+ "id": "0000786",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000784 | ethylene glycol ester of luciferin 6' methyl ether",
+ "title": "ethylene glycol ester of luciferin 6' methyl ether",
+ "value": "BAO:0000784 | ethylene glycol ester of luciferin 6' methyl ether $ec2c5d36-f3d4-4034-8298-4afad0227228",
+ "is_enabled": true,
+ "id": "0000784",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000789 | peptide-aminoluciferin",
+ "title": "peptide-aminoluciferin",
+ "value": "BAO:0000789 | peptide-aminoluciferin $b66c62a5-f141-49b8-8bee-982df8dbb291",
+ "is_enabled": true,
+ "id": "0000789",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000787 | luciferin-PPXE",
+ "title": "luciferin-PPXE",
+ "value": "BAO:0000787 | luciferin-PPXE $fcce0a2a-f12d-479e-886f-e439f98d80b8",
+ "is_enabled": true,
+ "id": "0000787",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000788 | luciferin-BE",
+ "title": "luciferin-BE",
+ "value": "BAO:0000788 | luciferin-BE $af831570-f1a5-4588-a495-026f8ebb09ad",
+ "is_enabled": true,
+ "id": "0000788",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000781 | deoxyluciferin",
+ "title": "deoxyluciferin",
+ "value": "BAO:0000781 | deoxyluciferin $8eefabc0-1561-4872-bdad-9c7ef756dc9f",
+ "is_enabled": true,
+ "id": "0000781",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000772 | triiodothyronine",
+ "title": "triiodothyronine",
+ "value": "BAO:0000772 | triiodothyronine $cf18eddd-9def-4dd9-80b0-ec286261a8b8",
+ "is_enabled": true,
+ "id": "0000772",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000773 | tunicamycin",
+ "title": "tunicamycin",
+ "value": "BAO:0000773 | tunicamycin $b54d6a49-9f59-4d87-bf20-626ba17ec0eb",
+ "is_enabled": true,
+ "id": "0000773",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000778 | creatine phosphate",
+ "title": "creatine phosphate",
+ "value": "BAO:0000778 | creatine phosphate $6366b85c-092e-4b42-837e-4f4bda5801b9",
+ "is_enabled": true,
+ "id": "0000778",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000777 | CDP-ME",
+ "title": "CDP-ME",
+ "value": "BAO:0000777 | CDP-ME $7473e91e-7154-4151-9217-f6bb00ee6732",
+ "is_enabled": true,
+ "id": "0000777",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000796 | ketoconazole",
+ "title": "ketoconazole",
+ "value": "BAO:0000796 | ketoconazole $6cfbb40a-353c-49a5-9b84-b12e963f3eae",
+ "is_enabled": true,
+ "id": "0000796",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000797 | quinidine",
+ "title": "quinidine",
+ "value": "BAO:0000797 | quinidine $256c3216-c4ab-4f0f-bf72-336b65e0abc7",
+ "is_enabled": true,
+ "id": "0000797",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000795 | furafylline",
+ "title": "furafylline",
+ "value": "BAO:0000795 | furafylline $15533cf2-b1eb-482f-a03d-d94654e30dca",
+ "is_enabled": true,
+ "id": "0000795",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000799 | lipofectin",
+ "title": "lipofectin",
+ "value": "BAO:0000799 | lipofectin $433b0df5-e2df-4aa1-b325-241dc7426aaa",
+ "is_enabled": true,
+ "id": "0000799",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000901 | Eu3+-cAMP",
+ "title": "Eu3+-cAMP",
+ "value": "BAO:0000901 | Eu3+-cAMP $d9f4d854-86f0-423f-ae3f-d4e2947c4bcd",
+ "is_enabled": true,
+ "id": "0000901",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000907 | fluo-4 AM calcium indicator",
+ "title": "fluo-4 AM calcium indicator",
+ "value": "BAO:0000907 | fluo-4 AM calcium indicator $f294b51a-5be8-4af0-a9a7-5ef923ac9887",
+ "is_enabled": true,
+ "id": "0000907",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000900 | estrogen-alexa 633",
+ "title": "estrogen-alexa 633",
+ "value": "BAO:0000900 | estrogen-alexa 633 $868cb0d9-fe76-455f-9711-edbf7841514d",
+ "is_enabled": true,
+ "id": "0000900",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000926 | glutamate",
+ "title": "glutamate",
+ "value": "BAO:0000926 | glutamate $9e85abc3-c6de-4dd6-9ef4-80d5681af990",
+ "is_enabled": true,
+ "id": "0000926",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000929 | Go6976",
+ "title": "Go6976",
+ "value": "BAO:0000929 | Go6976 $ef0048f5-ec15-4a73-b14c-f7d96a9543ca",
+ "is_enabled": true,
+ "id": "0000929",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000914 | fluorophosphonate-rhodamine",
+ "title": "fluorophosphonate-rhodamine",
+ "value": "BAO:0000914 | fluorophosphonate-rhodamine $ff82d787-e811-41cb-88c6-78224a1faf2c",
+ "is_enabled": true,
+ "id": "0000914",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000915 | fluozin-2",
+ "title": "fluozin-2",
+ "value": "BAO:0000915 | fluozin-2 $8d20c4c4-dfe7-448b-9520-c8be94f08981",
+ "is_enabled": true,
+ "id": "0000915",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000916 | fluozin",
+ "title": "fluozin",
+ "value": "BAO:0000916 | fluozin $8e7029c5-76d5-4564-ad4d-6ce7653038fc",
+ "is_enabled": true,
+ "id": "0000916",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000945 | indo-1 calcium indicator",
+ "title": "indo-1 calcium indicator",
+ "value": "BAO:0000945 | indo-1 calcium indicator $a49fda77-aeb4-4155-ad9c-17ddf8ef89cc",
+ "is_enabled": true,
+ "id": "0000945",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000949 | IPEGAL",
+ "title": "IPEGAL",
+ "value": "BAO:0000949 | IPEGAL $3a928e27-f4ba-403e-a4b2-68cfd60edd91",
+ "is_enabled": true,
+ "id": "0000949",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000932 | GW5074",
+ "title": "GW5074",
+ "value": "BAO:0000932 | GW5074 $ada379f6-0ef3-4d58-aa27-daa4c68bdbb3",
+ "is_enabled": true,
+ "id": "0000932",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000933 | GW8510",
+ "title": "GW8510",
+ "value": "BAO:0000933 | GW8510 $de7d1766-96fc-413a-8858-9bb961c30360",
+ "is_enabled": true,
+ "id": "0000933",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000967 | mevalonate",
+ "title": "mevalonate",
+ "value": "BAO:0000967 | mevalonate $1c00db4a-3322-4ad0-8292-0ca437617ffd",
+ "is_enabled": true,
+ "id": "0000967",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000961 | luciferin-H EGE",
+ "title": "luciferin-H EGE",
+ "value": "BAO:0000961 | luciferin-H EGE $2787fcf3-7752-4b93-8d8c-bad653a81daa",
+ "is_enabled": true,
+ "id": "0000961",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000962 | lysophosphatidylinositol",
+ "title": "lysophosphatidylinositol",
+ "value": "BAO:0000962 | lysophosphatidylinositol $828085f1-932b-4e3a-bbca-0e03eebee28a",
+ "is_enabled": true,
+ "id": "0000962",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000960 | luciferin-H",
+ "title": "luciferin-H",
+ "value": "BAO:0000960 | luciferin-H $acd9dea7-6e47-49d6-aede-d06705f1a581",
+ "is_enabled": true,
+ "id": "0000960",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000956 | lipofectamine 2000",
+ "title": "lipofectamine 2000",
+ "value": "BAO:0000956 | lipofectamine 2000 $9dca54cd-07ce-4b0e-a1ff-35ff8754d94d",
+ "is_enabled": true,
+ "id": "0000956",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000950 | isoproterenol",
+ "title": "isoproterenol",
+ "value": "BAO:0000950 | isoproterenol $d4e10bc6-867a-4601-bbee-1316de3a59d7",
+ "is_enabled": true,
+ "id": "0000950",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000952 | L-AP4",
+ "title": "L-AP4",
+ "value": "BAO:0000952 | L-AP4 $c24db9a1-d78e-485b-ac2e-281b69e9886f",
+ "is_enabled": true,
+ "id": "0000952",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000987 | para-nitrophenylphosphate",
+ "title": "para-nitrophenylphosphate",
+ "value": "BAO:0000987 | para-nitrophenylphosphate $d9eb3369-307a-4d73-97b7-7d5db2ea016d",
+ "is_enabled": true,
+ "id": "0000987",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000986 | para-nitrophenol",
+ "title": "para-nitrophenol",
+ "value": "BAO:0000986 | para-nitrophenol $2ab4d93b-c2a0-4bf3-8b1f-c035a4c97783",
+ "is_enabled": true,
+ "id": "0000986",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000980 | O-methyl-fluorescein phosphate",
+ "title": "O-methyl-fluorescein phosphate",
+ "value": "BAO:0000980 | O-methyl-fluorescein phosphate $ed164c46-a3ce-4fdc-a535-2b8b4460b0b3",
+ "is_enabled": true,
+ "id": "0000980",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000978 | NP-40",
+ "title": "NP-40",
+ "value": "BAO:0000978 | NP-40 $c5465100-74bd-46e7-b0b7-f7091160f566",
+ "is_enabled": true,
+ "id": "0000978",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000972 | NBD C6-HPC",
+ "title": "NBD C6-HPC",
+ "value": "BAO:0000972 | NBD C6-HPC $bfb54fec-c6a7-43eb-9a7a-bd1abbfd5c43",
+ "is_enabled": true,
+ "id": "0000972",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000995 | pluronic F-127",
+ "title": "pluronic F-127",
+ "value": "BAO:0000995 | pluronic F-127 $750e7088-be7a-41c2-9248-146470281c1f",
+ "is_enabled": true,
+ "id": "0000995",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000992 | phosphomevalonate",
+ "title": "phosphomevalonate",
+ "value": "BAO:0000992 | phosphomevalonate $cb3ba2d1-8a91-4bd2-a835-7d6500ce95de",
+ "is_enabled": true,
+ "id": "0000992",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000998 | probenecid",
+ "title": "probenecid",
+ "value": "BAO:0000998 | probenecid $2552ecc1-2cdd-41d0-a098-8377a463e785",
+ "is_enabled": true,
+ "id": "0000998",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000999 | profluorescent 1-AMA",
+ "title": "profluorescent 1-AMA",
+ "value": "BAO:0000999 | profluorescent 1-AMA $a137a1a8-8218-4b28-b09c-3fa3d17407ee",
+ "is_enabled": true,
+ "id": "0000999",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000996 | phorbol myristate acetate",
+ "title": "phorbol myristate acetate",
+ "value": "BAO:0000996 | phorbol myristate acetate $3614dbd5-7293-4a47-bdce-8da55883d03b",
+ "is_enabled": true,
+ "id": "0000996",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000997 | potassium phosphoenolpyruvate",
+ "title": "potassium phosphoenolpyruvate",
+ "value": "BAO:0000997 | potassium phosphoenolpyruvate $7a437baf-d95f-4d06-bd76-164b3d07b5f3",
+ "is_enabled": true,
+ "id": "0000997",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000990 | phosphoenolpyruvate",
+ "title": "phosphoenolpyruvate",
+ "value": "BAO:0000990 | phosphoenolpyruvate $aa0cffe8-ec2a-4b91-bb41-d1e255c6bda2",
+ "is_enabled": true,
+ "id": "0000990",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000991 | phosphoethanolamine",
+ "title": "phosphoethanolamine",
+ "value": "BAO:0000991 | phosphoethanolamine $8abbe247-d688-4ea7-8bd1-940d7661d3df",
+ "is_enabled": true,
+ "id": "0000991",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000895 | DTT",
+ "title": "DTT",
+ "value": "BAO:0000895 | DTT $e99a1521-71d4-4d30-a8bf-8cd91f52a562",
+ "is_enabled": true,
+ "id": "0000895",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000894 | dopamine",
+ "title": "dopamine",
+ "value": "BAO:0000894 | dopamine $6dbefe0a-08ad-4bdd-9edc-7b21699a27fb",
+ "is_enabled": true,
+ "id": "0000894",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000897 | dynorphin A",
+ "title": "dynorphin A",
+ "value": "BAO:0000897 | dynorphin A $0df8d8e6-7574-4b07-a053-a9532880c783",
+ "is_enabled": true,
+ "id": "0000897",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000891 | diminazene aceturate",
+ "title": "diminazene aceturate",
+ "value": "BAO:0000891 | diminazene aceturate $c488a9c1-22fa-4606-9645-bafb9e10d764",
+ "is_enabled": true,
+ "id": "0000891",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000892 | diphosphomevalonate",
+ "title": "diphosphomevalonate",
+ "value": "BAO:0000892 | diphosphomevalonate $2d97b828-96f5-47f6-b904-d190da366118",
+ "is_enabled": true,
+ "id": "0000892",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0000890 | DAMGO",
+ "title": "DAMGO",
+ "value": "BAO:0000890 | DAMGO $de90409b-2060-4ea6-91e4-1523e62e6f0e",
+ "is_enabled": true,
+ "id": "0000890",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003108 | beetle luciferin",
+ "title": "beetle luciferin",
+ "value": "BAO:0003108 | beetle luciferin $84693c03-4008-4b33-9a7c-53e1d6e2cebd",
+ "is_enabled": true,
+ "id": "0003108",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001017 | SNC80",
+ "title": "SNC80",
+ "value": "BAO:0001017 | SNC80 $38564ea5-31d9-4523-ba26-8aa4a8ecf462",
+ "is_enabled": true,
+ "id": "0001017",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001018 | sodium orthovanadate",
+ "title": "sodium orthovanadate",
+ "value": "BAO:0001018 | sodium orthovanadate $79cf696e-71a0-4746-bd79-69abce8030ac",
+ "is_enabled": true,
+ "id": "0001018",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001012 | Ro 20-1724",
+ "title": "Ro 20-1724",
+ "value": "BAO:0001012 | Ro 20-1724 $9ea80cc5-e39a-4413-a52d-e15f146d5bc7",
+ "is_enabled": true,
+ "id": "0001012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001013 | rolipram",
+ "title": "rolipram",
+ "value": "BAO:0001013 | rolipram $bcaa4f62-0435-48c9-997e-e77538acea18",
+ "is_enabled": true,
+ "id": "0001013",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001010 | rhodamine-conjugated sulfonate ester",
+ "title": "rhodamine-conjugated sulfonate ester",
+ "value": "BAO:0001010 | rhodamine-conjugated sulfonate ester $e2518e2d-38ab-4410-9053-973fd48bbd6b",
+ "is_enabled": true,
+ "id": "0001010",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001005 | rauwolscine",
+ "title": "rauwolscine",
+ "value": "BAO:0001005 | rauwolscine $ea5a158f-a199-4bb7-b64a-5eb0ba37f439",
+ "is_enabled": true,
+ "id": "0001005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001006 | resorufin",
+ "title": "resorufin",
+ "value": "BAO:0001006 | resorufin $389c7ef4-228d-48d0-9693-ce48fcc6d5b9",
+ "is_enabled": true,
+ "id": "0001006",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001003 | pyrimidine-4,6-dicarboxylic acid",
+ "title": "pyrimidine-4,6-dicarboxylic acid",
+ "value": "BAO:0001003 | pyrimidine-4,6-dicarboxylic acid $a961612c-43ed-4108-8d38-0fa79e7b029e",
+ "is_enabled": true,
+ "id": "0001003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001009 | rhodamine",
+ "title": "rhodamine",
+ "value": "BAO:0001009 | rhodamine $b0f79de9-73e6-43c4-b511-0d5910830c24",
+ "is_enabled": true,
+ "id": "0001009",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001001 | prostaglandin E2",
+ "title": "prostaglandin E2",
+ "value": "BAO:0001001 | prostaglandin E2 $7e9eef1f-6789-4ea8-bf4c-6c682b1b279a",
+ "is_enabled": true,
+ "id": "0001001",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001000 | prostaglandin",
+ "title": "prostaglandin",
+ "value": "BAO:0001000 | prostaglandin $5f2c747d-ac65-4cd2-aeaf-ee852e53228b",
+ "is_enabled": true,
+ "id": "0001000",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001038 | tween 20",
+ "title": "tween 20",
+ "value": "BAO:0001038 | tween 20 $f76b3561-3689-4ce8-8862-b5a384f2ce67",
+ "is_enabled": true,
+ "id": "0001038",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001037 | triton X-100",
+ "title": "triton X-100",
+ "value": "BAO:0001037 | triton X-100 $4e72f3e9-b54e-4bca-8f34-a45a30e03ce2",
+ "is_enabled": true,
+ "id": "0001037",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001030 | thapsigargin",
+ "title": "thapsigargin",
+ "value": "BAO:0001030 | thapsigargin $09ba1eb8-262e-4f31-aab1-8bcb44b846e8",
+ "is_enabled": true,
+ "id": "0001030",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001032 | thioflavine S",
+ "title": "thioflavine S",
+ "value": "BAO:0001032 | thioflavine S $49084e23-02bf-4546-ae7f-8120646af6b9",
+ "is_enabled": true,
+ "id": "0001032",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001027 | TG003",
+ "title": "TG003",
+ "value": "BAO:0001027 | TG003 $979d1acb-acb8-4e7f-b4c6-f115bf605683",
+ "is_enabled": true,
+ "id": "0001027",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001028 | thallium",
+ "title": "thallium",
+ "value": "BAO:0001028 | thallium $1676c166-7b4a-423b-9f85-f45a6b64ce50",
+ "is_enabled": true,
+ "id": "0001028",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001026 | texas Red",
+ "title": "texas Red",
+ "value": "BAO:0001026 | texas Red $f6c8d849-1611-4e81-afc0-0e769d0aa0bb",
+ "is_enabled": true,
+ "id": "0001026",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001024 | SYPRO orange dye",
+ "title": "SYPRO orange dye",
+ "value": "BAO:0001024 | SYPRO orange dye $411a72c1-a28e-4349-a3a9-ef102a03ec90",
+ "is_enabled": true,
+ "id": "0001024",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001021 | staurosporine",
+ "title": "staurosporine",
+ "value": "BAO:0001021 | staurosporine $c1937aab-92e4-4a5d-8607-f005fc6e2ddc",
+ "is_enabled": true,
+ "id": "0001021",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001022 | stibavirin",
+ "title": "stibavirin",
+ "value": "BAO:0001022 | stibavirin $85f64339-e7bd-433b-88fe-0f5e89ef62d8",
+ "is_enabled": true,
+ "id": "0001022",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001050 | WIN55212",
+ "title": "WIN55212",
+ "value": "BAO:0001050 | WIN55212 $67317041-09a3-4b77-84ee-a890768b4a6c",
+ "is_enabled": true,
+ "id": "0001050",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001054 | zaprinast",
+ "title": "zaprinast",
+ "value": "BAO:0001054 | zaprinast $9c7a3f8c-fa7d-474a-8727-6b62656be0c2",
+ "is_enabled": true,
+ "id": "0001054",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0001044 | vasopressin",
+ "title": "vasopressin",
+ "value": "BAO:0001044 | vasopressin $03083070-3d8b-42f1-a2b6-7f2816a279cd",
+ "is_enabled": true,
+ "id": "0001044",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0002149 | RNA interference construct",
+ "title": "RNA interference construct",
+ "value": "BAO:0002149 | RNA interference construct $bcf802cf-27ce-4f4c-ae5e-738cd5b0a7ca",
+ "is_enabled": true,
+ "id": "0002149",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0003119 | software",
+ "title": "software",
+ "value": "BAO:0003119 | software $8ef4ad05-ec92-4d0e-9827-d0f788ffcd27",
+ "is_enabled": true,
+ "id": "0003119",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180022 | sequencing data analysis software",
+ "title": "sequencing data analysis software",
+ "value": "BAO:0180022 | sequencing data analysis software $a3aa3e95-15ee-4e4e-b14a-7be37e32547d",
+ "is_enabled": true,
+ "id": "0180022",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180024 | Cuffdiff",
+ "title": "Cuffdiff",
+ "value": "BAO:0180024 | Cuffdiff $98218563-02f8-4cff-9e44-afd6d51d3f80",
+ "is_enabled": true,
+ "id": "0180024",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180023 | Cuffcompare",
+ "title": "Cuffcompare",
+ "value": "BAO:0180023 | Cuffcompare $ac1b8462-8b0c-4684-843a-14e0e39b7e2b",
+ "is_enabled": true,
+ "id": "0180023",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180004 | image analysis software",
+ "title": "image analysis software",
+ "value": "BAO:0180004 | image analysis software $86825a54-a1c2-44cd-b34d-a13c053b3802",
+ "is_enabled": true,
+ "id": "0180004",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180009 | IN Cell Investigator",
+ "title": "IN Cell Investigator",
+ "value": "BAO:0180009 | IN Cell Investigator $555b868e-84a3-42f5-9fda-ce7441f19f6e",
+ "is_enabled": true,
+ "id": "0180009",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180008 | Fiji",
+ "title": "Fiji",
+ "value": "BAO:0180008 | Fiji $0d00b22d-5e5c-46e1-80a5-a2e5ec438ff4",
+ "is_enabled": true,
+ "id": "0180008",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180007 | DCILabs",
+ "title": "DCILabs",
+ "value": "BAO:0180007 | DCILabs $00fa7778-63ac-4a5e-8251-c127dc359ac9",
+ "is_enabled": true,
+ "id": "0180007",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180006 | Cellomics BioApplication",
+ "title": "Cellomics BioApplication",
+ "value": "BAO:0180006 | Cellomics BioApplication $2679f2a0-08cf-446b-aa7c-b460c01d0364",
+ "is_enabled": true,
+ "id": "0180006",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180005 | CellProfiler",
+ "title": "CellProfiler",
+ "value": "BAO:0180005 | CellProfiler $20434e9f-bfb1-45e8-8158-3eb36cc69d41",
+ "is_enabled": true,
+ "id": "0180005",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180003 | BioImageXD",
+ "title": "BioImageXD",
+ "value": "BAO:0180003 | BioImageXD $f2f114c5-995b-4b5f-bb5f-82a066c985e3",
+ "is_enabled": true,
+ "id": "0180003",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180002 | BD AttoVision",
+ "title": "BD AttoVision",
+ "value": "BAO:0180002 | BD AttoVision $ceac16d1-d150-4570-8a9a-430a79fef5ab",
+ "is_enabled": true,
+ "id": "0180002",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180001 | Acapella",
+ "title": "Acapella",
+ "value": "BAO:0180001 | Acapella $b7b3aa51-0dc4-4617-9ac1-bd0f583f90be",
+ "is_enabled": true,
+ "id": "0180001",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180017 | Harmony",
+ "title": "Harmony",
+ "value": "BAO:0180017 | Harmony $5af4ada7-68d4-4add-a24c-52558afbff14",
+ "is_enabled": true,
+ "id": "0180017",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180016 | Volocity 3D Image Analysis Software",
+ "title": "Volocity 3D Image Analysis Software",
+ "value": "BAO:0180016 | Volocity 3D Image Analysis Software $6efba62a-221f-4601-9060-8a1b3e721010",
+ "is_enabled": true,
+ "id": "0180016",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180015 | MetaMorph",
+ "title": "MetaMorph",
+ "value": "BAO:0180015 | MetaMorph $97f4f62a-88fc-4cbb-b638-0de1ec1455ad",
+ "is_enabled": true,
+ "id": "0180015",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180014 | SlideBook software",
+ "title": "SlideBook software",
+ "value": "BAO:0180014 | SlideBook software $6fe47ea2-9254-4cb2-990e-6fef36d57ee0",
+ "is_enabled": true,
+ "id": "0180014",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180013 | MetaXpress",
+ "title": "MetaXpress",
+ "value": "BAO:0180013 | MetaXpress $c6f9ceaa-15ae-423d-8d0b-1b45bef392ef",
+ "is_enabled": true,
+ "id": "0180013",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180012 | MATLAB",
+ "title": "MATLAB",
+ "value": "BAO:0180012 | MATLAB $e3750451-8329-41ce-b489-b09766bb184a",
+ "is_enabled": true,
+ "id": "0180012",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180011 | ImageJ",
+ "title": "ImageJ",
+ "value": "BAO:0180011 | ImageJ $ee0267d8-9b6e-4889-a2a2-2e8419b16862",
+ "is_enabled": true,
+ "id": "0180011",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180010 | Icy",
+ "title": "Icy",
+ "value": "BAO:0180010 | Icy $1ae9220e-cc80-4a44-8cb7-ce833e2a2e98",
+ "is_enabled": true,
+ "id": "0180010",
+ "children": []
+ }
+ ]
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180018 | sequencing data alignment software",
+ "title": "sequencing data alignment software",
+ "value": "BAO:0180018 | sequencing data alignment software $2d83a369-50ee-4ed7-9050-959f6e1b0a20",
+ "is_enabled": true,
+ "id": "0180018",
+ "children": [{
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180021 | Bowtie",
+ "title": "Bowtie",
+ "value": "BAO:0180021 | Bowtie $f0437061-1f00-4c2f-81fe-ac67588f94d9",
+ "is_enabled": true,
+ "id": "0180021",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180020 | TopHat",
+ "title": "TopHat",
+ "value": "BAO:0180020 | TopHat $0889f1e2-6e76-473e-9971-47a26eaaa386",
+ "is_enabled": true,
+ "id": "0180020",
+ "children": []
+ }, {
+ "term_id": null,
+ "synonyms": null,
+ "synonym": null,
+ "search": "BAO:0180019 | Cufflinks",
+ "title": "Cufflinks",
+ "value": "BAO:0180019 | Cufflinks $19f069e4-2653-4803-92a6-0c192287baf2",
+ "is_enabled": true,
+ "id": "0180019",
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }]
+ }
diff --git a/run-js-dev.sh b/run-js-dev.sh
index 18c2666ed6..c868aad3f5 100755
--- a/run-js-dev.sh
+++ b/run-js-dev.sh
@@ -1,11 +1,16 @@
#!/bin/bash
-if [ ! -x yarn ]
-then
- npm install -g yarn
+if command -v yarn; then
+ echo '>>> yarn is installed -> continue'
+else
+ echo '>>> Missing yarn. Installing...'
+ npm install -g yarn
fi
-asdf global nodejs 14.21.3
+
+echo '>>> Installing JS packages...'
yarn install
+echo "=========================================================================================================="
echo "THIS WILL FAIL UNTIL THE RUBY GEMS ARE INSTALLED BY run-ruby-dev.sh. JUST TRY AGAIN AFTER INSTALLING THEM."
+echo "=========================================================================================================="
./bin/webpack-dev-server
diff --git a/run-ruby-dev.sh b/run-ruby-dev.sh
index cf9439c41c..b434b56468 100755
--- a/run-ruby-dev.sh
+++ b/run-ruby-dev.sh
@@ -1,6 +1,40 @@
#!/bin/bash
+export ASDF_BRANCH=v0.13.1
-gem install bundler -v 2.1.4 && bundle install
+# if asdf is not installed -> install
+if command -v asdf ; then
+ echo '>>> asdf is already installed -> continue'
+else
+ echo '>>> Missing asdf. Installing...'
+ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch $ASDF_BRANCH
+fi
+
+# if asdf plugins are not installed -> install
+if asdf plugin list | grep -Fxq 'ruby'; then
+ echo '>>> Ruby plugin for asdf is installed -> continue'
+else
+ echo '>>> Missing ruby plugin for asdf. Installing...'
+ asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git
+fi
+
+if asdf plugin list | grep -Fxq 'nodejs'; then
+ echo '>>> Nodejs plugin for asdf is installed -> continue'
+else
+ echo '>>> Missing nodejs plugin for asdf. Installing...'
+ asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git
+fi
+
+# install all tools as defined by .tool-versions
+echo '>>> Installing tool versions'
+asdf install
+
+# install bundler if not present and then install all gems as defined by GEMFILE
+echo '>>> checking bundler installation'
+BUNDLER_VERSION=$(sed -n '/BUNDLED WITH/{n;p;}' "Gemfile.lock" | tr -d '[:space:]')
+gem install bundler -v $BUNDLER_VERSION
+
+echo '>>> Installing gems'
+bundle install
rm -f tmp/pids/server.pid
@@ -16,5 +50,4 @@ else
bundle exec rake db:setup
fi
-
bundle exec rails s -p 3000 -b 0.0.0.0
diff --git a/spec/api/chemotion/admin_api_spec.rb b/spec/api/chemotion/admin_api_spec.rb
index 882570f635..b44d099b07 100644
--- a/spec/api/chemotion/admin_api_spec.rb
+++ b/spec/api/chemotion/admin_api_spec.rb
@@ -44,7 +44,7 @@
end
end
- describe 'GET /api/v1/admin/group_device/name' do
+ describe 'GET /api/v1/admin_user/listUsers/byname' do
let(:person) { create(:person) }
let(:group) { create(:group) }
let(:person_obj) { JSON.parse(Entities::UserSimpleEntity.new(person).to_json) }
@@ -52,7 +52,7 @@
describe 'with group type' do
before do
- get "/api/v1/admin/group_device/name?name=#{group.last_name[0..3]}&type=Group"
+ get "/api/v1/admin_user/listUsers/byname?name=#{group.last_name[0..3]}&type=Group"
end
it 'returns the right http status' do
@@ -66,7 +66,35 @@
describe 'with person type' do
before do
- get "/api/v1/admin/group_device/name?name=#{person.last_name[0..3]}&type=Person"
+ get "/api/v1/admin_user/listUsers/byname?name=#{person.last_name[0..3]}&type=Person"
+ end
+
+ it 'returns the right http status' do
+ expect(response).to have_http_status(:ok)
+ end
+
+ it 'returns a response with an array of people' do
+ expect(parsed_json_response['users']).to include(person_obj)
+ end
+ end
+
+ describe 'with person and group type' do
+ before do
+ get "/api/v1/admin_user/listUsers/byname?name=#{person.last_name[0..3]}&type=Person,Group"
+ end
+
+ it 'returns the right http status' do
+ expect(response).to have_http_status(:ok)
+ end
+
+ it 'returns a response with an array of people' do
+ expect(parsed_json_response['users']).to include(person_obj)
+ end
+ end
+
+ describe 'with no type' do
+ before do
+ get "/api/v1/admin_user/listUsers/byname?name=#{person.last_name[0..3]}"
end
it 'returns the right http status' do
diff --git a/spec/api/chemotion/attachment_api_spec.rb b/spec/api/chemotion/attachment_api_spec.rb
index fc8478ca99..0545c3cc47 100644
--- a/spec/api/chemotion/attachment_api_spec.rb
+++ b/spec/api/chemotion/attachment_api_spec.rb
@@ -22,6 +22,9 @@
'filesize' => attachment.filesize,
'identifier' => attachment.identifier,
'thumb' => attachment.thumb,
+ 'thumbnail' => attachment.thumb ? Base64.encode64(attachment.read_thumbnail) : nil,
+ 'created_at' => kind_of(String),
+ 'updated_at' => kind_of(String),
},
}
end
@@ -67,7 +70,7 @@
end
it 'returns the deleted attachment' do
- expect(parsed_json_response).to eq(expected_response)
+ expect(parsed_json_response).to include(expected_response)
end
it 'deletes the attachment on database', :enable_usecases_attachments_delete do
@@ -116,7 +119,7 @@
end
it 'returns the deleted attachment' do
- expect(parsed_json_response).to eq(expected_response)
+ expect(parsed_json_response).to include(expected_response)
end
it 'unlinks the attachment from container', :enable_usecases_attachments_unlink do
@@ -428,7 +431,40 @@
end
describe 'POST /api/v1/attachments/regenerate_spectrum' do
- pending 'not yet implemented'
+ let(:user) { create(:person) }
+ let(:container) { create(:container, containable: user) }
+ let(:original_attachment) { create(:attachment, :with_spectra_file_failure, attachable: container) }
+ let(:generated_attachment) { create(:attachment, :with_spectra_file, attachable: container) }
+ let(:spectrum_params) { { original: [], generated: [] } }
+
+ let(:execute_request) { post '/api/v1/attachments/regenerate_spectrum', params: spectrum_params }
+
+ context 'when regenerate without any file content' do
+ before do
+ execute_request
+ end
+
+ it 'returns statuscode 201' do
+ expect(response).to have_http_status(:created)
+ end
+ end
+
+ context 'when regenerate with file id' do
+ before do
+ spectrum_params[:original] = [original_attachment.id]
+ spectrum_params[:generated] = [generated_attachment.id]
+ execute_request
+ end
+
+ it 'returns statuscode 201' do
+ expect(response).to have_http_status(:created)
+ end
+
+ it 'old files have been deleted' do
+ atts = Attachment.where(filename: original_attachment.filename)
+ expect(atts.length).to eq(1)
+ end
+ end
end
describe 'POST /api/v1/attachments/save_spectrum' do
diff --git a/spec/api/chemotion/cell_line_api_spec.rb b/spec/api/chemotion/cell_line_api_spec.rb
new file mode 100644
index 0000000000..f46b2246c9
--- /dev/null
+++ b/spec/api/chemotion/cell_line_api_spec.rb
@@ -0,0 +1,253 @@
+# frozen_string_literal: true
+
+# rubocop:disable RSpec/LetSetup, RSpec/NestedGroups
+
+require 'rails_helper'
+
+describe Chemotion::CellLineAPI do
+ include_context 'api request authorization context'
+
+ describe 'GET /api/v1/cell_lines/' do
+ let(:collection) { create(:collection) }
+ let!(:user) { create(:user, collections: [collection]) }
+ let!(:cell_line) { create(:cellline_sample, collections: [collection]) }
+ let!(:cell_line2) do
+ create(:cellline_sample,
+ collections: [collection],
+ created_at: DateTime.parse('2000-01-01'),
+ updated_at: DateTime.parse('2010-01-01'))
+ end
+
+ let(:params) { { collection_id: collection.id } }
+
+ context 'when collection is accessable and got 2 cell lines' do
+ context 'when fetching by id without restrictions' do
+ before do
+ get '/api/v1/cell_lines/', params: params
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns two cell lines' do
+ expect(parsed_json_response['cell_lines'].count).to be 2
+ end
+ end
+
+ context 'when fetching by id with created at restriction (from_date)' do
+ let(:params) do
+ { collection_id: collection.id,
+ from_date: DateTime.parse('2022-01-01').to_i,
+ filter_created_at: true }
+ end
+
+ before do
+ get '/api/v1/cell_lines/', params: params
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns one cell line' do
+ expect(parsed_json_response['cell_lines'].count).to be 1
+ expect(parsed_json_response['cell_lines'].first['id']).to be cell_line.id
+ end
+ end
+
+ context 'when fetching by id with created at restriction (to_date)' do
+ let(:params) do
+ { collection_id: collection.id,
+ to_date: DateTime.parse('2022-01-01').to_i,
+ filter_created_at: true }
+ end
+
+ before do
+ get '/api/v1/cell_lines/', params: params
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns one cell line' do
+ expect(parsed_json_response['cell_lines'].count).to be 1
+ expect(parsed_json_response['cell_lines'].first['id']).to be cell_line2.id
+ end
+ end
+
+ context 'when fetching by id with updated_at restriction (from_date)' do
+ let(:params) do
+ { collection_id: collection.id,
+ from_date: DateTime.parse('2011-01-01').to_i,
+ filter_created_at: false }
+ end
+
+ before do
+ get '/api/v1/cell_lines/', params: params
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns one cell line' do
+ expect(parsed_json_response['cell_lines'].count).to be 1
+ expect(parsed_json_response['cell_lines'].first['id']).to be cell_line.id
+ end
+ end
+
+ context 'when fetching by id with updated_at restriction (to_date)' do
+ let(:params) do
+ { collection_id: collection.id,
+ to_date: DateTime.parse('2009-01-01').to_i,
+ filter_created_at: false }
+ end
+
+ before do
+ get '/api/v1/cell_lines/', params: params
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns no cell line' do
+ expect(parsed_json_response['cell_lines'].count).to be 0
+ end
+ end
+ end
+ end
+
+ describe 'GET /api/v1/cell_lines/{:id}' do
+ let(:cell_line) { create(:cellline_sample, collections: [collection]) }
+ let(:user) { create(:user, collections: [collection]) }
+ let(:collection) { create(:collection) }
+
+ context 'when cell line exists' do
+ before do
+ get "/api/v1/cell_lines/#{cell_line.id}"
+ end
+
+ it 'returns correct http status 200' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns correct cell line' do
+ expect(parsed_json_response['amount']).to be 999
+ expect(parsed_json_response['passage']).to be 10
+ end
+ end
+
+ context 'when cell does not line exist' do
+ before do
+ get '/api/v1/cell_lines/-1'
+ end
+
+ it 'returns correct http status 400' do
+ expect(response).to have_http_status :bad_request
+ end
+
+ it 'correct error message' do
+ expect(parsed_json_response['error']).to eq 'id not valid'
+ end
+ end
+ end
+
+ describe 'POST /api/v1/cell_lines/' do
+ context 'with correct parameter' do
+ let(:collection) { Collection.first }
+ let(:params) do
+ {
+ organism: 'something',
+ tissue: 'another',
+ amount: 100,
+ passage: 200,
+ disease: 'disease',
+ material_names: '[sd]',
+ biosafety_level: 'S1',
+ source: 'IPB',
+ unit: 'g',
+ collection_id: collection.id,
+ container: {},
+ }
+ end
+
+ before do
+ post '/api/v1/cell_lines/', params: params, as: :json
+ end
+
+ it 'returns correct status code 201' do
+ expect(response).to have_http_status :created
+ end
+
+ it 'returns correct representation of saved cell line sample' do # rubocop:disable RSpec/MultipleExpectations
+ expect(parsed_json_response['amount']).to be 100
+ expect(parsed_json_response['passage']).to be 200
+ expect(parsed_json_response['contamination']).to be_nil
+ expect(parsed_json_response['source']).to be_nil
+ expect(parsed_json_response['growth_medium']).to be_nil
+ expect(parsed_json_response['name']).to be_nil
+ expect(parsed_json_response['description']).to be_nil
+ expect(parsed_json_response['unit']).to eq 'g'
+ expect(parsed_json_response['cellline_material']['name']).to eq '[sd]'
+ expect(parsed_json_response['cellline_material']['cell_type']).to be_nil
+ expect(parsed_json_response['cellline_material']['organism']).to eq 'something'
+ expect(parsed_json_response['cellline_material']['tissue']).to eq 'another'
+ expect(parsed_json_response['cellline_material']['disease']).to eq 'disease'
+ expect(parsed_json_response['cellline_material']['biosafety_level']).to eq 'S1'
+ end
+ end
+
+ context 'with incorrect parameter' do
+ let(:collection) { Collection.first }
+ let(:params) do
+ {
+ passage: 200,
+ disease: 'disease',
+ material_names: '[sd]',
+ biosafety_level: 'S1',
+ collection_id: collection.id,
+ }
+ end
+
+ before do
+ post '/api/v1/cell_lines/', params: params, as: :json
+ end
+
+ it 'returns error status code 400' do
+ expect(response).to have_http_status :bad_request
+ end
+ end
+ end
+
+ describe 'GET /api/v1/cell_lines/material' do
+ context 'when material does not exist' do
+ before do
+ get '/api/v1/cell_lines/material/-1'
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :unauthorized
+ end
+ end
+
+ context 'when material exists' do
+ let(:material) { create(:cellline_material) }
+
+ before do
+ get "/api/v1/cell_lines/material/#{material.id}"
+ end
+
+ it 'returns correct response code' do
+ expect(response).to have_http_status :ok
+ end
+
+ it 'returns correct material' do
+ expect(parsed_json_response['id']).to be material.id
+ end
+ end
+ end
+end
+# rubocop:enable RSpec/LetSetup, RSpec/NestedGroups
diff --git a/spec/api/chemotion/comment_api_spec.rb b/spec/api/chemotion/comment_api_spec.rb
new file mode 100644
index 0000000000..3ed5bdbefd
--- /dev/null
+++ b/spec/api/chemotion/comment_api_spec.rb
@@ -0,0 +1,448 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.shared_examples 'an unauthorized response' do
+ it 'returns 401 status code' do
+ expect(response).to have_http_status(:unauthorized)
+ end
+end
+
+describe Chemotion::CommentAPI do
+ let!(:unauthorized_user) { create(:person) }
+ let!(:authorized_user) { create(:person) }
+ let!(:other_user) { create(:person) }
+ let(:group) do
+ create(:group, first_name: 'Group', users: [authorized_user, other_user], last_name: 'One Two',
+ name_abbreviation: 'G1_2x')
+ end
+
+ let!(:unshared_collection) do
+ create(:collection, user_id: authorized_user.id, is_shared: false, is_locked: false, permission_level: 0,
+ label: "authorized_user's unshared collection")
+ end
+ let!(:shared_collection) do
+ create(:collection, user_id: other_user.id, shared_by_id: authorized_user.id, is_shared: true, is_locked: true,
+ permission_level: 0, label: 'shared by authorized_user')
+ end
+ let(:shared_collection_to_group) do
+ create(:collection, user_id: group.id, is_shared: true, shared_by_id: authorized_user.id, is_locked: true,
+ permission_level: 0, label: 'shared by authorized_user to group')
+ end
+ let(:sync_collection) do
+ create(:collection, user_id: authorized_user.id, is_shared: false, is_synchronized: true,
+ label: 'synchronized by authorized_user')
+ end
+
+ let(:sync_collections_user) do
+ create(:sync_collections_user, collection_id: sync_collection.id, user_id: other_user.id, permission_level: 0,
+ shared_by_id: authorized_user.id, fake_ancestry: sync_collection.id.to_s)
+ end
+
+ let!(:unshared_sample) { create(:sample, name: 'Unshared sample', collections: [unshared_collection]) }
+ let!(:shared_sample) { create(:sample, collections: [unshared_collection, shared_collection]) }
+ let!(:shared_sample_for_group) { create(:sample, collections: [unshared_collection, shared_collection_to_group]) }
+ let!(:sync_sample) { create(:sample, collections: [unshared_collection, sync_collection]) }
+
+ let!(:unshared_reaction) { create(:reaction, name: 'Unshared reaction', collections: [unshared_collection]) }
+ let!(:shared_reaction) { create(:reaction, collections: [unshared_collection, shared_collection]) }
+
+ let(:comment_of_unshared_sample) do
+ create(:comment, content: 'test comment for unshared_sample', commentable_id: unshared_sample.id,
+ commentable_type: 'Sample', section: Comment.sample_sections[:properties],
+ created_by: authorized_user.id)
+ end
+ let(:comment_of_shared_sample) do
+ create(:comment, content: 'test comment for shared_sample', commentable_id: shared_sample.id,
+ commentable_type: 'Sample', section: Comment.sample_sections[:properties],
+ created_by: authorized_user.id)
+ end
+ let(:comment_of_shared_sample1) do
+ create(:comment, content: 'test comment for shared_sample by other user', commentable_id: shared_sample.id,
+ commentable_type: 'Sample', section: Comment.sample_sections[:properties],
+ created_by: other_user.id)
+ end
+ let(:comment_of_shared_sample_for_group) do
+ create(:comment, content: 'test comment for shared_sample for group', commentable_id: shared_sample_for_group.id,
+ commentable_type: 'Sample', section: Comment.sample_sections[:properties],
+ created_by: authorized_user.id)
+ end
+ let(:comment_of_sync_sample) do
+ create(:comment, content: 'test comment for sync_sample', commentable_id: sync_sample.id,
+ commentable_type: 'Sample', section: Comment.sample_sections[:properties],
+ created_by: authorized_user.id)
+ end
+
+ let(:comment_of_unshared_reaction) do
+ create(:comment, content: 'test comment for unshared reaction', commentable: unshared_reaction,
+ commentable_type: 'Reaction', section: Comment.reaction_sections[:scheme],
+ created_by: authorized_user.id)
+ end
+ let(:comment_of_shared_reaction) do
+ create(:comment, content: 'test comment for shared reaction', commentable: shared_reaction,
+ commentable_type: 'Reaction', section: Comment.reaction_sections[:scheme],
+ created_by: authorized_user.id)
+ end
+ let(:comment_of_shared_reaction1) do
+ create(:comment, content: 'test comment for shared reaction by other user', commentable: shared_reaction,
+ commentable_type: 'Reaction', section: Comment.reaction_sections[:scheme],
+ created_by: other_user.id)
+ end
+
+ let(:warden_authentication_instance) { instance_double(WardenAuthentication) }
+
+ context 'when the user is unauthorized' do
+ before do
+ allow(WardenAuthentication).to receive(:new).and_return(warden_authentication_instance)
+ allow(warden_authentication_instance).to receive(:current_user).and_return(unauthorized_user)
+ end
+
+ describe 'GET /api/v1/comments/:id' do
+ context 'when the comment element is not shared' do
+ before do
+ get "/api/v1/comments/#{comment_of_unshared_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ context 'when the comment element shared but not with the logged in user' do
+ before do
+ get "/api/v1/comments/#{comment_of_shared_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ context 'when the comment is shared with another group' do
+ before do
+ get "/api/v1/comments/#{comment_of_shared_sample_for_group.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ context 'when the comment is from an unaccesible synchronized collection' do
+ before do
+ get "/api/v1/comments/#{comment_of_sync_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+ end
+
+ describe 'PUT /api/v1/comments/:id' do
+ context 'when the comment element is not shared' do
+ before do
+ put "/api/v1/comments/#{comment_of_unshared_sample.id}", params: { content: 'test comment' }
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ context 'when the comment element shared but not with the logged in user' do
+ before do
+ put "/api/v1/comments/#{comment_of_shared_sample.id}", params: { content: 'test comment' }
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+ end
+
+ describe 'DELETE /api/v1/comments/:id' do
+ context 'when the comment element is not shared' do
+ before do
+ delete "/api/v1/comments/#{comment_of_unshared_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ context 'when the comment element shared but not with the logged in user' do
+ before do
+ delete "/api/v1/comments/#{comment_of_shared_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+ end
+ end
+
+ context 'when user is authorized' do
+ before do
+ allow(WardenAuthentication).to receive(:new).and_return(warden_authentication_instance)
+ allow(warden_authentication_instance).to receive(:current_user).and_return(authorized_user)
+ end
+
+ describe 'GET /api/v1/comments/:id' do
+ it 'returns comment data' do
+ get "/api/v1/comments/#{comment_of_unshared_sample.id}"
+
+ comment_data = JSON.parse(response.body)['comment']&.symbolize_keys
+ expect(comment_data[:id]).to eq(comment_of_unshared_sample.id)
+ end
+
+ it 'returns comment data when the element is shared with group' do
+ get "/api/v1/comments/#{comment_of_shared_sample_for_group.id}"
+
+ comment_data = JSON.parse(response.body)['comment']&.symbolize_keys
+ expect(comment_data[:id]).to eq(comment_of_shared_sample_for_group.id)
+ end
+
+ it 'returns comment data when the element is from synchronized collection' do
+ get "/api/v1/comments/#{comment_of_sync_sample.id}"
+
+ comment_data = JSON.parse(response.body)['comment']&.symbolize_keys
+ expect(comment_data[:id]).to eq(comment_of_sync_sample.id)
+ end
+ end
+
+ describe 'POST /api/v1/comments' do
+ context 'with sample' do
+ let(:params) do
+ {
+ content: 'test comment sample',
+ commentable_id: shared_sample.id,
+ commentable_type: 'Sample',
+ section: Comment.sample_sections[:properties],
+ }
+ end
+
+ it 'creates a new comment associated with the sample' do
+ post '/api/v1/comments', params: params
+
+ comment = Comment.find_by(content: 'test comment sample')
+ expect(comment).not_to be_nil
+ expect(comment.commentable_id).to eq(shared_sample.id)
+ end
+ end
+
+ context 'with reaction' do
+ let(:params) do
+ {
+ content: 'test comment reaction',
+ commentable_id: shared_reaction.id,
+ commentable_type: 'Reaction',
+ section: Comment.reaction_sections[:scheme],
+ }
+ end
+
+ it 'creates a new comment associated with the reaction' do
+ post '/api/v1/comments', params: params
+
+ comment = Comment.find_by(content: 'test comment reaction')
+ expect(comment).not_to be_nil
+ expect(comment.commentable_id).to eq(shared_reaction.id)
+ end
+ end
+ end
+
+ describe 'PUT /api/v1/comments/:id' do
+ context 'with own comment' do
+ it "updates comment's content" do
+ put "/api/v1/comments/#{comment_of_shared_sample.id}", params: { content: 'updated test comment' }
+
+ expect do
+ comment_of_shared_sample.reload
+ end.to change(comment_of_shared_sample, :content).to('updated test comment')
+ end
+ end
+
+ context 'with sample' do
+ let(:params) do
+ {
+ content: 'update test comment sample',
+ commentable_id: shared_sample.id,
+ commentable_type: 'Sample',
+ }
+ end
+
+ it "updates comment's content and association" do
+ put "/api/v1/comments/#{comment_of_shared_sample.id}", params: params
+
+ comment = Comment.find(comment_of_shared_sample.id)
+ expect([comment.content, comment.commentable_id,
+ comment.commentable_type]).to eq(['update test comment sample', shared_sample.id, 'Sample'])
+ end
+ end
+
+ context 'with reaction' do
+ let(:params) do
+ {
+ content: 'update test comment reaction',
+ commentable_id: shared_reaction.id,
+ commentable_type: 'Reaction',
+ section: Comment.reaction_sections[:scheme],
+ }
+ end
+
+ it "updates comment's content and association" do
+ put "/api/v1/comments/#{comment_of_shared_reaction.id}", params: params
+
+ comment = Comment.find(comment_of_shared_reaction.id)
+ expect([comment.content, comment.commentable_id,
+ comment.commentable_type]).to eq(['update test comment reaction', shared_reaction.id, 'Reaction'])
+ end
+ end
+ end
+
+ describe 'DELETE /api/v1/comments/:id' do
+ it 'deletes own comment' do
+ expect do
+ delete "/api/v1/comments/#{comment_of_shared_reaction.id}"
+ end.to change { Comment.exists?(comment_of_shared_reaction.id) }.from(true).to(false)
+ end
+
+ context 'when deletes other user comments in own collection' do
+ before do
+ delete "/api/v1/comments/#{comment_of_shared_reaction1.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+ end
+ end
+
+ context 'when user has access to a shared/synchronized collection owned by another user' do
+ before do
+ allow(WardenAuthentication).to receive(:new).and_return(warden_authentication_instance)
+ allow(warden_authentication_instance).to receive(:current_user).and_return(other_user)
+ end
+
+ describe 'GET /api/v1/comments/:id' do
+ context 'when the comment is from another user' do
+ before do
+ get "/api/v1/comments/#{comment_of_unshared_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ it 'returns comment data' do
+ get "/api/v1/comments/#{comment_of_shared_sample.id}"
+
+ comment_data = JSON.parse(response.body)['comment']&.symbolize_keys
+ expect(comment_data[:id]).to eq(comment_of_shared_sample.id)
+ end
+
+ it 'returns comment data when the element is shared with group' do
+ get "/api/v1/comments/#{comment_of_shared_sample_for_group.id}"
+
+ comment_data = JSON.parse(response.body)['comment']&.symbolize_keys
+ expect(comment_data[:id]).to eq(comment_of_shared_sample_for_group.id)
+ end
+ end
+
+ describe 'POST /api/v1/comments' do
+ context 'with content' do
+ let(:params) do
+ {
+ content: 'test comment',
+ commentable_id: shared_reaction.id,
+ commentable_type: 'Reaction',
+ section: Comment.reaction_sections[:scheme],
+ }
+ end
+
+ before do
+ post '/api/v1/comments', params: params
+ end
+
+ it 'creates a new comment (on accessible element)' do
+ comment = Comment.find_by(content: 'test comment')
+ expect(comment).not_to be_nil
+ end
+ end
+
+ context 'with sample' do
+ let(:params) do
+ {
+ content: 'test comment sample',
+ commentable_id: shared_sample.id,
+ commentable_type: 'Sample',
+ section: Comment.sample_sections[:properties],
+ }
+ end
+
+ it 'creates a new comment associated with the sample' do
+ post '/api/v1/comments', params: params
+
+ comment = Comment.find_by(content: 'test comment sample')
+ expect(comment).not_to be_nil
+ expect(comment.commentable_id).to eq(shared_sample.id)
+ end
+ end
+
+ context 'with reaction' do
+ let(:params) do
+ {
+ content: 'test comment reaction',
+ commentable_id: shared_reaction.id,
+ commentable_type: 'Reaction',
+ section: Comment.reaction_sections[:scheme],
+ }
+ end
+
+ it 'creates a new comment associated with the reaction' do
+ post '/api/v1/comments', params: params
+
+ comment = Comment.find_by(content: 'test comment reaction')
+ expect(comment).not_to be_nil
+ expect(comment.commentable_id).to eq(shared_reaction.id)
+ end
+ end
+ end
+
+ describe 'PUT /api/v1/comments/:id' do
+ context 'when the comment is from another user' do
+ before do
+ put "/api/v1/comments/#{comment_of_shared_sample.id}", params: { content: 'update test comment' }
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ it 'updates own comment' do
+ put "/api/v1/comments/#{comment_of_shared_sample1.id}", params: { content: 'update test comment' }
+
+ expect do
+ comment_of_shared_sample1.reload
+ end.to change(comment_of_shared_sample1, :content).to('update test comment')
+ end
+
+ it 'resolves comment from another user' do
+ put "/api/v1/comments/#{comment_of_shared_sample.id}", params: { status: 'Resolved',
+ content: comment_of_shared_sample.content }
+
+ expect do
+ comment_of_shared_sample.reload
+ end.to change(comment_of_shared_sample, :status).to('Resolved')
+ end
+
+ it 'resolves own comment' do
+ put "/api/v1/comments/#{comment_of_shared_sample1.id}", params: { status: 'Resolved',
+ content: comment_of_shared_sample1.content }
+
+ expect do
+ comment_of_shared_sample1.reload
+ end.to change(comment_of_shared_sample1, :status).to('Resolved')
+ end
+ end
+
+ describe 'DELETE /api/v1/comments/:id' do
+ context 'when the comment is from another user' do
+ before do
+ delete "/api/v1/comments/#{comment_of_shared_sample.id}"
+ end
+
+ it_behaves_like 'an unauthorized response'
+ end
+
+ it 'deletes own comment' do
+ expect do
+ delete "/api/v1/comments/#{comment_of_shared_sample1.id}"
+ end.to change { Comment.exists?(comment_of_shared_sample1.id) }.from(true).to(false)
+ end
+ end
+ end
+end
diff --git a/spec/api/chemotion/generic_dataset_api_spec.rb b/spec/api/chemotion/generic_dataset_api_spec.rb
new file mode 100644
index 0000000000..53ea8b639a
--- /dev/null
+++ b/spec/api/chemotion/generic_dataset_api_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+# rubocop:disable RSpec/NestedGroups
+describe Labimotion::GenericDatasetAPI do
+ context 'with authorized user' do
+ let(:user) { create(:person) }
+
+ before do
+ allow_any_instance_of(WardenAuthentication).to receive(:current_user).and_return(user)
+ end
+
+ describe 'GET /api/v1/generic_dataset/klasses' do
+ it 'fetch dataset klasses' do
+ get '/api/v1/generic_dataset/klasses'
+ body = JSON.parse(response.body)
+
+ expect(body['klass']).to be_an(Array)
+ end
+
+ end
+ end
+end
+# rubocop:enable RSpec/NestedGroups
diff --git a/spec/api/chemotion/generic_element_api_spec.rb b/spec/api/chemotion/generic_element_api_spec.rb
index 915ab46ed0..fe24879388 100644
--- a/spec/api/chemotion/generic_element_api_spec.rb
+++ b/spec/api/chemotion/generic_element_api_spec.rb
@@ -2,7 +2,8 @@
require 'rails_helper'
-describe Chemotion::GenericElementAPI do
+# rubocop:disable RSpec/NestedGroups
+describe Labimotion::GenericElementAPI do
context 'with authorized user' do
let(:user) { create(:person) }
@@ -17,6 +18,139 @@
expect(body['generic_elements']).to be_an(Array)
end
+
+ context 'with sort_column' do
+ let(:collection) { create(:collection, user: user, is_shared: false) }
+ let(:element_klass) { create(:element_klass) }
+ let(:element1) do
+ properties = element_klass.properties_release
+ properties['layers']['gen']['fields'][0]['value'] = nil # type field
+ properties['layers']['gen']['fields'][1]['value'] = 'a' # class field
+ properties['layers']['gen']['fields'][2]['value'] = 'b' # mode field
+
+ create(
+ :element,
+ element_klass: element_klass,
+ properties: properties,
+ creator: user,
+ updated_at: Time.current,
+ collections: [collection],
+ )
+ end
+ let(:element2) do
+ properties = element_klass.properties_release
+ properties['layers']['gen']['fields'][0]['value'] = 'c' # type field
+ properties['layers']['gen']['fields'][1]['value'] = nil # class field
+ properties['layers']['gen']['fields'][2]['value'] = 'a' # mode field
+
+ create(
+ :element,
+ element_klass: element_klass,
+ properties: properties,
+ creator: user,
+ updated_at: 1.minute.ago,
+ collections: [collection],
+ )
+ end
+ let(:element3) do
+ properties = element_klass.properties_release
+ properties['layers']['gen']['fields'][0]['value'] = 'b' # type field
+ properties['layers']['gen']['fields'][1]['value'] = 'c' # class field
+ properties['layers']['gen']['fields'][2]['value'] = nil # mode field
+
+ create(
+ :element,
+ element_klass: element_klass,
+ properties: properties,
+ creator: user,
+ updated_at: 1.minute.from_now,
+ collections: [collection],
+ )
+ end
+
+ before do
+ element1
+ element2
+ element3
+ end
+
+ it 'returns sorted elements per default by updated_at' do
+ get '/api/v1/generic_elements', params: { collection_id: collection.id, el_type: element_klass.name }
+
+ expect(JSON.parse(response.body)['generic_elements'].pluck('id')).to eq(
+ [
+ element3.id,
+ element1.id,
+ element2.id,
+ ],
+ )
+ end
+
+ it 'returns sorted elements by gen.type' do
+ get '/api/v1/generic_elements', params: {
+ collection_id: collection.id,
+ el_type: element_klass.name,
+ sort_column: 'gen.type',
+ }
+
+ expect(JSON.parse(response.body)['generic_elements'].pluck('id')).to eq(
+ [
+ element1.id, # null first
+ element3.id, # b
+ element2.id, # c
+ ],
+ )
+ end
+
+ it 'returns sorted elements by gen.class' do
+ get '/api/v1/generic_elements', params: {
+ collection_id: collection.id,
+ el_type: element_klass.name,
+ sort_column: 'gen.class',
+ }
+
+ expect(JSON.parse(response.body)['generic_elements'].pluck('id')).to eq(
+ [
+ element2.id, # null first
+ element1.id, # a
+ element3.id, # b
+ ],
+ )
+ end
+
+ it 'returns sorted elements by gen.mode' do
+ get '/api/v1/generic_elements', params: {
+ collection_id: collection.id,
+ el_type: element_klass.name,
+ sort_column: 'gen.mode',
+ }
+
+ expect(JSON.parse(response.body)['generic_elements'].pluck('id')).to eq(
+ [
+ element3.id, # null first
+ element2.id, # a
+ element1.id, # b
+ ],
+ )
+ end
+
+ it 'returns sorted elements by updated_at for missing field' do
+ get '/api/v1/generic_elements', params: {
+ collection_id: collection.id,
+ el_type: element_klass.name,
+ sort_column: 'gen.missing_key',
+ }
+
+ expect(JSON.parse(response.body)['generic_elements'].pluck('id')).to eq(
+ [
+ element3.id,
+ element1.id,
+ element2.id,
+ ],
+ )
+ end
+ end
end
end
end
+# rubocop:enable RSpec/NestedGroups
diff --git a/spec/api/chemotion/inventory_api_spec.rb b/spec/api/chemotion/inventory_api_spec.rb
new file mode 100644
index 0000000000..e7033369a0
--- /dev/null
+++ b/spec/api/chemotion/inventory_api_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Chemotion::InventoryAPI do
+ include_context 'api request authorization context'
+
+ let(:collection) { Collection.find_by(user_id: user.id) }
+
+ describe 'PUT /api/v1/inventory/update_inventory_label' do
+ let(:params) do
+ {
+ 'prefix' => 'BNC',
+ 'name' => 'Bräse North Camp',
+ 'counter' => 0,
+ 'collection_ids' => [collection.id],
+ }
+ end
+
+ let(:expected_response) do
+ Inventory.create_or_update_inventory_label(
+ 'BNC',
+ 'Bräse North Camp',
+ 0,
+ [collection.id],
+ user.id,
+ ).to_json
+ end
+
+ before do
+ put '/api/v1/inventory/update_inventory_label', params: params
+ end
+
+ it 'updates sample inventory label for user' do
+ expect(response).to have_http_status(:ok)
+ expect(response.body).to eq(expected_response)
+ end
+ end
+
+ describe 'GET user_inventory_collections' do
+ before do
+ get '/api/v1/inventory/user_inventory_collections'
+ end
+
+ let(:expected_response) do
+ { inventory_collections: Collection.inventory_collections(collection.user_id) }.to_json
+ end
+
+ it 'fetch own collections for user' do
+ json_response = JSON.parse(response.body)
+ expect(json_response).to have_key('inventory_collections')
+ end
+ end
+end
diff --git a/spec/api/chemotion/reaction_api_spec.rb b/spec/api/chemotion/reaction_api_spec.rb
index d34b355b28..e4fc14ded7 100644
--- a/spec/api/chemotion/reaction_api_spec.rb
+++ b/spec/api/chemotion/reaction_api_spec.rb
@@ -47,7 +47,7 @@
it 'returns serialized reaction' do
reactions = JSON.parse(response.body)['reactions']
- expect(reactions.map { |reaction| reaction['id'] }).to eq([r2.id, r1.id])
+ expect(reactions.pluck('id')).to eq([r2.id, r1.id])
end
end
@@ -72,7 +72,7 @@
it 'returns serialized reaction' do
reactions = JSON.parse(response.body)['reactions']
- expect(reactions.map { |reaction| reaction['id'] }).to eq([r2.id, r1.id])
+ expect(reactions.pluck('id')).to eq([r2.id, r1.id])
end
end
@@ -86,6 +86,100 @@
expect(reactions.size).to be(0)
end
end
+
+ context 'with sort_column' do
+ let(:collection) { create(:collection, user: user, is_shared: false) }
+ let(:reaction1) do
+ create(
+ :reaction,
+ updated_at: Time.current,
+ rxno: 'A',
+ rinchi_short_key: 'C',
+ collections: [collection],
+ )
+ end
+ let(:reaction2) do
+ create(
+ :reaction,
+ updated_at: 1.minute.ago,
+ rxno: 'C',
+ rinchi_short_key: 'B',
+ collections: [collection],
+ )
+ end
+ let(:reaction3) do
+ create(
+ :reaction,
+ updated_at: 1.minute.from_now,
+ rxno: 'B',
+ rinchi_short_key: 'A',
+ collections: [collection],
+ )
+ end
+
+ before do
+ Reaction.skip_callback(:save, :before, :generate_rinchis)
+ reaction1
+ reaction2
+ reaction3
+ Reaction.set_callback(:save, :before, :generate_rinchis)
+ end
+
+ it 'returns sorted reactions per default by short_label' do
+ get '/api/v1/reactions', params: { collection_id: collection.id }
+
+ expect(JSON.parse(response.body)['reactions'].pluck('id')).to eq(
+ [
+ reaction3.id,
+ reaction2.id,
+ reaction1.id,
+ ],
+ )
+ end
+
+ it 'returns sorted reactions by updated_at' do
+ get '/api/v1/reactions', params: { collection_id: collection.id, sort_column: 'created_at' }
+
+ expect(JSON.parse(response.body)['reactions'].pluck('id')).to eq(
+ [
+ reaction3.id,
+ reaction2.id,
+ reaction1.id,
+ ],
+ )
+ end
+
+ it 'returns sorted reactions by rxno' do
+ get '/api/v1/reactions', params: { collection_id: collection.id, sort_column: 'rxno' }
+
+ expect(JSON.parse(response.body)['reactions'].pluck('id')).to eq(
+ [
+ reaction1.id,
+ reaction3.id,
+ reaction2.id,
+ ],
+ )
+ end
+
+ it 'returns sorted reactions by rinchi_short_key' do
+ get '/api/v1/reactions', params: { collection_id: collection.id, sort_column: 'rinchi_short_key' }
+
+ expect(JSON.parse(response.body)['reactions'].pluck('id')).to eq(
+ [
+ reaction3.id,
+ reaction2.id,
+ reaction1.id,
+ ],
+ )
+ end
+
+ it 'gives error for invalid value for sort_column' do
+ get '/api/v1/reactions', params: { collection_id: collection.id, sort_column: 'not_allowed' }
+
+ expect(response).to have_http_status(:bad_request)
+ expect(JSON.parse(response.body)['error']).to eq('sort_column does not have a valid value')
+ end
+ end
end
describe 'GET /api/v1/reactions/:id' do
diff --git a/spec/api/chemotion/sample_api_spec.rb b/spec/api/chemotion/sample_api_spec.rb
index a6ecdff9ba..ab9c394ffb 100644
--- a/spec/api/chemotion/sample_api_spec.rb
+++ b/spec/api/chemotion/sample_api_spec.rb
@@ -31,9 +31,9 @@
all: false,
included_ids: [sample_1.id, sample_2.id],
excluded_ids: [],
- collection_id: collection.id
+ collection_id: collection.id,
},
- limit: limit
+ limit: limit,
}
end
@@ -49,8 +49,8 @@
all: false,
included_ids: [sample_1.id, sample_2.id],
excluded_ids: [],
- collection_id: collection.id
- }
+ collection_id: collection.id,
+ },
}
end
@@ -70,10 +70,10 @@
sample: {
all: true,
included_ids: [],
- excluded_ids: []
+ excluded_ids: [],
},
- currentCollectionId: collection.id
- }
+ currentCollectionId: collection.id,
+ },
}
end
@@ -96,18 +96,18 @@
]
sample1_attributes = s1.attributes.except(*except_attr)
subsample1_attributes = s3.attributes.except(*except_attr)
- expect(sample1_attributes).to eq (subsample1_attributes)
+ expect(sample1_attributes).to eq(subsample1_attributes)
expect(s3.name).to eq(s1.name)
expect(s3.external_label).to eq(s1.external_label)
- expect(s3.short_label).to eq(s1.short_label + '-' + s1.children.count.to_s)
+ expect(s3.short_label).to eq("#{s1.short_label}-#{s1.children.count}")
sample2_attributes = s2.attributes.except(*except_attr)
subsample2_attributes = s4.attributes.except(*except_attr)
- expect(sample2_attributes).to eq (subsample2_attributes)
+ expect(sample2_attributes).to eq(subsample2_attributes)
expect(s4.name).to eq(s2.name)
expect(s4.external_label).to eq(s2.external_label)
- expect(s4.short_label).to eq(s2.short_label + '-' + s2.children.count.to_s)
+ expect(s4.short_label).to eq("#{s2.short_label}-#{s2.children.count}")
expect(s1.id).not_to eq(s3.id)
expect(s2.id).not_to eq(s4.id)
@@ -129,8 +129,8 @@
params: params,
headers: {
'HTTP_ACCEPT' => '*/*',
- 'CONTENT_TYPE' => 'multipart/form-data'
- }
+ 'CONTENT_TYPE' => 'multipart/form-data',
+ },
)
end
@@ -138,7 +138,8 @@
let(:params) do
{
currentCollectionId: collection.id,
- file: fixture_file_upload(Rails.root.join('spec/fixtures/import_sample_data.xlsx'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+ file: fixture_file_upload(Rails.root.join('spec/fixtures/import_sample_data.xlsx'),
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'),
}
end
@@ -155,13 +156,13 @@
let(:params) do
{
currentCollectionId: collection.id,
- file: fixture_file_upload(Rails.root.join('spec/fixtures/import_sample_data.sdf'), 'chemical/x-mdl-sdfile')
+ file: fixture_file_upload(Rails.root.join('spec/fixtures/import_sample_data.sdf'), 'chemical/x-mdl-sdfile'),
}
end
it 'is able to import new samples' do
expect(
- JSON.parse(response.body)['message']
+ JSON.parse(response.body)['message'],
).to eq "This file contains 2 Molecules.\n2 Molecules processed. "
expect(JSON.parse(response.body)['sdf']).to be true
@@ -184,53 +185,53 @@
{
currentCollectionId: collection.id,
mapped_keys: {
- "description": %w[
+ description: %w[
MOLECULE_NAME
SAFETY_R_S
SMILES_STEREO
],
- "short_label": 'EMP_FORMULA_SHORT',
- "target_amount": 'AMOUNT',
- "real_amount": 'REAL_AMOUNT',
- "density": 'DENSITY_20',
- "decoupled": 'MOLECULE-LESS',
- "molarity": 'MOLARITY',
- "melting_point": 'melting_point',
- "boiling_point": 'boiling_point',
- "location": 'location',
- "external_label": 'external_label',
- "name": 'name'
+ short_label: 'EMP_FORMULA_SHORT',
+ target_amount: 'AMOUNT',
+ real_amount: 'REAL_AMOUNT',
+ density: 'DENSITY_20',
+ decoupled: 'MOLECULE-LESS',
+ molarity: 'MOLARITY',
+ melting_point: 'melting_point',
+ boiling_point: 'boiling_point',
+ location: 'location',
+ external_label: 'external_label',
+ name: 'name',
},
rows: [{
- "inchikey": 'DTHMTBUWTGVEFG-DDWIOCJRSA-N',
- "molfile": File.read(Rails.root.join('spec', 'fixtures', 'mf_with_data_01.sdf')),
- "description": "MOLECULE_NAME\n(R)-Methyl-2-amino-2-phenylacetate hydrochloride ?96%; (R)-(?)-2-Phenylglycine methyl ester hydrochloride\n\nSAFETY_R_S\nH: 319; P: 305+351+338\n\nSMILES_STEREO\n[Cl-].COC(=O)[C@H](N)c1ccccc1.[H+]\n",
- "short_label": 'C9H12ClNO2',
- "target_amount": '10 g / g',
- "real_amount": '15mg/mg',
- "density": '30',
- "decoupled": 'f',
- "molarity": '900',
- "melting_point": '[900.0,)',
- "boiling_point": '[900.0,1500.0)',
- "location": 'location',
- "external_label": 'external_label',
- "name": 'name'
- }]
+ inchikey: 'DTHMTBUWTGVEFG-DDWIOCJRSA-N',
+ molfile: Rails.root.join('spec', 'fixtures', 'mf_with_data_01.sdf').read,
+ description: "MOLECULE_NAME\n(R)-Methyl-2-amino-2-phenylacetate hydrochloride ?96%; (R)-(?)-2-Phenylglycine methyl ester hydrochloride\n\nSAFETY_R_S\nH: 319; P: 305+351+338\n\nSMILES_STEREO\n[Cl-].COC(=O)[C@H](N)c1ccccc1.[H+]\n",
+ short_label: 'C9H12ClNO2',
+ target_amount: '10 g / g',
+ real_amount: '15mg/mg',
+ density: '30',
+ decoupled: 'f',
+ molarity: '900',
+ melting_point: '900.0',
+ boiling_point: '900.0-1500.0',
+ location: 'location',
+ external_label: 'external_label',
+ name: 'name',
+ }],
}
end
it 'is able to create samples from an array of inchikeys' do
expect(
- JSON.parse(response.body)['message']
+ JSON.parse(response.body)['message'],
).to eq "This file contains 1 Molecules.\nCreated 1 sample. \nImport successful! "
expect(
- JSON.parse(response.body)['sdf']
+ JSON.parse(response.body)['sdf'],
).to be true
expect(
- JSON.parse(response.body)['status']
+ JSON.parse(response.body)['status'],
).to eq 'ok'
collection_sample = CollectionsSample.where(collection_id: collection.id)
@@ -260,47 +261,47 @@
{
currentCollectionId: collection.id,
mapped_keys: {
- "description": %w[
+ description: %w[
MOLECULE_NAME
SAFETY_R_S
SMILES_STEREO
],
- "short_label": 'EMP_FORMULA_SHORT',
- "target_amount": 'AMOUNT',
- "real_amount": 'REAL_AMOUNT',
- "density": 'DENSITY_20',
- "decoupled": 'MOLECULE-LESS'
+ short_label: 'EMP_FORMULA_SHORT',
+ target_amount: 'AMOUNT',
+ real_amount: 'REAL_AMOUNT',
+ density: 'DENSITY_20',
+ decoupled: 'MOLECULE-LESS',
},
rows: [{
- "inchikey": 'DTHMTBUWTGVEFG-DDWIOCJRSA-N',
- "molfile": File.read(Rails.root.join('spec', 'fixtures', 'mf_with_data_01.sdf')),
- "description": "MOLECULE_NAME\n(R)-Methyl-2-amino-2-phenylacetate hydrochloride ?96%; (R)-(?)-2-Phenylglycine methyl ester hydrochloride\n\nSAFETY_R_S\nH: 319; P: 305+351+338\n\nSMILES_STEREO\n[Cl-].COC(=O)[C@H](N)c1ccccc1.[H+]\n",
- "short_label": 'C9H12ClNO2',
- "target_amount": 'Test data',
- "real_amount": 'Test',
- "density": 'Test',
- "decoupled": 'f',
- "molarity": '900sdadsad',
- "melting_point": 'test900',
- "boiling_point": 'test1000',
- "location": 'location',
- "external_label": 'external_label',
- "name": 'name'
- }]
+ inchikey: 'DTHMTBUWTGVEFG-DDWIOCJRSA-N',
+ molfile: Rails.root.join('spec', 'fixtures', 'mf_with_data_01.sdf').read,
+ description: "MOLECULE_NAME\n(R)-Methyl-2-amino-2-phenylacetate hydrochloride ?96%; (R)-(?)-2-Phenylglycine methyl ester hydrochloride\n\nSAFETY_R_S\nH: 319; P: 305+351+338\n\nSMILES_STEREO\n[Cl-].COC(=O)[C@H](N)c1ccccc1.[H+]\n",
+ short_label: 'C9H12ClNO2',
+ target_amount: 'Test data',
+ real_amount: 'Test',
+ density: 'Test',
+ decoupled: 'f',
+ molarity: '900sdadsad',
+ melting_point: '900',
+ boiling_point: '1000',
+ location: 'location',
+ external_label: 'external_label',
+ name: 'name',
+ }],
}
end
it 'is able to import new samples' do
expect(
- JSON.parse(response.body)['message']
+ JSON.parse(response.body)['message'],
).to eq "This file contains 1 Molecules.\nCreated 1 sample. \nImport successful! "
expect(
- JSON.parse(response.body)['sdf']
+ JSON.parse(response.body)['sdf'],
).to be true
expect(
- JSON.parse(response.body)['status']
+ JSON.parse(response.body)['status'],
).to eq 'ok'
collection_sample = CollectionsSample.where(collection_id: collection.id)
@@ -338,20 +339,20 @@
expect(first_sample).to include(
id: sample.id,
name: sample.name,
- type: 'sample'
+ type: 'sample',
)
expect(
- first_sample[:tag]['taggable_data']['collection_labels']
+ first_sample[:tag]['taggable_data']['collection_labels'],
).to include(
'name' => personal_collection.label,
'is_shared' => false,
'id' => personal_collection.id,
'user_id' => user.id,
'shared_by_id' => personal_collection.shared_by_id,
- 'is_synchronized' => personal_collection.is_synchronized
+ 'is_synchronized' => personal_collection.is_synchronized,
)
expect(
- first_sample[:tag]['taggable_data']['analyses']
+ first_sample[:tag]['taggable_data']['analyses'],
).to include('confirmed' => { 'CHMO:0000595 | 13C nuclear magnetic resonance spectroscopy (13C NMR)' => 1 })
end
end
@@ -362,7 +363,7 @@
it 'returns samples in the right order' do
get '/api/v1/samples', params: { molecule_sort: 1 }
- expect(JSON.parse(response.body)['samples'].map { |x| x['id'] }).to eq([sample.id, sample2.id])
+ expect(JSON.parse(response.body)['samples'].pluck('id')).to eq([sample.id, sample2.id])
end
end
@@ -372,7 +373,7 @@
it 'returns samples in the right order' do
get '/api/v1/samples', params: { molecule_sort: 0 }
- expect(JSON.parse(response.body)['samples'].map { |x| x['id'] }).to eq([sample2.id, sample.id])
+ expect(JSON.parse(response.body)['samples'].pluck('id')).to eq([sample2.id, sample.id])
end
end
@@ -393,6 +394,41 @@
expect(JSON.parse(response.body)['samples'].size).to eq(0)
end
end
+
+ context 'when filtered by created at with from_date and to_date' do
+ let(:time) { Time.current }
+ let(:sample1) { create(:sample, created_at: time, collections: [personal_collection]) }
+ let(:sample2) { create(:sample, created_at: time.end_of_day, collections: [personal_collection]) }
+ let(:sample3) { create(:sample, created_at: time.beginning_of_day, collections: [personal_collection]) }
+ let(:sample4) { create(:sample, created_at: 1.day.from_now.end_of_day, collections: [personal_collection]) }
+ let(:sample5) { create(:sample, created_at: 1.day.from_now.beginning_of_day, collections: [personal_collection]) }
+ let(:sample6) { create(:sample, created_at: 1.day.ago.beginning_of_day, collections: [personal_collection]) }
+
+ it 'returns samples in range' do
+ sample1
+ sample2
+ sample3
+ sample4
+ sample5
+ sample6
+
+ get '/api/v1/samples', params: {
+ collection_id: personal_collection.id,
+ filter_created_at: true,
+ from_date: time.to_i,
+ to_date: time.to_i,
+ }
+
+ expect(JSON.parse(response.body)['samples'].pluck('id').sort).to eq(
+ [
+ sample1.id,
+ sample2.id,
+ # sample3.id, should have been included
+ sample5.id, # should have been excluded
+ ],
+ )
+ end
+ end
end
describe 'GET /api/v1/samples/:id' do
@@ -408,7 +444,7 @@
end
it 'returns 200 status code' do
- expect(response.status).to eq 200
+ expect(response).to have_http_status :ok
end
it 'returns serialized sample' do
@@ -416,8 +452,8 @@
end
it 'returns correct can_publish & can_update' do
- expect(JSON.parse(response.body)['sample']['can_update']).to eq true
- expect(JSON.parse(response.body)['sample']['can_publish']).to eq true
+ expect(JSON.parse(response.body)['sample']['can_update']).to be true
+ expect(JSON.parse(response.body)['sample']['can_publish']).to be true
end
end
@@ -433,8 +469,8 @@
let(:permission_level) { 0 }
it 'returns correct can_publish & can_update' do
- expect(JSON.parse(response.body)['sample']['can_update']).to eq false
- expect(JSON.parse(response.body)['sample']['can_publish']).to eq false
+ expect(JSON.parse(response.body)['sample']['can_update']).to be false
+ expect(JSON.parse(response.body)['sample']['can_publish']).to be false
end
end
@@ -442,8 +478,8 @@
let(:permission_level) { 1 }
it 'returns correct can_publish & can_update' do
- expect(JSON.parse(response.body)['sample']['can_update']).to eq true
- expect(JSON.parse(response.body)['sample']['can_publish']).to eq false
+ expect(JSON.parse(response.body)['sample']['can_update']).to be true
+ expect(JSON.parse(response.body)['sample']['can_publish']).to be false
end
end
@@ -451,8 +487,8 @@
let(:permission_level) { 3 }
it 'returns correct can_publish & can_update' do
- expect(JSON.parse(response.body)['sample']['can_update']).to eq true
- expect(JSON.parse(response.body)['sample']['can_publish']).to eq true
+ expect(JSON.parse(response.body)['sample']['can_update']).to be true
+ expect(JSON.parse(response.body)['sample']['can_publish']).to be true
end
end
end
@@ -462,7 +498,7 @@
it 'returns 401 unauthorized status code' do
get "/api/v1/samples/#{sample.id}"
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
@@ -473,7 +509,7 @@
let(:expected_response) do
{
'sample_id' => sample.id,
- 'collection_id' => collection.id
+ 'collection_id' => collection.id,
}
end
@@ -518,12 +554,12 @@
children: [],
is_new: true,
is_deleted: false,
- name: 'new'
+ name: 'new',
},
boiling_point_upperbound: 100.0,
boiling_point_lowerbound: nil,
melting_point_upperbound: 121.5,
- melting_point_lowerbound: nil
+ melting_point_lowerbound: nil,
}
end
@@ -538,7 +574,7 @@
let(:sample) { s1 }
it 'returns 200 status code' do
- expect(response.status).to eq 200
+ expect(response).to have_http_status :ok
end
it 'updates sample' do
@@ -553,7 +589,7 @@
let(:sample) { s2 }
it 'returns 200 status code' do
- expect(response.status).to eq 200
+ expect(response).to have_http_status :ok
end
it 'updates sample' do
@@ -578,7 +614,7 @@
solvent: '',
location: '',
molfile: '',
- is_top_secret: false
+ is_top_secret: false,
}
end
@@ -586,7 +622,7 @@
CollectionsSample.create!(sample: sample, collection: other_user_collection)
put "/api/v1/samples/#{sample.id}", params: params
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
@@ -610,17 +646,18 @@
boiling_point_lowerbound: 100,
melting_point_upperbound: 200,
melting_point_lowerbound: 200,
- molfile: File.read(Rails.root + 'spec/fixtures/test_2.mol'),
+ molfile: File.read("#{Rails.root}/spec/fixtures/test_2.mol"),
is_top_secret: false,
+ dry_solvent: true,
xref: { 'cas' => cas },
container: {
attachments: [],
children: [],
is_new: true,
is_deleted: false,
- name: 'new'
+ name: 'new',
},
- collection_id: user.collections[1][:id]
+ collection_id: user.collections[1][:id],
}
end
@@ -640,7 +677,9 @@
expect(s.attributes.symbolize_keys[:boiling_point].last).to eq(v) if k.to_s == 'boiling_point_lowerbound'
expect(s.attributes.symbolize_keys[:melting_point].first).to eq(v) if k.to_s == 'melting_point_upperbound'
expect(s.attributes.symbolize_keys[:melting_point].last).to eq(v) if k.to_s == 'melting_point_lowerbound'
- expect(s.attributes.symbolize_keys[k]).to eq(v) unless k.to_s.include?('bound') || k.to_s.include?('collection_id')
+ unless k.to_s.include?('bound') || k.to_s.include?('collection_id')
+ expect(s.attributes.symbolize_keys[k]).to eq(v)
+ end
end
expect(s.attributes.symbolize_keys[:solvent]).to eq([])
@@ -650,6 +689,19 @@
s = Sample.find_by(name: 'test')
expect(s.creator).to eq(user)
end
+
+ context 'with dry solvent' do
+ let(:sample) { Sample.find_by(name: 'test') }
+
+ it 'correctly sets the dry_solvent field' do
+ expect(sample.dry_solvent).to be(true)
+ end
+
+ it 'can be set to false' do
+ sample.dry_solvent = false
+ expect(sample.dry_solvent).to be(false)
+ end
+ end
end
describe 'DELETE /api/v1/samples' do
@@ -668,7 +720,7 @@
solvent: '',
location: '',
molfile: '',
- is_top_secret: false
+ is_top_secret: false,
}
end
@@ -692,7 +744,7 @@
{
all: false,
included_ids: [sample_1.id, sample_2.id],
- excluded_ids: []
+ excluded_ids: [],
}
end
@@ -700,7 +752,7 @@
{
all: true,
included_ids: [],
- excluded_ids: [sample_3.id]
+ excluded_ids: [sample_3.id],
}
end
@@ -788,16 +840,14 @@
:attachment,
storage: 'tmp', key: '8580a8d0-4b83-11e7-afc4-85a98b9d0194',
filename: 'upload.jpg',
- file_path: File.join(Rails.root, 'spec/fixtures/upload.jpg'),
+ file_path: Rails.root.join('spec/fixtures/upload.jpg'),
created_by: u1.id, created_for: u1.id
)
end
let(:sample_upd_1_params) do
JSON.parse(
- IO.read(File.join(
- Rails.root, 'spec', 'fixtures', 'sample_update_1_params.json'
- ))
+ Rails.root.join('spec', 'fixtures', 'sample_update_1_params.json').read,
).deep_symbolize_keys
end
@@ -830,13 +880,12 @@
attachment.attachable = nil
attachment.save!
put("/api/v1/samples/#{s1.id}.json",
- params: sample_upd_1_params.to_json,
- headers: { 'CONTENT_TYPE' => 'application/json' }
- )
+ params: sample_upd_1_params.to_json,
+ headers: { 'CONTENT_TYPE' => 'application/json' })
end
it 'returns 200 status code' do
- expect(response.status).to eq 200
+ expect(response).to have_http_status :ok
end
it 'has updated the analysis description' do
@@ -852,13 +901,13 @@
it 'has created an attachment for the new dataset' do
expect(Attachment.count).to eq(1)
expect(
- s1.analyses.first.children.first.attachments.first
+ s1.analyses.first.children.first.attachments.first,
).to eq(attachment)
end
it 'has stored the file' do
expect(
- File.exist?(s1.analyses.first.children.first.attachments.first.abs_path)
+ File.exist?(s1.analyses.first.children.first.attachments.first.abs_path),
).to be true
end
end
@@ -883,22 +932,21 @@
# sample_upd_1_params[:container][:children][0][:children][0][:id] =
# s2.container.children[0].children[0].id
put("/api/v1/samples/#{s1.id}.json",
- params: sample_upd_1_params.to_json,
- headers: { 'CONTENT_TYPE' => 'application/json' }
- )
+ params: sample_upd_1_params.to_json,
+ headers: { 'CONTENT_TYPE' => 'application/json' })
end
it 'returns 200 status code' do
- expect(response.status).to eq 200
+ expect(response).to have_http_status :ok
end
+
it 'has not created a dataset for the corresponding analysis' do
expect(cont_s2_analysis.children.count).to eq(1)
expect do
put("/api/v1/samples/#{s1.id}.json",
- params: sample_upd_1_params.to_json,
- headers: { 'CONTENT_TYPE' => 'application/json' }
- )
- end.to change { s2.analyses.first.children.count }.by 0
+ params: sample_upd_1_params.to_json,
+ headers: { 'CONTENT_TYPE' => 'application/json' })
+ end.not_to change { s2.analyses.first.children.count }
end
end
end
diff --git a/spec/api/chemotion/sample_task_api_spec.rb b/spec/api/chemotion/sample_task_api_spec.rb
index 2c2a689100..f46c3cdfa3 100644
--- a/spec/api/chemotion/sample_task_api_spec.rb
+++ b/spec/api/chemotion/sample_task_api_spec.rb
@@ -89,7 +89,7 @@
let(:expected_result) do
{
description: 'whatever',
- display_name: sample.showed_name,
+ display_name: sample.name,
done: false,
required_scan_results: 2,
result_unit: 'g',
@@ -138,4 +138,22 @@
end
end
end
+
+ describe 'DELETE /api/v1/sample_tasks/:id' do
+ context 'when sample task is open' do
+ it 'deletes the sample task and its related scan results and attachments' do
+ delete "/api/v1/sample_tasks/#{new_sample_task.id}"
+
+ expect(parsed_json_response).to include('deleted' => new_sample_task.id)
+ end
+ end
+
+ context 'when sample task is not open' do
+ it 'returns a 400' do
+ delete "/api/v1/sample_tasks/#{finished_scan.id}"
+
+ expect(parsed_json_response).to include('error' => 'Task could not be deleted')
+ end
+ end
+ end
end
diff --git a/spec/api/chemotion/search_api_spec.rb b/spec/api/chemotion/search_api_spec.rb
index 2b2b2c4b34..cd24ccee50 100644
--- a/spec/api/chemotion/search_api_spec.rb
+++ b/spec/api/chemotion/search_api_spec.rb
@@ -2,6 +2,8 @@
require 'rails_helper'
+# rubocop:disable RSpec/MultipleMemoizedHelpers, RSpec/MultipleExpectations
+
describe Chemotion::SearchAPI do
include_context 'api request authorization context'
@@ -18,6 +20,7 @@
let(:other_reaction) { create(:reaction, name: 'Other Reaction', samples: [sample_c, sample_d], creator: other_user) }
let(:screen) { create(:screen, name: 'Screen') }
let(:other_screen) { create(:screen, name: 'Other Screen') }
+ let!(:cell_line) { create(:cellline_sample, name: 'another-cellline-search-example', collections: [collection]) }
before do
CollectionsReaction.create!(reaction: reaction, collection: collection)
@@ -39,22 +42,140 @@
pending 'TODO: Add missing spec'
end
+ describe 'POST /api/v1/search/cell_lines' do
+ let(:url) { '/api/v1/search/cell_lines' }
+ let(:result) { JSON.parse(response.body) }
+ let(:params) do
+ {
+ selection: {
+ elementType: :cell_lines,
+ name: search_term,
+ search_by_method: search_method,
+ },
+ collection_id: collection.id,
+ }
+ end
+
+ context 'when searching a cell line sample in correct collection by cell line material name' do
+ let(:search_term) { 'name-001' }
+ let(:search_method) { 'cell_line_material_name' }
+
+ it 'returns one cell line sample object' do
+ expect(result.dig('cell_lines', 'totalElements')).to eq 1
+ expect(result.dig('cell_lines', 'ids')).to eq [cell_line.id]
+ end
+ end
+
+ context 'when searching a cell line sample in correct collection by cell line sample name' do
+ let(:search_term) { 'other' }
+ let(:search_method) { 'cell_line_sample_name' }
+
+ it 'returns one cell line sample object' do
+ expect(result.dig('cell_lines', 'totalElements')).to eq 1
+ expect(result.dig('cell_lines', 'ids')).to eq [cell_line.id]
+ end
+ end
+ end
+
describe 'POST /api/v1/search/all' do
let(:url) { '/api/v1/search/all' }
+ let(:search_method) { 'substring' }
+ let(:search_by_method) { :substring }
+ let(:result) { JSON.parse(response.body) }
let(:params) do
{
selection: {
elementType: :all,
name: search_term,
- search_by_method: :substring
+ search_by_method: search_by_method,
},
- collection_id: collection.id
+ collection_id: collection.id,
}
end
+ context 'when searching a cell line sample in correct collection by cell line material name' do
+ let(:search_term) { 'name-001' }
+ let(:search_method) { 'cell_line_material_name' }
+ let(:search_by_method) { :cell_line_material_name }
+
+ it 'returns one cell line sample object' do
+ expect(result.dig('cell_lines', 'totalElements')).to eq 1
+ expect(result.dig('cell_lines', 'ids')).to eq [cell_line.id]
+ end
+ end
+
+ context 'when searching a cell line sample in correct collection by cell line sample name' do
+ let(:search_term) { 'cellline-search-example' }
+ let(:search_method) { 'cell_line_sample_name' }
+ let(:search_by_method) { :cell_line_sample_name }
+
+ it 'returns one cell line sample object' do
+ expect(result.dig('cell_lines', 'totalElements')).to eq 1
+ expect(result.dig('cell_lines', 'ids')).to eq [cell_line.id]
+ end
+ end
+
context 'when searching a sample in correct collection' do
let(:search_term) { 'SampleA' }
+ it 'returns the sample' do
+ expect(result.dig('samples', 'totalElements')).to eq 1
+ expect(result.dig('samples', 'ids')).to eq [sample_a.id]
+ end
+
+ it 'returns referenced reaction of sample' do
+ expect(result.dig('reactions', 'totalElements')).to eq 1
+ expect(result.dig('reactions', 'ids')).to eq [reaction.id]
+ end
+
+ it 'returns referenced screen of sample' do
+ expect(result.dig('screens', 'totalElements')).to eq 1
+ expect(result.dig('screens', 'ids')).to eq [screen.id]
+ end
+
+ it 'returns referenced wellplate of sample' do
+ expect(result.dig('wellplates', 'totalElements')).to eq 1
+ expect(result.dig('wellplates', 'ids')).to eq [wellplate.id]
+ end
+ end
+ end
+
+ describe 'POST /api/v1/search/advanced' do
+ let(:url) { '/api/v1/search/advanced' }
+ let(:advanced_params) do
+ [
+ {
+ link: '',
+ match: 'LIKE',
+ table: 'samples',
+ element_id: 0,
+ field: {
+ column: 'name',
+ label: 'Name',
+ },
+ value: search_term,
+ sub_values: [],
+ unit: '',
+ },
+ ]
+ end
+ let(:params) do
+ {
+ selection: {
+ elementType: :advanced,
+ advanced_params: advanced_params,
+ search_by_method: :advanced,
+ },
+ collection_id: collection.id,
+ page: 1,
+ per_page: 15,
+ molecule_sort: true,
+ }
+ end
+
+ context 'when searching a name in samples in correct collection' do
+ let(:search_term) { 'SampleA' }
+
it 'returns the sample and all other objects referencing the sample from the requested collection' do
result = JSON.parse(response.body)
@@ -70,31 +191,114 @@
end
end
+ describe 'POST /api/v1/search/structure' do
+ let(:url) { '/api/v1/search/structure' }
+ let(:params) do
+ {
+ selection: {
+ elementType: :structure,
+ molfile: molfile,
+ search_type: 'sub',
+ tanimoto_threshold: 0.7,
+ search_by_method: :structure,
+ structure_search: true,
+ },
+ collection_id: collection.id,
+ page: 1,
+ per_page: 15,
+ molecule_sort: true,
+ }
+ end
+
+ context 'when searching a molfile in samples in correct collection' do
+ let(:molfile) { sample_a.molfile }
+
+ it 'returns the sample and all other objects referencing the sample from the requested collection' do
+ result = JSON.parse(response.body)
+
+ expect(result.dig('reactions', 'totalElements')).to eq 1
+ expect(result.dig('reactions', 'ids')).to eq [reaction.id]
+ expect(result.dig('samples', 'totalElements')).to eq 1
+ expect(result.dig('samples', 'ids')).to eq [sample_a.id]
+ expect(result.dig('screens', 'totalElements')).to eq 1
+ expect(result.dig('screens', 'ids')).to eq [screen.id]
+ expect(result.dig('wellplates', 'totalElements')).to eq 1
+ expect(result.dig('wellplates', 'ids')).to eq [wellplate.id]
+ end
+ end
+ end
+
+ describe 'POST /api/v1/search/by_ids' do
+ let(:url) { '/api/v1/search/by_ids' }
+ let(:id_params) do
+ {
+ model_name: 'sample',
+ ids: ids,
+ total_elements: 2,
+ with_filter: false,
+ }
+ end
+ let(:params) do
+ {
+ selection: {
+ elementType: :by_ids,
+ id_params: id_params,
+ list_filter_params: {},
+ search_by_method: 'search_by_ids',
+ },
+ collection_id: collection.id,
+ page: 1,
+ page_size: 15,
+ per_page: 15,
+ molecule_sort: true,
+ }
+ end
+
+ context 'when searching ids of search result in samples in correct collection' do
+ let(:ids) { [sample_a.id, sample_b.id] }
+
+ it 'returns the sample and all other objects referencing the sample from the requested collection' do
+ result = JSON.parse(response.body)
+
+ expect(result.dig('samples', 'totalElements')).to eq 2
+ expect(result.dig('samples', 'ids')).to eq [sample_a.id.to_s, sample_b.id.to_s]
+ end
+ end
+ end
+
describe 'POST /api/v1/search/samples' do
let(:url) { '/api/v1/search/samples' }
context 'when searching a sample in correct collection' do
let(:search_term) { 'SampleA' }
+ let(:result) { JSON.parse(response.body) }
let(:params) do
{
selection: {
elementType: :samples,
name: search_term,
- search_by_method: :substring
+ search_by_method: :substring,
},
- collection_id: collection.id
+ collection_id: collection.id,
}
end
- it 'returns the sample and all other objects referencing the sample from the requested collection' do
- result = JSON.parse(response.body)
+ it 'returns the sample' do
+ expect(result.dig('samples', 'totalElements')).to eq 1
+ expect(result.dig('samples', 'ids')).to eq [sample_a.id]
+ end
+ it 'returns referenced reaction of sample' do
expect(result.dig('reactions', 'totalElements')).to eq 1
expect(result.dig('reactions', 'ids')).to eq [reaction.id]
- expect(result.dig('samples', 'totalElements')).to eq 1
- expect(result.dig('samples', 'ids')).to eq [sample_a.id]
+ end
+
+ it 'returns screen reaction of sample' do
expect(result.dig('screens', 'totalElements')).to eq 1
expect(result.dig('screens', 'ids')).to eq [screen.id]
+ end
+
+ it 'returns wellplate reaction of sample' do
expect(result.dig('wellplates', 'totalElements')).to eq 1
expect(result.dig('wellplates', 'ids')).to eq [wellplate.id]
end
@@ -113,3 +317,4 @@
pending 'TODO: Add missing spec'
end
end
+# rubocop:enable RSpec/MultipleMemoizedHelpers, RSpec/MultipleExpectations
diff --git a/spec/api/chemotion/segment_api_spec.rb b/spec/api/chemotion/segment_api_spec.rb
new file mode 100644
index 0000000000..91dd9e6ed9
--- /dev/null
+++ b/spec/api/chemotion/segment_api_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+# rubocop:disable RSpec/NestedGroups
+describe Labimotion::SegmentAPI do
+ context 'with authorized user' do
+ let(:user) { create(:person) }
+
+ before do
+ allow_any_instance_of(WardenAuthentication).to receive(:current_user).and_return(user)
+ end
+
+ describe 'GET /api/v1/segments/klasses' do
+ it 'fetch segment klasses' do
+ get '/api/v1/segments/klasses'
+ body = JSON.parse(response.body)
+
+ expect(body['klass']).to be_an(Array)
+ end
+
+ end
+ end
+end
+# rubocop:enable RSpec/NestedGroups
diff --git a/spec/api/chemotion/suggestion_api_spec.rb b/spec/api/chemotion/suggestion_api_spec.rb
index 3b63b69eb6..e495dadc34 100644
--- a/spec/api/chemotion/suggestion_api_spec.rb
+++ b/spec/api/chemotion/suggestion_api_spec.rb
@@ -1,21 +1,118 @@
# frozen_string_literal: true
+# rubocop:disable RSpec/LetSetup
require 'rails_helper'
describe Chemotion::SuggestionAPI do
let!(:user) { create(:person, first_name: 'tam', last_name: 'M') }
- let(:collection) { create(:collection, user: user, is_shared: true, permission_level: 1) }
+ let(:collection) { create(:collection, user: user, is_shared: true, permission_level: 1, sample_detail_level: 10) }
let(:query) { 'query' }
+ let(:json_repsonse) { JSON.parse(response.body) }
+ let(:json_response) { response.body }
+ let(:params) do
+ {
+ collection_id: collection.id,
+ query: query,
+ is_sync: false,
+ }
+ end
+
+ describe 'GET /api/v1/cell_lines/suggestions/cell_lines' do
+ include_context 'api request authorization context'
+ let!(:cell_line) { create(:cellline_sample, collections: [collection]) }
+ let!(:cell_line2) { create(:cellline_sample, name: 'search-example', collections: [collection]) }
+ let!(:cell_line_without_col) { create(:cellline_sample, name: 'search-example') }
+ let!(:sample) { create(:sample, name: 'search-example', collections: [collection]) }
+
+ before do
+ get '/api/v1/suggestions/cell_lines', params: params
+ end
+
+ context 'when search term matches one cell line by the material name' do
+ let(:query) { 'name-001' }
+
+ it 'status code is success' do
+ expect(response).to have_http_status(:success)
+ end
+
+ it 'suggestions should be returned' do
+ expect(json_repsonse['suggestions'].length).to be 1
+ expect(json_repsonse['suggestions'].first['name']).to eq 'name-001'
+ expect(json_repsonse['suggestions'].first['search_by_method']).to eq 'cell_line_material_name'
+ end
+ end
+
+ context 'when search term matches one cell line by the sample name' do
+ let(:query) { 'arch-examp' }
+
+ it 'status code is success' do
+ expect(response).to have_http_status(:success)
+ end
+
+ it 'suggestions should be returned' do
+ expect(json_repsonse['suggestions'].length).to be 1
+ expect(json_repsonse['suggestions'].first['name']).to eq 'search-example'
+ expect(json_repsonse['suggestions'].first['search_by_method']).to eq 'cell_line_sample_name'
+ end
+ end
+ end
+
+ describe 'GET /api/v1/cell_lines/suggestions/all' do
+ include_context 'api request authorization context'
+ let!(:cell_line) { create(:cellline_sample, collections: [collection]) }
+ let!(:cell_line2) { create(:cellline_sample, name: 'search-example', collections: [collection]) }
+ let!(:sample) { create(:sample, name: 'search-example', collections: [collection]) }
+
+ before do
+ get '/api/v1/suggestions/all', params: params
+ end
+
+ context 'when search term matches two cell line samples with the same material name' do
+ let(:query) { 'name-001' }
+
+ it 'status code is success' do
+ expect(response).to have_http_status(:success)
+ end
+
+ it 'suggestions should be returned' do
+ expect(json_repsonse['suggestions'].length).to be 1
+ expect(json_repsonse['suggestions'].first['name']).to eq 'name-001'
+ expect(json_repsonse['suggestions'].first['search_by_method']).to eq 'cell_line_material_name'
+ end
+ end
+
+ context 'when search term matches one cell line by the sample name' do
+ let(:query) { 'arch-examp' }
+
+ it 'status code is success' do
+ expect(response).to have_http_status(:success)
+ end
+
+ it 'two suggestions were found' do
+ expect(json_repsonse['suggestions'].length).to be 2
+ end
+
+ it 'first suggestion from sample' do
+ expect(json_repsonse['suggestions'].first['name']).to eq 'search-example'
+ expect(json_repsonse['suggestions'].first['search_by_method']).to eq 'sample_name'
+ end
+
+ it 'second suggestion from cell line' do
+ expect(json_repsonse['suggestions'].second['name']).to eq 'search-example'
+ expect(json_repsonse['suggestions'].second['search_by_method']).to eq 'cell_line_sample_name'
+ end
+ end
+ end
context 'when user is authenticated' do
include_context 'api request authorization context'
it 'returns suggestions object with the correct structure' do
get '/api/v1/suggestions/all',
- params: {
- collection_id: collection.id,
- query: query,
- is_sync: false,
- }
+ params: {
+ collection_id: collection.id,
+ query: query,
+ is_sync: false,
+ }
expect(response).to have_http_status(:success)
json_response = JSON.parse(response.body)
expect(json_response.keys).to contain_exactly('suggestions')
@@ -27,13 +124,14 @@
context 'when user is not authenticated' do
it 'returns unauthorized error' do
get '/api/v1/suggestions/all',
- params:
- {
- collection_id: collection.id,
- query: query,
- is_sync: false,
- }
+ params:
+ {
+ collection_id: collection.id,
+ query: query,
+ is_sync: false,
+ }
expect(response).to have_http_status(:unauthorized)
end
end
end
+# rubocop:enable RSpec/LetSetup
diff --git a/spec/api/chemotion/third_party_app_api_spec.rb b/spec/api/chemotion/third_party_app_api_spec.rb
index e8d1b6a1d4..65e6689c2e 100644
--- a/spec/api/chemotion/third_party_app_api_spec.rb
+++ b/spec/api/chemotion/third_party_app_api_spec.rb
@@ -12,8 +12,8 @@
describe 'List all third party apps API' do
describe 'GET /third_party_apps/all' do
before do
- ThirdPartyApp.create(IPAddress: 'http://test.com', name: 'Test1')
- ThirdPartyApp.create(IPAddress: 'http://test.com', name: 'Test2')
+ ThirdPartyApp.create(url: 'http://test.com', name: 'Test1')
+ ThirdPartyApp.create(url: 'http://test.com', name: 'Test2')
end
it 'status of get request 200?' do
@@ -31,7 +31,7 @@
get '/api/v1//third_party_apps/all'
response_data = JSON.parse(response.body)
arr = [response_data[0]['name'], response_data[1]['name'],
- response_data[0]['IPAddress'], response_data[1]['IPAddress']]
+ response_data[0]['url'], response_data[1]['url']]
expect(arr).to eq(['Test1', 'Test2', 'http://test.com', 'http://test.com'])
end
end
@@ -41,7 +41,7 @@
describe 'POST /new_third_party_app' do
let(:params) do
{
- IPAddress: 'http://127.0.0.1',
+ url: 'http://127.0.0.1',
name: 'Example App',
}
end
@@ -53,15 +53,15 @@
it 'Entries of new third party app correct?' do
post '/api/v1/third_party_apps_administration/new_third_party_app', params: params
- tpas = [ThirdPartyApp.last.IPAddress, ThirdPartyApp.last.name]
- expect(tpas).to eq([params[:IPAddress], params[:name]])
+ tpas = [ThirdPartyApp.last.url, ThirdPartyApp.last.name]
+ expect(tpas).to eq([params[:url], params[:name]])
end
end
end
describe 'update_third_party_app API' do
let(:tpa_id) do
- ThirdPartyApp.create(IPAddress: 'http://test.com', name: 'Test1')
+ ThirdPartyApp.create(url: 'http://test.com', name: 'Test1')
tpas = ThirdPartyApp.all
tpa = tpas[0]
tpa.id
@@ -71,7 +71,7 @@
let(:params_all) do
{
id: tpa_id,
- IPAddress: '127.0.0.1',
+ url: '127.0.0.1',
name: 'Example App',
}
end
@@ -79,7 +79,7 @@
let(:params_name) do
{
id: tpa_id,
- IPAddress: 'http://test.com',
+ url: 'http://test.com',
name: 'Example App',
}
end
@@ -87,34 +87,34 @@
let(:params_ip) do
{
id: tpa_id,
- IPAddress: '127.0.0.1',
+ url: '127.0.0.1',
name: 'Test1',
}
end
it 'Change of ip address & name successfull?' do
post '/api/v1/third_party_apps_administration/update_third_party_app', params: params_all
- tpas = [ThirdPartyApp.last.IPAddress, ThirdPartyApp.last.name]
- expect(tpas).to eq([params_all[:IPAddress], params_all[:name]])
+ tpas = [ThirdPartyApp.last.url, ThirdPartyApp.last.name]
+ expect(tpas).to eq([params_all[:url], params_all[:name]])
end
it 'Change of name successfull?' do
post '/api/v1/third_party_apps_administration/update_third_party_app', params: params_name
- tpas = [ThirdPartyApp.last.IPAddress, ThirdPartyApp.last.name]
- expect(tpas).to eq([params_name[:IPAddress], params_name[:name]])
+ tpas = [ThirdPartyApp.last.url, ThirdPartyApp.last.name]
+ expect(tpas).to eq([params_name[:url], params_name[:name]])
end
it 'Change of ip address successfull?' do
post '/api/v1/third_party_apps_administration/update_third_party_app', params: params_ip
- tpas = [ThirdPartyApp.last.IPAddress, ThirdPartyApp.last.name]
- expect(tpas).to eq([params_ip[:IPAddress], params_ip[:name]])
+ tpas = [ThirdPartyApp.last.url, ThirdPartyApp.last.name]
+ expect(tpas).to eq([params_ip[:url], params_ip[:name]])
end
end
end
describe 'delete_third_party_app API' do
let(:tpa_id) do
- ThirdPartyApp.create(IPAddress: 'http://test.com', name: 'Test1')
+ ThirdPartyApp.create(url: 'http://test.com', name: 'Test1')
tpas = ThirdPartyApp.all
tpa = tpas[0]
tpa.id
@@ -136,10 +136,10 @@
describe 'get_by_id a third party app' do
before do
- ThirdPartyApp.create(IPAddress: 'http://test1.com', name: 'Test1')
- ThirdPartyApp.create(IPAddress: 'http://test2.com', name: 'Test2')
- ThirdPartyApp.create(IPAddress: 'http://test3.com', name: 'Test3')
- ThirdPartyApp.create(IPAddress: 'http://test4.com', name: 'Test4')
+ ThirdPartyApp.create(url: 'http://test1.com', name: 'Test1')
+ ThirdPartyApp.create(url: 'http://test2.com', name: 'Test2')
+ ThirdPartyApp.create(url: 'http://test3.com', name: 'Test3')
+ ThirdPartyApp.create(url: 'http://test4.com', name: 'Test4')
end
let(:tpas) do
@@ -163,14 +163,14 @@
it 'Is access by ID 1 of third party apps successfull?' do
get '/api/v1/third_party_apps/get_by_id', params: params1
response_data = JSON.parse(response.body)
- res = [response_data['name'], response_data['IPAddress']]
+ res = [response_data['name'], response_data['url']]
expect(res).to eq(['Test1', 'http://test1.com'])
end
it 'Is access by ID 3 of third party apps successfull?' do
get '/api/v1/third_party_apps/get_by_id', params: params3
response_data = JSON.parse(response.body)
- res = [response_data['name'], response_data['IPAddress']]
+ res = [response_data['name'], response_data['url']]
expect(res).to eq(['Test3', 'http://test3.com'])
end
end
@@ -178,8 +178,8 @@
describe 'get names of all third party apps' do
before do
- ThirdPartyApp.create(IPAddress: 'http://test1.com', name: 'Test1')
- ThirdPartyApp.create(IPAddress: 'http://test2.com', name: 'Test2')
+ ThirdPartyApp.create(url: 'http://test1.com', name: 'Test1')
+ ThirdPartyApp.create(url: 'http://test2.com', name: 'Test2')
end
describe 'GET /api/v1/names/all' do
@@ -194,8 +194,8 @@
describe 'get ip address of a third party app by name' do
before do
- ThirdPartyApp.create(IPAddress: 'http://test1.com', name: 'Test1')
- ThirdPartyApp.create(IPAddress: 'http://test2.com', name: 'Test2')
+ ThirdPartyApp.create(url: 'http://test1.com', name: 'Test1')
+ ThirdPartyApp.create(url: 'http://test2.com', name: 'Test2')
end
describe 'GET /IP' do
diff --git a/spec/api/chemotion/ui_api_spec.rb b/spec/api/chemotion/ui_api_spec.rb
index b7584556ac..a7dc6dbdba 100644
--- a/spec/api/chemotion/ui_api_spec.rb
+++ b/spec/api/chemotion/ui_api_spec.rb
@@ -19,7 +19,7 @@ class StubConfig
describe 'without spectra config' do
before do
StubConfig.url = false
- Rails.configuration.spectra.chempspectra = {}
+ Rails.configuration.spectra.chemspectra = StubConfig
get '/api/v1/ui/initialize'
end
diff --git a/spec/api/chemotion/user_api_spec.rb b/spec/api/chemotion/user_api_spec.rb
index 08aa560409..6c41474e4f 100644
--- a/spec/api/chemotion/user_api_spec.rb
+++ b/spec/api/chemotion/user_api_spec.rb
@@ -9,7 +9,7 @@
let(:alternative_user) { create(:person) }
describe 'GET /api/v1/users/name' do
- let(:query_param) { "name=#{name_param}" }
+ let(:query_param) { "name=#{name_param}&type=Group,Person" }
before do
create(:person, first_name: 'Jane', last_name: 'Doe')
@@ -28,13 +28,13 @@
it 'returns data from 2 people and 1 group' do
expect(
- JSON.parse(response.body)['users'].map { |u| u['user_type'] }
+ JSON.parse(response.body)['users'].pluck('type'),
).to contain_exactly('Person', 'Person', 'Group')
end
end
context 'when name is missing' do
- let(:query_param) {}
+ let(:query_param) { '' }
it 'returns an empty array' do
expect(JSON.parse(response.body)['error']).to eq('name is missing')
@@ -42,7 +42,7 @@
end
context 'when name is empty' do
- let(:name_param) {}
+ let(:name_param) { '' }
it 'returns an empty array' do
expect(JSON.parse(response.body)['users'].length).to eq(0)
@@ -84,7 +84,7 @@
let(:jwt_token) { 42 }
it 'returns 401 unauthorized status code' do
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
@@ -146,7 +146,7 @@
'first_name' => 'My', 'last_name' => 'Fanclub',
'email' => 'jane.s@fan.club',
'name_abbreviation' => 'JFC', 'users' => [other_user.id]
- }
+ },
}
end
@@ -159,19 +159,19 @@
Group.where(
last_name: 'Fanclub',
first_name: 'My', name_abbreviation: 'JFC'
- )
+ ),
).not_to be_empty
expect(
- Group.find_by(name_abbreviation: 'JFC').users.pluck(:id)
+ Group.find_by(name_abbreviation: 'JFC').users.pluck(:id),
).to match_array [user.id, other_user.id]
expect(
- Group.find_by(name_abbreviation: 'JFC').admins
+ Group.find_by(name_abbreviation: 'JFC').admins,
).not_to be_empty
expect(
- Group.find_by(name_abbreviation: 'JFC').admins.first
+ Group.find_by(name_abbreviation: 'JFC').admins.first,
).to eq user
expect(
- user.administrated_accounts.where(name_abbreviation: 'JFC')
+ user.administrated_accounts.where(name_abbreviation: 'JFC'),
).not_to be_empty
end
end
@@ -198,7 +198,7 @@
let(:params) do
{
rm_users: [user.id, other_user.id],
- add_users: [alternative_user.id]
+ add_users: [alternative_user.id],
}
end
@@ -244,7 +244,7 @@
let(:params) do
{
rm_users: [other_user.id, alternative_user.id],
- add_users: [user.id]
+ add_users: [user.id],
}
end
@@ -254,12 +254,12 @@
it 'does not update a group of persons' do
expect(
- Group.find(group.id).users.pluck(:id)
+ Group.find(group.id).users.pluck(:id),
).to match_array([other_user.id, alternative_user.id])
end
it 'returns with unauthorized status' do
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
it 'returns with unauthorized message' do
diff --git a/spec/api/collection_api_spec.rb b/spec/api/collection_api_spec.rb
index 3606b5a5b0..a4314e7cfc 100644
--- a/spec/api/collection_api_spec.rb
+++ b/spec/api/collection_api_spec.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+# rubocop:disable RSpec/NestedGroups, Style/FormatString, RSpec/MultipleMemoizedHelpers, RSpec/AnyInstance, RSpec/MultipleExpectations, RSpec/FilePath, RSpec/LetSetup, Naming/VariableNumber, RSpec/IndexedLet, Lint/RedundantCopDisableDirective
+
require 'rails_helper'
describe Chemotion::CollectionAPI do
@@ -11,11 +13,11 @@
sample_detail_level reaction_detail_level wellplate_detail_level
screen_detail_level is_shared is_locked sync_collections_users
shared_users is_synchronized is_remote shared_to
- ]
+ ],
}
end
- context 'authorized user logged in' do
+ context 'with authorized user logged in' do
let!(:user) { create(:person, first_name: 'Musashi', last_name: 'M') }
let!(:u2) { create(:person) }
let(:group) { create(:group) }
@@ -24,17 +26,28 @@
let!(:root_u2) { create(:collection, user: user, shared_by_id: u2.id, is_shared: true, is_locked: true) }
let!(:root_u) { create(:collection, user: u2, shared_by_id: user.id, is_shared: true, is_locked: true) }
- let!(:c2) { create(:collection, user: u2, shared_by_id: user.id, is_shared: true, permission_level: 2, ancestry: root_u.id.to_s) }
+ let!(:c2) do
+ create(:collection, user: u2, shared_by_id: user.id, is_shared: true, permission_level: 2,
+ ancestry: root_u.id.to_s)
+ end
let!(:c3) { create(:collection, user: user, is_shared: false) }
let!(:c4) { create(:collection, user: user, shared_by_id: u2.id, is_shared: true, ancestry: root_u2.id.to_s) }
let!(:c5) { create(:collection, shared_by_id: u2.id, is_shared: true) }
# - - - - sync collection
let!(:owner) { create(:user) }
- let!(:c_sync_ancestry) { create(:collection, user: user, shared_by_id: owner.id, is_shared: true, is_locked: true, is_synchronized: false) }
+ let!(:c_sync_ancestry) do
+ create(:collection, user: user, shared_by_id: owner.id, is_shared: true, is_locked: true, is_synchronized: false)
+ end
let!(:c_sync_r) { create(:collection, user: owner, is_shared: false, is_locked: false, is_synchronized: false) }
let!(:c_sync_w) { create(:collection, user: owner, is_shared: false, is_locked: false, is_synchronized: false) }
- let!(:sc_r) { create(:sync_collections_user, collection_id: c_sync_r.id, user_id: user.id, permission_level: 0, shared_by_id: owner.id, fake_ancestry: c_sync_ancestry.id.to_s) }
- let!(:sc_w) { create(:sync_collections_user, collection_id: c_sync_w.id, user_id: user.id, permission_level: 1, shared_by_id: owner.id, fake_ancestry: c_sync_ancestry.id.to_s) }
+ let!(:sc_r) do
+ create(:sync_collections_user, collection_id: c_sync_r.id, user_id: user.id, permission_level: 0,
+ shared_by_id: owner.id, fake_ancestry: c_sync_ancestry.id.to_s)
+ end
+ let!(:sc_w) do
+ create(:sync_collections_user, collection_id: c_sync_w.id, user_id: user.id, permission_level: 1,
+ shared_by_id: owner.id, fake_ancestry: c_sync_ancestry.id.to_s)
+ end
before do
allow_any_instance_of(WardenAuthentication).to receive(:current_user).and_return(user)
@@ -56,7 +69,7 @@
before { post "/api/v1/collections/take_ownership/#{c1.id}" }
it 'is allowed' do
- expect(response.status).to eq 201
+ expect(response).to have_http_status :created
end
end
@@ -73,13 +86,13 @@
end
it 'is allowed' do
- expect(response.status).to eq 201
+ expect(response).to have_http_status :created
end
it 'makes c2 an unshared root collection of user' do
c2.reload
expect(c2.parent).to be_nil
- expect(c2.is_shared).to eq false
+ expect(c2.is_shared).to be false
expect(c2.shared_by_id).to be_nil
end
end
@@ -97,7 +110,7 @@
before { post "/api/v1/collections/take_ownership/#{c1.id}" }
it 'is not allowed' do
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
@@ -105,7 +118,7 @@
before { post "/api/v1/collections/take_ownership/#{c2.id}" }
it 'is not allowed' do
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
@@ -124,7 +137,7 @@
describe 'GET /api/v1/collections/locked' do
it 'returns serialized locked unshared collection roots of logged in user' do
get '/api/v1/collections/locked'
- expect(JSON.parse(response.body)['collections'].map { |coll| coll['label'] })
+ expect(JSON.parse(response.body)['collections'].pluck('label'))
.to eq ['All', 'chemotion-repository.net']
end
end
@@ -144,9 +157,10 @@
it 'returns serialized (remote) collection roots of logged in user' do
get '/api/v1/collections/remote_roots'
expect(
- JSON.parse(response.body).dig('collections', 0, 'children').map { |c| c['id'] }
+ JSON.parse(response.body).dig('collections', 0, 'children').pluck('id'),
).to include(c4.id)
end
+
context 'with a collection shared to a group' do
let(:p2) { create(:person) }
let!(:g1) { create(:group, users: [user]) }
@@ -168,8 +182,8 @@
it 'returns serialized (remote) collection roots of logged in user' do
expect(
JSON.parse(response.body)['collections'].map do |root|
- root['children'].map { |e| e['id'] }
- end.flatten
+ root['children'].pluck('id')
+ end.flatten,
).to match_array [c4.id, c6.id]
end
end
@@ -178,7 +192,7 @@
describe 'POST /api/v1/collections/unshared' do
let(:params) do
{
- label: 'test'
+ label: 'test',
}
end
@@ -197,8 +211,12 @@
let!(:c2_source) { create(:collection, user: u2) }
let!(:c2_target) { create(:collection, user: u2) }
let!(:c3_target) { create(:collection, user: u2, is_shared: true, shared_by_id: user.id) }
- let!(:c_shared_source_low) { create(:collection, user_id: user.id, shared_by_id: u2.id, is_shared: true, permission_level: 1) }
- let!(:c_shared_source_high) { create(:collection, user_id: user.id, shared_by_id: u2.id, is_shared: true, permission_level: 3) }
+ let!(:c_shared_source_low) do
+ create(:collection, user_id: user.id, shared_by_id: u2.id, is_shared: true, permission_level: 1)
+ end
+ let!(:c_shared_source_high) do
+ create(:collection, user_id: user.id, shared_by_id: u2.id, is_shared: true, permission_level: 3)
+ end
let!(:c_shared_target) { create(:collection, user: user, shared_by_id: u2.id, is_shared: true) }
let!(:c_sync_source) { create(:sync_collections_user, user: user, shared_by_id: u2.id, collection_id: c2_source) }
let!(:c_sync_target) { create(:sync_collections_user, user: user, shared_by_id: u2.id, collection_id: c2_target) }
@@ -221,9 +239,9 @@
research_plan: { all: true },
currentCollection: {
id: c_source.id,
- "is_shared": false,
- "is_synchronized": false
- }
+ is_shared: false,
+ is_synchronized: false,
+ },
}
end
@@ -231,16 +249,16 @@
{
currentCollection: {
id: c3_target.id,
- is_shared: true
- }
+ is_shared: true,
+ },
}
end
let!(:ui_state_tweaked) do
{
currentCollection: {
- id: c2_source.id
- }
+ id: c2_source.id,
+ },
}
end
@@ -248,8 +266,8 @@
{
currentCollection: {
id: c_shared_source_high.id,
- is_shared: true
- }
+ is_shared: true,
+ },
}
end
@@ -257,12 +275,19 @@
{
currentCollection: {
id: c_shared_source_low.id,
- is_shared: true
- }
+ is_shared: true,
+ },
+ }
+ end
+
+ let!(:tabs_segment) do
+ {
+ 'sample' => { 'results' => -2, 'analyses' => 1, 'properties' => 2, 'references' => -1, 'qc_curation' => 3,
+ 'measurements' => -3 },
}
end
- describe '01 - from and to collections owned by user, ' do
+ describe '01 - from and to collections owned by user,' do
# before do
# CollectionsSample.create!(collection_id: c_source.id, sample_id: s.id)
# CollectionsSample.create!(collection_id: c_source.id, sample_id: s_r.id)
@@ -278,108 +303,245 @@
# c_target.reload2
# end
describe 'PUT /api/v1/collections/elements' do
+ let!(:cell_line_1) { create(:cellline_sample, collections: [c_source]) }
+ let!(:cell_line_2) { create(:cellline_sample, collections: [c_source]) }
+ let!(:cell_line_3) { create(:cellline_sample, collections: [c_source]) }
+ let(:cell_line_ids) { [] }
+ let!(:ui_state) do
+ {
+ cell_line: {
+ checkedAll: false,
+ checkedIds: cell_line_ids,
+ },
+ currentCollection: {
+ id: c_source.id,
+ is_shared: false,
+ is_synchronized: false,
+ },
+ }
+ end
+
+ context 'when try to move two of three cell line elements into empty collection' do
+ let(:target_collection_id) { c_target.id }
+ let(:cell_line_ids) { [cell_line_1.id, cell_line_2.id] }
+
+ before do
+ put '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: target_collection_id }
+ end
+
+ it 'the cell line samples are now in the target collection' do
+ expect(cell_line_1.reload.collections).to eq [c_target]
+ expect(cell_line_2.reload.collections).to eq [c_target]
+ end
+
+ it 'the cell line samples are not in the old collection' do
+ expect(c_source.reload.cellline_samples.pluck(:id)).to eq [cell_line_3.id]
+ end
+
+ it 'tags in the moved elements are adjusted' do
+ new_coll_id_1 = cell_line_1.reload.tag.taggable_data['collection_labels'].first['id']
+ new_coll_id_2 = cell_line_2.reload.tag.taggable_data['collection_labels'].first['id']
+ expect(new_coll_id_1).to be c_target.id
+ expect(new_coll_id_2).to be c_target.id
+ end
+
+ it 'the third cell line should remain in the old collection' do
+ expect(cell_line_3.reload.collections).to eq [c_source]
+ end
+ end
+
+ context 'when try to move cell line element into collection where it already exists' do
+ let!(:cellline_in_two_colls) { create(:cellline_sample, collections: [c_source, c_target]) }
+ let(:target_collection_id) { c_target.id }
+ let(:cell_line_ids) { [cellline_in_two_colls.id] }
+
+ before do
+ put '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: target_collection_id }
+ end
+
+ it 'the cell line sample is only in the target collection' do
+ expect(cellline_in_two_colls.reload.collections).to eq [c_target]
+ end
+
+ it 'tags in the moved cellline are adjusted' do
+ collection_id = cellline_in_two_colls.reload.tag.taggable_data['collection_labels'].first['id']
+ expect(collection_id).to be c_target.id
+ end
+ end
+
+ context 'when source and target collection are the same' do
+ let(:target_collection_id) { c_source.id }
+ let(:cell_line_ids) { [cell_line_1.id] }
+
+ before do
+ put '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c_source }
+ end
+
+ it 'the cell line sample was not moved' do
+ expect(cell_line_1.reload.collections).to eq [c_source]
+ end
+ end
+
it 'moves all elements and returns 204' do
put '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c_target.id }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
describe 'POST /api/v1/collections/elements' do
- it 'assigns elements to collection and returns 204' do
- post '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c_target.id }
- expect(response.status).to eq 204
+ let!(:cell_line_sample) { create(:cellline_sample, collections: [c_source]) }
+ let!(:ui_state) do
+ {
+ cell_line: {
+ checkedAll: false,
+ checkedIds: [cell_line_sample.id],
+ },
+ currentCollection: {
+ id: c_source.id,
+ is_shared: false,
+ is_synchronized: false,
+ },
+ }
+ end
+
+ context 'when assigning cellline to new collection' do
+ before do
+ post '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c_target.id }
+ end
+
+ it 'cell line connected to two collections' do
+ expect(cell_line_sample.reload.collections.pluck(:id)).to eq [c_source.id, c_target.id]
+ end
+
+ it 'cell line tag was updated' do
+ new_coll_ids = cell_line_sample.reload.tag.taggable_data['collection_labels'].pluck('id')
+ expect(new_coll_ids).to eq [c_source.id, c_target.id]
+ end
+ end
+
+ context 'when assigning cell line to collection where it is already in' do
+ let(:cellline_collections) do
+ CollectionsCellline.find_by(
+ cellline_sample_id: cell_line_sample.id,
+ collection_id: c_source.id,
+ )
+ end
+
+ before do
+ post '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c_source.id }
+ end
+
+ it 'cell line connected to one collections' do
+ expect(cell_line_sample.reload.collections.map(&:id)).to eq [c_source.id]
+ end
+
+ it 'cell line tag was not updated' do
+ new_coll_id = cell_line_sample.reload.tag.taggable_data['collection_labels'].pluck('id')
+ expect(new_coll_id).to eq [c_source.id]
+ end
+
+ it 'only one link between cell line and collection exists' do
+ expect([cellline_collections].flatten.size).to be 1
+ end
+ end
+
+ xit 'assigns elements to collection and returns 204' do
+ expect(response).to have_http_status :no_content
end
end
describe 'DELETE /api/v1/collections/elements' do
it 'removes elements from a collection and returns 204' do
delete '/api/v1/collections/elements', params: { ui_state: ui_state }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
end
- describe '02 - from collection owned by user to collection shared by user, ' do
+ describe '02 - from collection owned by user to collection shared by user,' do
describe 'PUT /api/v1/collections/elements to collection shared by user' do
it 'moves all elements and returns 204' do
put '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c3_target.id }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
describe 'POST /api/v1/collections/elements to collection shared by user' do
it 'assigns elements to collection and returns 204' do
post '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c3_target.id }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
end
- describe '03 - from collection shared by user, to collection owned by user, ' do
+ describe '03 - from collection shared by user, to collection owned by user,' do
describe 'PUT /api/v1/collections/elements from collection shared by user' do
it 'moves all elements and returns 204' do
put('/api/v1/collections/elements', params: { ui_state: ui_state_shared, collection_id: c_target.id })
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
describe 'POST /api/v1/collections/elements from collection shared by user' do
it 'assigns elements to collection and returns 204' do
post '/api/v1/collections/elements', params: { ui_state: ui_state_shared, collection_id: c_target.id }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
describe 'DELETE /api/v1/collections/elements from collection shared by user' do
it 'removes elements from a collection and returns 204' do
delete '/api/v1/collections/elements', params: { ui_state: ui_state_shared }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
end
- describe '04 - from collection shared to user with high permission level (>3), to collection owned by user, ' do
+ describe '04 - from collection shared to user with high permission level (>3), to collection owned by user,' do
describe 'PUT /api/v1/collections/elements from collection shared by user' do
it 'moves all elements and returns 204' do
- put '/api/v1/collections/elements', params: { ui_state: ui_state_shared_to_high, collection_id: c_target.id }
- expect(response.status).to eq 204
+ put '/api/v1/collections/elements',
+ params: { ui_state: ui_state_shared_to_high, collection_id: c_target.id }
+ expect(response).to have_http_status :no_content
end
end
describe 'POST /api/v1/collections/elements from collection shared by user' do
it 'assigns elements to collection and returns 204' do
- post '/api/v1/collections/elements', params: { ui_state: ui_state_shared_to_high, collection_id: c_target.id }
- expect(response.status).to eq 204
+ post '/api/v1/collections/elements',
+ params: { ui_state: ui_state_shared_to_high, collection_id: c_target.id }
+ expect(response).to have_http_status :no_content
end
end
describe 'DELETE /api/v1/collections/elements from collection shared by user' do
it 'removes elements from a collection and returns 204' do
delete '/api/v1/collections/elements', params: { ui_state: ui_state_shared_to_high }
- expect(response.status).to eq 204
+ expect(response).to have_http_status :no_content
end
end
end
- describe '05 - from collection shared to user with low permission level, to collection owned by user, ' do
+ describe '05 - from collection shared to user with low permission level, to collection owned by user,' do
describe 'PUT /api/v1/collections/elements from collection shared by user' do
it 'refuses with 401' do
put '/api/v1/collections/elements', params: { ui_state: ui_state_shared_to_low, collection_id: c_target.id }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
describe 'POST /api/v1/collections/elements from collection shared by user' do
it 'refuses with 401' do
- post '/api/v1/collections/elements', params: { ui_state: ui_state_shared_to_low, collection_id: c_target.id }
- expect(response.status).to eq 401
+ post '/api/v1/collections/elements',
+ params: { ui_state: ui_state_shared_to_low, collection_id: c_target.id }
+ expect(response).to have_http_status :unauthorized
end
end
describe 'DELETE /api/v1/collections/elements from collection shared by user' do
it 'refuses with 401' do
delete '/api/v1/collections/elements', params: { ui_state: ui_state_shared_to_low }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
@@ -388,21 +550,21 @@
describe 'PUT /api/v1/collections/elements' do
it 'refuses with 401' do
put '/api/v1/collections/elements', params: { ui_state: ui_state_tweaked, collection_id: c_target.id }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
describe 'POST /api/v1/collections/elements' do
it 'refuses with 401' do
post '/api/v1/collections/elements', params: { ui_state: ui_state_tweaked, collection_id: c_target.id }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
describe 'DELETE /api/v1/collections/elements' do
it 'refuses with 401' do
delete '/api/v1/collections/elements', params: { ui_state: ui_state_tweaked }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
@@ -411,19 +573,38 @@
describe 'PUT /api/v1/collections/elements' do
it 'refuses with 401' do
put '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c2_target.id }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
describe 'POST /api/v1/collections/elements' do
it 'refuses with 401' do
post '/api/v1/collections/elements', params: { ui_state: ui_state, collection_id: c2_target.id }
- expect(response.status).to eq 401
+ expect(response).to have_http_status :unauthorized
end
end
end
# TODO: from/to authorized sync/shared collection
# TODO from All collection put and delete: expect(response.status).to eq 401
+
+ describe 'update tab segments collection' do
+ describe 'POST /api/v1/collections/tabs' do
+ it 'find collection and insert creates tab segments value' do
+ post '/api/v1/collections/tabs', params: { segments: tabs_segment, id: c_target.id }
+ c = Collection.find(c_target.id)
+ expect(c).not_to be_nil
+ expect(c.tabs_segment).not_to be_nil
+ expect(response).to have_http_status :created
+ end
+ end
+
+ describe 'PATCH /api/v1/collections/tabs' do
+ it 'updates new tab segments value and returns 204' do
+ patch '/api/v1/collections/tabs', params: { segment: tabs_segment, id: c_target.id }
+ expect(response).to have_http_status :no_content
+ end
+ end
+ end
end
describe 'PUT /api/v1/collections/shared/:id' do
@@ -433,7 +614,7 @@
sample_detail_level: 5,
reaction_detail_level: 2,
wellplate_detail_level: 1,
- screen_detail_level: 5
+ screen_detail_level: 5,
} }
end
@@ -471,25 +652,25 @@
sample: {
all: true,
included_ids: [s1.id],
- excluded_ids: [s2.id]
+ excluded_ids: [s2.id],
},
reaction: {
all: true,
included_ids: [],
- excluded_ids: []
+ excluded_ids: [],
},
wellplate: {
all: false,
included_ids: [w1.id],
- excluded_ids: []
+ excluded_ids: [],
},
screen: {
all: true,
included_ids: [],
- excluded_ids: [sc1.id]
+ excluded_ids: [sc1.id],
},
- research_plan: {}
- }
+ research_plan: {},
+ },
}
end
@@ -520,13 +701,13 @@
all: true,
included_ids: [s1.id],
excluded_ids: [],
- collection_id: c1.id
+ collection_id: c1.id,
},
reaction: {},
wellplate: {},
screen: {},
- research_plan: {}
- }
+ research_plan: {},
+ },
}
end
@@ -548,13 +729,13 @@
{
collections: [c1.id],
format: 'zip',
- nested: true
+ nested: true,
}
end
it 'creates an export job' do
post '/api/v1/collections/exports', params: params.to_json, headers: { 'CONTENT_TYPE' => 'application/json' }
- expect(response.status).to eq(204)
+ expect(response).to have_http_status(:no_content)
end
end
@@ -563,13 +744,13 @@
{
collections: [c2.id],
format: 'zip',
- nested: true
+ nested: true,
}
end
it 'returns 401 Unauthorized' do
post '/api/v1/collections/exports', params: params.to_json, headers: { 'CONTENT_TYPE' => 'application/json' }
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
@@ -578,13 +759,13 @@
{
collections: [666],
format: 'zip',
- nested: true
+ nested: true,
}
end
it 'returns 401 Unauthorized' do
post '/api/v1/collections/exports', params: params.to_json, headers: { 'CONTENT_TYPE' => 'application/json' }
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
end
@@ -595,49 +776,49 @@
{
file: fixture_file_upload(
Rails.root.join('spec/fixtures/import/2541a423-11d9-4c76-a7e1-0da470644012.zip'), 'application/gzip'
- )
+ ),
}
end
it 'creates an import job' do
- status = post '/api/v1/collections/imports', params: file_upload
- expect(response.status).to eq(204)
+ post '/api/v1/collections/imports', params: file_upload
+ expect(response).to have_http_status(:no_content)
end
end
end
- context 'metadata' do
+ context 'with metadata' do
describe 'GET /api/v1/collections//metadata' do
it 'with a valid collection id and with existing metadata' do
c1.metadata = create(:metadata)
get '/api/v1/collections/%s/metadata' % c1.id
- expect(response.status).to eq(200)
+ expect(response).to have_http_status(:ok)
expect(JSON.parse(response.body)['metadata']['title']).to eq('A test collection')
end
it 'with a valid collection id, but without existing metadata' do
get '/api/v1/collections/%s/metadata' % c1.id
- expect(response.status).to eq(404)
+ expect(response).to have_http_status(:not_found)
end
it 'without a valid collection id' do
get '/api/v1/collections/12345/metadata'
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
it 'with a collection id of someone else' do
get '/api/v1/collections/%s/metadata' % c5.id
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
describe 'POST /api/v1/collections//metadata' do
- let (:post_params) do
+ let(:post_params) do
{
metadata: {
- title: 'A new collection title'
- }
+ title: 'A new collection title',
+ },
}
end
@@ -645,31 +826,30 @@
c1.metadata = create(:metadata)
post '/api/v1/collections/%s/metadata' % c1.id, params: post_params
- expect(response.status).to eq(201)
+ expect(response).to have_http_status(:created)
expect(JSON.parse(response.body)['metadata']['title']).to eq('A new collection title')
end
it 'with a valid collection id, but without existing metadata' do
post '/api/v1/collections/%s/metadata' % c1.id, params: post_params
- expect(response.status).to eq(201)
+ expect(response).to have_http_status(:created)
expect(JSON.parse(response.body)['metadata']['title']).to eq('A new collection title')
end
it 'without a valid collection id' do
post '/api/v1/collections/12345/metadata', params: post_params
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
it 'with a collection id of someone else' do
post '/api/v1/collections/%s/metadata' % c5.id, params: post_params
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
end
-
end
- context 'no user logged in' do
+ context 'when no user logged in' do
before do
allow_any_instance_of(WardenAuthentication).to receive(:current_user).and_return(nil)
end
@@ -677,14 +857,14 @@
describe 'GET /api/v1/collections/roots' do
it 'responds with 401 status code' do
get '/api/v1/collections/roots'
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
describe 'GET /api/v1/collections/shared_roots' do
it 'responds with 401 status code' do
get '/api/v1/collections/shared_roots'
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
@@ -693,14 +873,14 @@
{
collection_attributes: attributes_for(:collection, label: 'New'),
user_ids: [1],
- sample_ids: []
+ sample_ids: [],
}
end
it 'does not create a new collection' do
post '/api/v1/collections/shared', params: params
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
c = Collection.find_by(label: 'New')
expect(c).to be_nil
@@ -713,13 +893,13 @@
{
collections: [1, 2, 3],
format: 'zip',
- nested: true
+ nested: true,
}
end
it 'responds with 401 status code' do
post '/api/v1/collections/exports', params: params.to_json, headers: { 'CONTENT_TYPE' => 'application/json' }
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
end
@@ -730,40 +910,40 @@
{
file: fixture_file_upload(
Rails.root.join('spec/fixtures/import/2541a423-11d9-4c76-a7e1-0da470644012.zip'), 'application/gzip'
- )
+ ),
}
end
it 'responds with 401 status code' do
- status = post '/api/v1/collections/imports', params: file_upload
- expect(response.status).to eq(401)
+ post '/api/v1/collections/imports', params: file_upload
+ expect(response).to have_http_status(:unauthorized)
end
end
end
- context 'metadata' do
- let!(:c1) { create(:collection) }
+ context 'with metadata' do
+ let!(:c1) { create(:collection) }
describe 'GET /api/v1/collections//metadata' do
it 'with a valid collection id and with existing metadata' do
c1.metadata = create(:metadata)
get '/api/v1/collections/%s/metadata' % c1.id
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
it 'with a valid collection id, but without existing metadata' do
get '/api/v1/collections/%s/metadata' % c1.id
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
describe 'POST /api/v1/collections//metadata' do
- let (:post_params) do
+ let(:post_params) do
{
metadata: {
- title: 'A new collection title'
- }
+ title: 'A new collection title',
+ },
}
end
@@ -771,14 +951,15 @@
c1.metadata = create(:metadata)
post '/api/v1/collections/%s/metadata' % c1.id, params: post_params
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
it 'with a valid collection id, but without existing metadata' do
post '/api/v1/collections/%s/metadata' % c1.id, params: post_params
- expect(response.status).to eq(401)
+ expect(response).to have_http_status(:unauthorized)
end
end
end
end
end
+# rubocop:enable RSpec/NestedGroups, Style/FormatString, RSpec/MultipleMemoizedHelpers, RSpec/AnyInstance, RSpec/MultipleExpectations, RSpec/FilePath, RSpec/LetSetup, Naming/VariableNumber, RSpec/IndexedLet, Lint/RedundantCopDisableDirective
diff --git a/spec/api/element_api_spec.rb b/spec/api/element_api_spec.rb
index 8d92425e8f..345b327773 100644
--- a/spec/api/element_api_spec.rb
+++ b/spec/api/element_api_spec.rb
@@ -1,19 +1,94 @@
# frozen_string_literal: true
+# rubocop: disable RSpec/NestedGroups
+# rubocop: disable RSpec/AnyInstance
+# rubocop: disable RSpec/LetSetup
+# rubocop: disable RSpec/FilePath
+# rubocop: disable RSpec/IndexedLet, Lint/RedundantCopDisableDirective, RSpec/Rails/HaveHttpStatus
+
require 'rails_helper'
describe Chemotion::ElementAPI do
- context 'authorized user logged in' do
- let(:user) { create(:user) }
- let!(:c) { create(:collection, user_id: user.id) }
- let!(:s1) { create(:sample, collections: [c]) }
- let!(:r1) { create(:reaction, collections: [c]) }
+ let(:user) { create(:user) }
+ let!(:collection) { create(:collection, user_id: user.id) }
+
+ describe 'DELETE /api/v1/ui_state' do
+ let!(:cell_line_sample1) { create(:cellline_sample, collections: [collection, collection2]) }
+ let!(:cell_line_sample2) { create(:cellline_sample, collections: [collection, collection2]) }
+ let!(:collection2) { create(:collection, user_id: user.id) }
+
+ context 'with user with delete access is logged in,' do
+ before do
+ allow_any_instance_of(WardenAuthentication).to receive(:current_user).and_return(user)
+ delete '/api/v1/ui_state/', params: params.to_json, headers: { 'CONTENT_TYPE' => 'application/json' }
+ end
+
+ context 'when one cell line should be removed from the eln:' do
+ let(:params) do
+ {
+ cell_line: { checkedIds: [cell_line_sample1.id] },
+ options: {},
+ selecteds: [],
+ currentCollection: { id: collection.id },
+ }
+ end
+
+ it 'only one cell line remains in eln' do
+ expect(CelllineSample.find_by(id: cell_line_sample1.id)).to be_nil
+ expect(CelllineSample.count).to be 1
+ end
+
+ it 'all links between collections and cell lines are removed' do
+ expect(CollectionsCellline.find_by(cellline_sample_id: cell_line_sample1.id)).to be_nil
+ end
+
+ it 'cell line material still remains in eln' do
+ expect(CelllineMaterial.find(cell_line_sample1.cellline_material_id)).not_to be_nil
+ end
+
+ it 'returned correct response code' do
+ expect(response.code).to eq '200'
+ end
+ end
+
+ context 'when all cell lines should be removed from the eln' do
+ let(:params) do
+ {
+ cell_line: { checkedAll: true },
+ options: {},
+ selecteds: [],
+ currentCollection: { id: collection.id },
+ }
+ end
+
+ it 'no cell line remains in eln' do
+ expect(CelllineSample.count).to be 0
+ end
+
+ it 'all links between collections and cell lines are removed' do
+ expect(CollectionsCellline.count).to be 0
+ end
+
+ it 'cell line material still remains in eln' do
+ expect(CelllineMaterial.find(cell_line_sample1.cellline_material_id)).not_to be_nil
+ end
+
+ it 'returned correct response code' do
+ expect(response.code).to eq '200'
+ end
+ end
+ end
+ end
+
+ context 'when authorized user logged in' do
+ let!(:s1) { create(:sample, collections: [collection]) }
+ let!(:r1) { create(:reaction, collections: [collection]) }
let(:params) do
{
sample: { checkedIds: [s1.id] },
reaction: { checkedIds: [r1.id] },
- currentCollection: { id: c.id }
+ currentCollection: { id: collection.id },
}
end
@@ -33,3 +108,9 @@
end
end
end
+
+# rubocop: enable RSpec/NestedGroups
+# rubocop: enable RSpec/AnyInstance
+# rubocop: enable RSpec/LetSetup
+# rubocop: enable RSpec/FilePath
+# rubocop: enable RSpec/IndexedLet, Lint/RedundantCopDisableDirective, RSpec/Rails/HaveHttpStatus
diff --git a/spec/api/entities/inventory_entity_spec.rb b/spec/api/entities/inventory_entity_spec.rb
new file mode 100644
index 0000000000..80fc0ec196
--- /dev/null
+++ b/spec/api/entities/inventory_entity_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Entities::InventoryEntity do
+ describe '.represent' do
+ subject(:entity) do
+ described_class.represent(inventory)
+ end
+
+ let(:inventory) { create(:inventory) }
+
+ it 'returns all necessary data' do
+ expect(grape_entity_as_hash).to include(
+ :id,
+ :prefix,
+ :name,
+ :counter,
+ )
+ end
+ end
+end
diff --git a/spec/api/entities/reaction_entity_spec.rb b/spec/api/entities/reaction_entity_spec.rb
index af09ee312e..8cff990ce3 100644
--- a/spec/api/entities/reaction_entity_spec.rb
+++ b/spec/api/entities/reaction_entity_spec.rb
@@ -24,6 +24,146 @@
starting_materials: [create(:valid_sample)],
solvents: [create(:valid_sample)],
purification_solvents: [create(:valid_sample)],
+ variations: [{ id: '1',
+ products: { '47': { aux: { yield: 0,
+ purity: 0.29,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C21H18N2O2',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 330.37982,
+ equivalent: nil },
+ unit: 'g',
+ value: nil },
+ '48': { aux: { yield: 100,
+ purity: 0.12,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C31H30O4',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 466.56750000000005,
+ equivalent: nil },
+ unit: 'g',
+ value: '6' } },
+ reactants: { '45': { aux: { yield: nil,
+ purity: 0.78,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C10H17NO2S',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 215.31247999999997,
+ equivalent: nil },
+ unit: 'g',
+ value: nil },
+ '46': { aux: { yield: nil,
+ purity: 0.84,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C10H16O4S',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 232.29664,
+ equivalent: nil },
+ unit: 'g',
+ value: nil } },
+ properties: { duration: { foo: {}, unit: 'Hour(s)', value: '19' },
+ temperature: { unit: 'C', value: '1' } },
+ startingMaterials: { '43': { aux: { yield: nil,
+ purity: 0.25,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C10H10BF4IN2',
+ coefficient: 1,
+ isReference: true,
+ molecularWeight: 371.9088828000001,
+ equivalent: nil },
+ unit: 'g',
+ value: 0.483 },
+ '44': { aux: { yield: nil,
+ purity: 0.4,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C32H72Cr2N2O7',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 700.9154799999998,
+ equivalent: nil },
+ unit: 'g',
+ value: nil } },
+ solvents: {} },
+ { id: '2',
+ products: { '47': { aux: { yield: 0,
+ purity: 0.29,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C21H18N2O2',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 330.37982,
+ equivalent: nil },
+ unit: 'g',
+ value: nil },
+ '48': { aux: { yield: 2,
+ purity: 0.12,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C31H30O4',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 466.56750000000005,
+ equivalent: nil },
+ unit: 'g',
+ value: '0.03' } },
+ reactants: { '45': { aux: { yield: nil,
+ purity: 0.78,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C10H17NO2S',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 215.31247999999997,
+ equivalent: nil },
+ unit: 'g',
+ value: nil },
+ '46': { aux: { yield: nil,
+ purity: 0.84,
+ loading: nil,
+ molarity: 0,
+ sumFormula: 'C10H16O4S',
+ coefficient: 1,
+ isReference: false,
+ molecularWeight: 232.29664,
+ equivalent: nil },
+ unit: 'g',
+ value: nil } },
+ properties: { duration: { unit: 'Hour(s)', value: '15' },
+ temperature: { unit: '