<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import _ from 'underscore';
import { Panel, PanelBody } from '../libs/bootstrap/panel';
import { auditDecor } from './audit';
import { DocumentsPanelReq } from './doc';
import * as globals from './globals';
import { DbxrefList } from './dbxref';
import { ExperimentTable } from './dataset';
import { FetchedItems } from './fetched';
import { FileGallery } from './filegallery';
import { ProjectBadge } from './image';
import { Breadcrumbs } from './navigation';
import { singleTreatment, AlternateAccession } from './objectutils';
import pubReferenceList from './reference';
import { SortTablePanel, SortTable } from './sorttable';
import Status from './status';
import { BiosampleSummaryString, BiosampleOrganismNames, CollectBiosampleDocs, AwardRef, Supersede } from './typeutils';


const anisogenicValues = [
    'anisogenic, sex-matched and age-matched',
    'anisogenic, age-matched',
    'anisogenic, sex-matched',
    'anisogenic',
];


// Return an array of React components to render into the enclosing panel, given the experiment
// object in the context parameter
function AssayDetails(replicates, libVals, libSpecials, libComps) {
    // Make a deep copy of libVals to avoid side effects.
    const results = Object.assign({}, libVals);

    // Little utility to convert a replicate to a unique index we can use for arrays (like libraryValues below)
    function replicateToIndex(replicate) {
        return `${replicate.biological_replicate_number}-${replicate.technical_replicate_number}`;
    }

    // No replicates, so no assay entries
    if (!replicates.length) {
        return [];
    }

    // Collect library values to display from each replicate. Each key holds an array of values from each replicate's library,
    // indexed by the replicate's biological replicate number. After this loop runs, libraryValues.values should all be filled
    // with objects keyed by <bio rep num>-<tech rep num> and have the corresponding value or undefined if no value exists
    // for that key. The 'value' properties of each object in libraryValues will all be undefined after this loop runs.
    replicates.forEach((replicate) => {
        const library = replicate.library;
        const replicateIndex = replicateToIndex(replicate);

        if (library) {
            // Handle "normal" library properties
            Object.keys(results).forEach((key) => {
                let libraryValue;

                // For specific library properties, preprocess non-simple values into simple ones using librarySpecials
                if (libSpecials && libSpecials[key]) {
                    // Preprocess complex values into simple ones
                    libraryValue = libSpecials[key](library);
                } else {
                    // Simple value -- just copy it if it exists (copy undefined if it doesn't)
                    libraryValue = library[key];
                }

                // If library property exists, add it to the values we're collecting, keyed by the biological replicate number.
                // We'll prune it after this replicate loop.
                results[key].values[replicateIndex] = libraryValue;
            });
        }
    });

    // Each property of libraryValues now has every value found in every existing library property in every replicate.
    // Now for each library value in libraryValues, set the 'value' property if all values in the 'values' object are
    // identical and existing. Otherwise, keep 'value' set to undefined.
    const firstBiologicalReplicate = replicateToIndex(replicates[0]);
    Object.keys(results).forEach((key) => {
        // Get the first key's value to compare against the others.
        const firstValue = results[key].values[firstBiologicalReplicate];

        // See if all values in the values array are identical. Treat 'undefined' as a value
        if (_(Object.keys(results[key].values)).all(replicateId => results[key].values[replicateId] === firstValue)) {
            // All values for the library value are the same. Set the 'value' field with that value.
            results[key].value = firstValue;

            // If the resulting value is undefined, then all values are undefined for this key. Null out the values array.
            if (firstValue === undefined) {
                results[key].values = [];
            } else if (libComps && libComps[key]) {
                // The current key shows a rendering component, call it and save the resulting React object for later rendering.
                results[key].component[firstBiologicalReplicate] = libComps[key](replicates[0].library);
            }
        } else if (libComps && libComps[key]) {
            replicates.forEach((replicate) => {
                // If the current key shows a rendering component, call it and save the resulting React object for later rendering.
                results[key].component[replicateToIndex(replicate)] = libComps[key](replicate.library);
            });
        }
    });

    // Now begin the output process -- one React component per array element
    const components = Object.keys(results).map((key) => {
        const libraryEntry = results[key];
        if (libraryEntry.value !== undefined || (libraryEntry.values && Object.keys(libraryEntry.values).length)) {
            return (
                <div key={key} data-test={libraryEntry.test}>
                    <dt>{libraryEntry.title}</dt>
                    <dd>
                        {libraryEntry.value !== undefined ?
                            <span>
                                {(libraryEntry.component && Object.keys(libraryEntry.component).length) ?
                                    <span>
                                        {Object.keys(libraryEntry.component).map(componentKey => <span key={componentKey}>{libraryEntry.component[componentKey]}</span>)}
                                    </span>
                                :
                                    <span>{libraryEntry.value}</span>
                                }
                            </span>
                        :
                            <span>
                                {Object.keys(libraryEntry.values).map((replicateId) => {
                                    const value = libraryEntry.values[replicateId];
                                    if (libraryEntry.component && libraryEntry.component[replicateId]) {
                                        // Display the pre-rendered component
                                        return <span key={replicateId} className="line-item">{libraryEntry.component[replicateId]} [{replicateId}]</span>;
                                    }
                                    if (value) {
                                        // Display the simple value
                                        return <span key={replicateId} className="line-item">{value} [{replicateId}]</span>;
                                    }

                                    // No value to display; happens when at least one replicate had a value for this property, but this one doesn't
                                    return null;
                                })}
                            </span>
                        }
                    </dd>
                </div>
            );
        }

        // No value exists for this property in any replicate; display nothing for this property.
        return null;
    });

    // Finally, return the array of JSX renderings of all assay details.
    return components;
}


