analyzeBedItemStructure()

in client/client/modules/render/tracks/bed/internal/data/bedTransformer.js [11:157]


    analyzeBedItemStructure(bedItem, level = 2) {
        bedItem.name = bedItem.name || '';
        let structure = null;
        let correctedItems = null;
        switch (level) {
            case 0: {
                correctedItems = [];
                // display bed feature as rectangle
                const item = {
                    startIndex: bedItem.startIndex,
                    endIndex: bedItem.endIndex,
                    index: null,
                    strand: bedItem.strand,
                    isEmpty: false
                };
                correctedItems.push(item);
            }
                break;
            case 1: {
                // display bed feature as line & inner rectangle
                if (bedItem.thickStart !== null && bedItem.thickStart !== undefined && bedItem.thickEnd !== null && bedItem.thickEnd !== undefined) {
                    let featuresCoordinates = [bedItem.startIndex, bedItem.endIndex];
                    correctedItems = [];
                    if (featuresCoordinates.indexOf(bedItem.thickStart) === -1) {
                        featuresCoordinates.push(bedItem.thickStart);
                    }
                    if (featuresCoordinates.indexOf(bedItem.thickEnd) === -1) {
                        featuresCoordinates.push(bedItem.thickEnd);
                    }

                    featuresCoordinates = Sorting.quickSort(featuresCoordinates);

                    for (let i = 0; i < featuresCoordinates.length - 1; i++) {
                        const startIndex = featuresCoordinates[i];
                        const endIndex = featuresCoordinates[i + 1];
                        const item = {
                            startIndex: startIndex,
                            endIndex: endIndex,
                            index: null,
                            strand: bedItem.strand,
                            isEmpty: startIndex < bedItem.thickStart || endIndex > bedItem.thickEnd
                        };
                        correctedItems.push(item);
                    }
                }
            }
                break;
            default: {
                // display bed feature with blocks
                if (bedItem.blockStarts !== null && bedItem.blockStarts !== undefined && bedItem.blockStarts.length > 0) {
                    let featuresCoordinates = [bedItem.startIndex, bedItem.endIndex];
                    correctedItems = [];

                    for (let i = 0; i < bedItem.blockStarts.length; i++) {
                        if (featuresCoordinates.indexOf(bedItem.startIndex + bedItem.blockStarts[i]) === -1) {
                            featuresCoordinates.push(bedItem.startIndex + bedItem.blockStarts[i]);
                        }
                        if (featuresCoordinates.indexOf(bedItem.startIndex + bedItem.blockStarts[i] + bedItem.blockSizes[i] - 1) === -1) {
                            featuresCoordinates.push(bedItem.startIndex + bedItem.blockStarts[i] + bedItem.blockSizes[i] - 1);
                        }
                    }

                    featuresCoordinates = Sorting.quickSort(featuresCoordinates);

                    for (let i = 0; i < featuresCoordinates.length - 1; i++) {
                        const startIndex = featuresCoordinates[i];
                        const endIndex = featuresCoordinates[i + 1];
                        const item = {
                            startIndex: startIndex,
                            endIndex: endIndex,
                            index: null,
                            strand: bedItem.strand,
                            isEmpty: true
                        };
                        for (let j = 0; j < bedItem.blockStarts.length; j++) {
                            if (item.startIndex >= bedItem.startIndex + bedItem.blockStarts[j] && item.endIndex <= bedItem.startIndex + bedItem.blockStarts[j] + bedItem.blockSizes[j] - 1) {
                                item.isEmpty = false;
                                item.index = j;
                                break;
                            }
                        }
                        correctedItems.push(item);
                    }
                }
            }
                break;
        }
        if (correctedItems) {
            structure = [];
            // correction: we should combine two neighbor elements if they have equal indices.
            let i = 0;
            while (i < correctedItems.length - 1) {
                const current = correctedItems[i];
                const next = correctedItems[i + 1];
                if (current.index === next.index) {
                    current.endIndex = next.endIndex;
                    correctedItems.splice(i + 1, 1);
                }
                else {
                    i++;
                }
            }
            // creating blocks (empty / not empty)
            let block = null;
            for (let i = 0; i < correctedItems.length; i++) {
                const item = correctedItems[i];
                if (block === null) {
                    block = {
                        strand: item.strand,
                        startIndex: item.startIndex,
                        endIndex: item.endIndex,
                        items: [item],
                        isEmpty: item.isEmpty
                    };
                    continue;
                }
                if (item.isEmpty === block.isEmpty) {
                    block.items.push(item);
                    block.endIndex = item.endIndex;
                }
                else {
                    structure.push(block);
                    block = {
                        strand: item.strand,
                        startIndex: item.startIndex,
                        endIndex: item.endIndex,
                        items: [item],
                        isEmpty: item.isEmpty
                    };
                }
            }

            if (block) {
                structure.push(block);
            }

            // correction: we should increase empty block's start index by 1 bp and decrease end index by 1 bp
            for (let i = 0; i < structure.length; i++) {
                const block = structure[i];
                if (block.isEmpty) {
                    block.startIndex++;
                    block.endIndex--;
                }
            }
        }
        return structure;
    }