const ControllingExperiments = (props) => {
    const context = props.context;

    if (props.items.length) {
        return (
            <div>
                <ExperimentTable
                    {...props}
                    items={props.items}
                    limit={5}
                    url={props.url}
                    title={`Experiments with ${context.accession} as a control:`}
                />
            </div>
        );
    }
    return null;
};

ControllingExperiments.propTypes = {
    context: PropTypes.object.isRequired, // Experiment object containing the table being rendered
    items: PropTypes.array, // Experiments to display in the table
    url: PropTypes.string, // URL to go to full search results corresponding to the table
};

ControllingExperiments.defaultProps = {
    items: [],
    url: '',
};


class ExperimentComponent extends React.Component {
    constructor() {
        super();

        this.libraryValues = {
            treatments: { values: {}, value: undefined, component: {}, title: 'Treatments', test: 'treatments' },
            nucleic_acid_term_name: { values: {}, value: undefined, component: {}, title: 'Nucleic acid type', test: 'nucleicacid' },
            depleted_in_term_name: { values: {}, value: undefined, component: {}, title: 'Depleted in', test: 'depletedin' },
            nucleic_acid_starting_quantity: { values: {}, value: undefined, component: {}, title: 'Library starting quantity', test: 'startingquantity' },
            size_range: { values: {}, value: undefined, component: {}, title: 'Size range', test: 'sizerange' },
            lysis_method: { values: {}, value: undefined, component: {}, title: 'Lysis method', test: 'lysismethod' },
            extraction_method: { values: {}, value: undefined, component: {}, title: 'Extraction method', test: 'extractionmethod' },
            fragmentation_method: { values: {}, value: undefined, component: {}, title: 'Fragmentation method', test: 'fragmentationmethod' },
            library_size_selection_method: { values: {}, value: undefined, component: {}, title: 'Size selection method', test: 'sizeselectionmethod' },
            strand_specificity: { values: {}, value: undefined, component: {}, title: 'Strand specificity', test: 'strandspecificity' },
            spikeins_used: { values: {}, value: undefined, component: {}, title: 'Spike-ins datasets', test: 'spikeins' },
        };
    }

    render() {
        let librarySpecials = {};
        let libraryComponents = {};
        let condensedReplicates = [];
        let libSubmitterComments = [];
        const context = this.props.context;
        const adminUser = !!(this.context.session_properties && this.context.session_properties.admin);
        const itemClass = globals.itemClass(context, 'view-item');
        const replicates = context.replicates && context.replicates.length ? context.replicates : [];
        if (replicates.length) {
            const condensedReplicatesKeyed = _(replicates).groupBy(replicate => (replicate.library ? replicate.library['@id'] : replicate.uuid));
            if (Object.keys(condensedReplicatesKeyed).length) {
                condensedReplicates = _.toArray(condensedReplicatesKeyed);
            }

            // Collect all replicate libraries into one array of library objects.<commit_msg>ENCD-4135-integrity-num (#2375)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import _ from 'underscore';
import { Panel, PanelBody } from '../libs/bootstrap/panel';
import { auditDecor } from './audit';
import { DocumentsPanelReq } from './doc';
import * as globals from './globals';
import { DbxrefList } from './dbxref';
import { ExperimentTable } from './dataset';
import { FetchedItems } from './fetched';
import { FileGallery } from './filegallery';
import { ProjectBadge } from './image';
import { Breadcrumbs } from './navigation';
import { singleTreatment, AlternateAccession } from './objectutils';
import pubReferenceList from './reference';
import { SortTablePanel, SortTable } from './sorttable';
import Status from './status';
import { BiosampleSummaryString, BiosampleOrganismNames, CollectBiosampleDocs, AwardRef, Supersede } from './typeutils';


const anisogenicValues = [
    'anisogenic, sex-matched and age-matched',
    'anisogenic, age-matched',
    'anisogenic, sex-matched',
    'anisogenic',
];


// Return an array of React components to render into the enclosing panel, given the experiment
// object in the context parameter
function AssayDetails(replicates, libVals, libSpecials, libComps) {
    // Make a deep copy of libVals to avoid side effects.
    const results = Object.assign({}, libVals);

    // Little utility to convert a replicate to a unique index we can use for arrays (like libraryValues below)
    function replicateToIndex(replicate) {
        return `${replicate.biological_replicate_number}-${replicate.technical_replicate_number}`;
    }

    // No replicates, so no assay entries
    if (!replicates.length) {
        return [];
    }

    // Collect library values to display from each replicate. Each key holds an array of values from each replicate's library,
    // indexed by the replicate's biological replicate number. After this loop runs, libraryValues.values should all be filled
    // with objects keyed by <bio rep num>-<tech rep num> and have the corresponding value or undefined if no value exists
    // for that key. The 'value' properties of each object in libraryValues will all be undefined after this loop runs.
    replicates.forEach((replicate) => {
        const library = replicate.library;
        const replicateIndex = replicateToIndex(replicate);

        if (library) {
            // Handle "normal" library properties
            Object.keys(results).forEach((key) => {
                let libraryValue;

                // For specific library properties, preprocess non-simple values into simple ones using librarySpecials
                if (libSpecials && libSpecials[key]) {
                    // Preprocess complex values into simple ones
                    libraryValue = libSpecials[key](library);
                } else {
                    // Simple value -- just copy it if it exists (copy undefined if it doesn't)
                    libraryValue = library[key];
                }

                // If library property exists, add it to the values we're collecting, keyed by the biological replicate number.
                // We'll prune it after this replicate loop.
                results[key].values[replicateIndex] = libraryValue;
            });
        }
    });

    // Each property of libraryValues now has every value found in every existing library property in every replicate.
    // Now for each library value in libraryValues, set the 'value' property if all values in the 'values' object are
    // identical and existing. Otherwise, keep 'value' set to undefined.
    const firstBiologicalReplicate = replicateToIndex(replicates[0]);
    Object.keys(results).forEach((key) => {
        // Get the first key's value to compare against the others.
        const firstValue = results[key].values[firstBiologicalReplicate];

        // See if all values in the values array are identical. Treat 'undefined' as a value
        if (_(Object.keys(results[key].values)).all(replicateId => results[key].values[replicateId] === firstValue)) {
            // All values for the library value are the same. Set the 'value' field with that value.
            results[key].value = firstValue;

            // If the resulting value is undefined, then all values are undefined for this key. Null out the values array.
            if (firstValue === undefined) {
                results[key].values = [];
            } else if (libComps && libComps[key]) {
                // The current key shows a rendering component, call it and save the resulting React object for later rendering.
                results[key].component[firstBiologicalReplicate] = libComps[key](replicates[0].library);
            }
        } else if (libComps && libComps[key]) {
            replicates.forEach((replicate) => {
                // If the current key shows a rendering component, call it and save the resulting React object for later rendering.
                results[key].component[replicateToIndex(replicate)] = libComps[key](replicate.library);
            });
        }
    });

    // Now begin the output process -- one React component per array element
    const components = Object.keys(results).map((key) => {
        const libraryEntry = results[key];
        if (libraryEntry.value !== undefined || (libraryEntry.values && Object.keys(libraryEntry.values).length)) {
            return (
                <div key={key} data-test={libraryEntry.test}>
                    <dt>{libraryEntry.title}</dt>
                    <dd>
                        {libraryEntry.value !== undefined ?
                            <span>
                                {(libraryEntry.component && Object.keys(libraryEntry.component).length) ?
                                    <span>
                                        {Object.keys(libraryEntry.component).map(componentKey => <span key={componentKey}>{libraryEntry.component[componentKey]}</span>)}
                                    </span>
                                :
                                    <span>{libraryEntry.value}</span>
                                }
                            </span>
                        :
                            <span>
                                {Object.keys(libraryEntry.values).map((replicateId) => {
                                    const value = libraryEntry.values[replicateId];
                                    if (libraryEntry.component && libraryEntry.component[replicateId]) {
                                        // Display the pre-rendered component
                                        return <span key={replicateId} className="line-item">{libraryEntry.component[replicateId]} [{replicateId}]</span>;
                                    }
                                    if (value) {
                                        // Display the simple value
                                        return <span key={replicateId} className="line-item">{value} [{replicateId}]</span>;
                                    }

                                    // No value to display; happens when at least one replicate had a value for this property, but this one doesn't
                                    return null;
                                })}
                            </span>
                        }
                    </dd>
                </div>
            );
        }

        // No value exists for this property in any replicate; display nothing for this property.
        return null;
    });

    // Finally, return the array of JSX renderings of all assay details.
    return components;
}


const ControllingExperiments = (props) => {
    const context = props.context;

    if (props.items.length) {
        return (
            <div>
                <ExperimentTable
                    {...props}
                    items={props.items}
                    limit={5}
                    url={props.url}
                    title={`Experiments with ${context.accession} as a control:`}
                />
            </div>
        );
    }
    return null;
};

ControllingExperiments.propTypes = {
    context: PropTypes.object.isRequired, // Experiment object containing the table being rendered
    items: PropTypes.array, // Experiments to display in the table
    url: PropTypes.string, // URL to go to full search results corresponding to the table
};

ControllingExperiments.defaultProps = {
    items: [],
    url: '',
};


class ExperimentComponent extends React.Component {
    constructor() {
        super();

        this.libraryValues = {
            treatments: { values: {}, value: undefined, component: {}, title: 'Treatments', test: 'treatments' },
            nucleic_acid_term_name: { values: {}, value: undefined, component: {}, title: 'Nucleic acid type', test: 'nucleicacid' },
            rna_integrity_number: { values: {}, value: undefined, component: {}, title: 'RNA integrity number', test: 'rnaintegritynumber' },
            depleted_in_term_name: { values: {}, value: undefined, component: {}, title: 'Depleted in', test: 'depletedin' },
            nucleic_acid_starting_quantity: { values: {}, value: undefined, component: {}, title: 'Library starting quantity', test: 'startingquantity' },
            size_range: { values: {}, value: undefined, component: {}, title: 'Size range', test: 'sizerange' },
            lysis_method: { values: {}, value: undefined, component: {}, title: 'Lysis method', test: 'lysismethod' },
            extraction_method: { values: {}, value: undefined, component: {}, title: 'Extraction method', test: 'extractionmethod' },
            fragmentation_method: { values: {}, value: undefined, component: {}, title: 'Fragmentation method', test: 'fragmentationmethod' },
            library_size_selection_method: { values: {}, value: undefined, component: {}, title: 'Size selection method', test: 'sizeselectionmethod' },
            strand_specificity: { values: {}, value: undefined, component: {}, title: 'Strand specificity', test: 'strandspecificity' },
            spikeins_used: { values: {}, value: undefined, component: {}, title: 'Spike-ins datasets', test: 'spikeins' },
        };
    }

    render() {
        let librarySpecials = {};
        let libraryComponents = {};
        let condensedReplicates = [];
        let libSubmitterComments = [];
        const context = this.props.context;
        const adminUser = !!(this.context.session_properties && this.context.session_properties.admin);
        const itemClass = globals.itemClass(context, 'view-item');
        const replicates = context.replicates && context.replicates.length ? context.replicates : [];
        if (replicates.length) {
            const condensedReplicatesKeyed = _(replicates).groupBy(replicate => (replicate.library ? replicate.library['@id'] : replicate.uuid));
            if (Object.keys(condensedReplicatesKeyed).length) {
                condensedReplicates = _.toArray(condensedReplicatesKeyed);
            }

            // Collect all replicate libraries into one array of library objects.
{'fraction_non_alphanumeric': 0.1053082191780822, 'fraction_numerical': 0.0006308579668348954, 'mean_word_length': 2.1143699129946674, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 34, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1358966', 'n_tokens_mistral': 5487, 'n_tokens_neox': 5200, 'n_words': 1685}