File

src/app/components/report/report.component.ts

Implements

OnInit

Metadata

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(reportService: ReportService, ts: TreeService, ga: GoogleAnalyticsService)
Parameters :
Name Type Optional
reportService ReportService No
ts TreeService No
ga GoogleAnalyticsService No

Inputs

asFullData
Type : Row[]
Default value : []
bmType
Type : string
Default value : ''
compareData
Type : Observable<literal type>
compareSheets
Type : CompareData[]
Default value : []
currentSheet
Type : Sheet
currentSheetConfig
Type : Observable<SheetConfig>
fullDataByOrgan
Type : Row[][]
Default value : []
hideReportCompareTab
Type : boolean
Default value : false
inputReportData
Type : Observable<Report>
linksData$
Type : Observable<LinksASCTBData>
sheetData
Type : Row[]
Default value : []

Outputs

closeReport
Type : EventEmitter
computedReport
Type : EventEmitter
deleteSheet
Type : EventEmitter

Methods

customColors
customColors(v: string)
Parameters :
Name Type Optional
v string No
Returns : string
deleteCompareSheetReport
deleteCompareSheetReport(i: number)
Parameters :
Name Type Optional
i number No
Returns : void
downloadCompareSheetReport
downloadCompareSheetReport(i: number)
Parameters :
Name Type Optional
i number No
Returns : { sheet: any; sheetName: any; name: string; }
downloadData
downloadData()
Returns : { sheet: any; sheetName: any; name: string; }
downloadReport
downloadReport(i)
Parameters :
Name Optional Default value
i No -1
Returns : void
downloadReportByOrgan
downloadReportByOrgan()
Returns : void
getBiomarkerLabel
getBiomarkerLabel(bmType: string)
Parameters :
Name Type Optional
bmType string No
getBMCTAS
getBMCTAS(bmCtPairs: BmCtPairings[], download: Record[])
Parameters :
Name Type Optional
bmCtPairs BmCtPairings[] No
download Record<string, string>[] No
Returns : {}
getTotals
getTotals(data: CByOrgan[], key: string)
Parameters :
Name Type Optional
data CByOrgan[] No
key string No
Returns : any
makeOntologyLinksGraphData
makeOntologyLinksGraphData(reportData: Report, sheetData: Row[])
Parameters :
Name Type Optional
reportData Report No
sheetData Row[] No
Returns : {}

Properties

biomarkersCounts
Type : BiomarkersCounts[]
Default value : []
biomarkersSeperateNames
Type : BiomarkersNamesInReport[]
Default value : []
clickButton
Default value : false
compareReport
Type : CompareReport[]
Default value : []
countsByOrgan
Type : MatTableDataSource<CByOrgan>
Default value : new MatTableDataSource()
displayedColumns
Type : string[]
Default value : [ 'organName', 'ASWithNoLink', 'CTWithNoLink', 'BWithNoLink', 'ASWithNoCT', 'CTWithNoB', 'AS_AS', 'AS_CT', 'CT_BM', 'anatomicalStructures', 'cellTypes', ]
Public ga
Type : GoogleAnalyticsService
ontologyLinkGraphData
Type : ReturnType<>
Default value : []
reportData
Type : Report
Default value : { anatomicalStructures: [], cellTypes: [], biomarkers: [], ASWithNoLink: [], CTWithNoLink: [], BWithNoLink: [], ASWithNoCT: [], CTWithNoB: [], }
Public reportService
Type : ReportService
resultDataByOrganName
Type : Report
Default value : { anatomicalStructures: [], ASWithNoLink: [], CTWithNoLink: [], BWithNoLink: [], cellTypes: [], biomarkers: [], ASWithNoCT: [], CTWithNoB: [], }
SheetConfig
Type : SheetConfig
sort
Type : MatSort
Decorators :
@ViewChild(MatSort)
total_AS_AS
Type : number
Default value : 0
total_AS_CT
Type : number
Default value : 0
total_CT_B
Type : number
Default value : 0
Public ts
Type : TreeService
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { BiomarkersCounts, BiomarkersNamesInReport, CByOrgan, Report } from '../../models/report.model';
import { CompareData, CompareReport, Row, Sheet, SheetConfig } from '../../models/sheet.model';
import { ReportService } from './report.service';

import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import * as moment from 'moment';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
import { Observable } from 'rxjs';
import * as XLSX from 'xlsx';
import { GaAction, GaCategory } from '../../models/ga.model';
import { BmCtPairings, LinksASCTBData } from '../../models/tree.model';
import { TreeService } from '../../modules/tree/tree.service';

@Component({
  selector: 'app-report',
  templateUrl: './report.component.html',
  styleUrls: ['./report.component.scss'],
})
export class ReportComponent implements OnInit {
  reportData: Report = {
    anatomicalStructures: [],
    cellTypes: [],
    biomarkers: [],
    ASWithNoLink: [],
    CTWithNoLink: [],
    BWithNoLink: [],
    ASWithNoCT: [],
    CTWithNoB: [],
  };
  resultDataByOrganName: Report = {
    anatomicalStructures: [],
    ASWithNoLink: [],
    CTWithNoLink: [],
    BWithNoLink: [],
    cellTypes: [],
    biomarkers: [],
    ASWithNoCT: [],
    CTWithNoB: [],
  };
  countsByOrgan: MatTableDataSource<CByOrgan> = new MatTableDataSource();
  displayedColumns: string[] = [
    'organName',
    'ASWithNoLink',
    'CTWithNoLink',
    'BWithNoLink',
    'ASWithNoCT',
    'CTWithNoB',
    'AS_AS',
    'AS_CT',
    'CT_BM',
    'anatomicalStructures',
    'cellTypes',
  ];
  biomarkersSeperateNames: BiomarkersNamesInReport[] = [];
  compareReport: CompareReport[] = [];
  clickButton = false; // for mat expansion panel download button

  @ViewChild(MatSort) sort!: MatSort;
  ontologyLinkGraphData: ReturnType<typeof this.makeOntologyLinksGraphData> = [];
  SheetConfig!: SheetConfig;
  total_AS_AS = 0;
  biomarkersCounts: BiomarkersCounts[] = [];

  @Input() compareSheets: CompareData[] = [];
  @Input() sheetData: Row[] = [];
  @Input() asFullData: Row[] = [];
  @Input() fullDataByOrgan: Row[][] = [];
  @Input() currentSheet!: Sheet;
  @Input() linksData$!: Observable<LinksASCTBData>;
  @Input() inputReportData!: Observable<Report>;
  @Input() currentSheetConfig!: Observable<SheetConfig>;
  @Input() compareData!: Observable<{ data: Row[]; sheets: CompareData[] }>;
  @Input() bmType = '';
  @Input() hideReportCompareTab = false;
  @Output() closeReport = new EventEmitter<void>();
  @Output() computedReport = new EventEmitter<Report>();
  @Output() deleteSheet = new EventEmitter<number>();
  total_AS_CT = 0;
  total_CT_B = 0;

  constructor(
    public reportService: ReportService,
    public ts: TreeService,
    public ga: GoogleAnalyticsService,
  ) {}

  ngOnInit(): void {
    this.reportService.reportData$.subscribe((data) => {
      this.reportData = data.data as Report;
      this.computedReport.emit(data.data as Report);

      this.ontologyLinkGraphData = this.makeOntologyLinksGraphData(data.data as Report, this.sheetData);
    });
    this.linksData$.subscribe((data) => {
      this.total_AS_AS = data.AS_AS;
      this.total_AS_CT = data.AS_CT;
      this.total_CT_B = data.CT_B;
    });

    this.reportService.compareData$.subscribe((data) => {
      this.compareReport = data.data;
    });

    this.currentSheetConfig.subscribe((data) => {
      this.SheetConfig = data;
    });

    this.compareData.subscribe((data) => {
      if (data.sheets.length && data.data.length) {
        this.reportService.makeCompareData(this.reportData, data.data, data.sheets);
      }
    });

    this.fullDataByOrgan.forEach((data) => {
      this.ts.makeTreeData(this.currentSheet, data, this.compareData, true);
    });

    this.reportService.makeReportData(this.currentSheet, this.sheetData, this.bmType, true);
  }

  makeOntologyLinksGraphData(reportData: Report, sheetData: Row[]) {
    const { result, biomarkersSeperateNames } = this.reportService.makeAllOrganReportDataByOrgan(
      sheetData,
      this.asFullData,
    );

    const biomarkerCols: string[] = [];
    biomarkersSeperateNames.forEach((bm) => {
      if (this.displayedColumns.includes(bm.name) === false) {
        biomarkerCols.push(bm.name);
      }
      this.displayedColumns = [
        'organName',
        'tableVersion',
        'anatomicalStructures',
        'cellTypes',
        'b_total',
        ...biomarkerCols,
        'ASWithNoLink',
        'CTWithNoLink',
        'BWithNoLink',
        'ASWithNoCT',
        'CTWithNoB',
        'AS_AS',
        'AS_CT',
        'CT_BM',
      ];
    });
    const tableVersions = new Map<string, string>();
    sheetData.forEach((element) => {
      if (!(element.organName in tableVersions.keys())) {
        tableVersions.set(element.organName, element.tableVersion);
      }
    });
    this.biomarkersSeperateNames = biomarkersSeperateNames;
    this.linksData$.subscribe((data) => {
      this.countsByOrgan = new MatTableDataSource(
        this.reportService
          .makeAllOrganReportDataCountsByOrgan(result, data, tableVersions)
          .sort((a, b) => a.organName?.localeCompare(b.organName ?? '') ?? 0),
      );
      this.biomarkersCounts = [];
      this.biomarkersSeperateNames.forEach((bm) => {
        this.biomarkersCounts.push({
          name: bm.name,
          value: this.countsByOrgan.data[0][bm.name as keyof CByOrgan] as number,
        });
      });
      this.countsByOrgan.sort = this.sort;
    });
    return [
      {
        results: [
          {
            name: 'with Uberon Links',
            value: reportData.anatomicalStructures.length - reportData.ASWithNoLink.length,
          },
          {
            name: 'without Uberon Links',
            value: reportData.ASWithNoLink.length,
          },
        ],
        label: 'Total Anatomical Structures',
      },
      {
        results: [
          {
            name: 'with CL Links',
            value: reportData.cellTypes.length - reportData.CTWithNoLink.length,
          },
          { name: 'without CL Links', value: reportData.CTWithNoLink.length },
        ],
        label: 'Total Cell Types',
      },
      {
        results: [
          {
            name: 'with HGNC Links',
            value: reportData.biomarkers.length - reportData.BWithNoLink.length,
          },
          { name: 'without HGNC Links', value: reportData.BWithNoLink.length },
        ],
        label: this.getBiomarkerLabel(this.bmType),
      },
    ];
  }

  getBiomarkerLabel(bmType: string) {
    return bmType === 'Gene'
      ? 'Total Gene Biomarkers'
      : bmType === 'Protein'
        ? 'Total Protein Biomarkers'
        : bmType === 'Lipids'
          ? 'Total Lipids Biomarkers'
          : bmType === 'Metabolites'
            ? 'Total Metabolites Biomarkers'
            : bmType === 'Proteoforms'
              ? 'Total Proteoforms Biomarkers'
              : 'Total Biomarkers';
  }

  customColors(v: string) {
    const mapper = {
      'with Uberon Links': '#E41A1C',
      'without Uberon Links': '#f5bcba',
      'with CL Links': '#377EB8',
      'without CL Links': '#abc9eb',
      'with HGNC Links': '#4DAF4A',
      'without HGNC Links': '#bce8be',
    };
    return mapper[v as keyof typeof mapper];
  }

  deleteCompareSheetReport(i: number) {
    this.clickButton = true;
    this.compareReport.splice(i, 1);
    this.deleteSheet.emit(i);

    this.ga.event(GaAction.CLICK, GaCategory.REPORT, 'Delete a sheet comparison', i);
  }

  getTotals(data: CByOrgan[], key: string) {
    return data
      .map((t) => (t[key as keyof CByOrgan] ? (t[key as keyof CByOrgan] as number) : 0))
      .reduce((acc, value) => acc + value, 0);
  }

  downloadData() {
    const download: Record<string, string>[] = [];
    const totalRows = 6;
    for (
      let i = 0;
      i <
      Math.max(
        this.reportData.anatomicalStructures.length,
        this.reportData.cellTypes.length,
        this.reportData.biomarkers.length,
      );
      i++
    ) {
      const row: Record<string, string> = {};
      if (i < this.reportData.anatomicalStructures.length) {
        row['Unique Anatomical Structures'] = this.reportData.anatomicalStructures[i].structure;
        if (!this.reportData.anatomicalStructures[i].uberon.includes('UBERON')) {
          row['AS with no Uberon Link'] = this.reportData.anatomicalStructures[i].structure;
        }
      }
      if (i < this.reportData.cellTypes.length) {
        row['Unique Cell Types'] = this.reportData.cellTypes[i].structure;
        row['CT ID'] = this.reportData.cellTypes[i].link;
        if (!this.reportData.cellTypes[i].link.includes('CL')) {
          row['CL with no Link'] = this.reportData.cellTypes[i].structure;
        }
      }
      if (i < this.reportData.biomarkers.length) {
        row['Unique Biomarkers'] = this.reportData.biomarkers[i].structure;
        row['BM ID'] = this.reportData.biomarkers[i].link;
      }
      if (i < this.reportData.BWithNoLink.length) {
        row['Biomarkers with no links'] = this.reportData.BWithNoLink[i].structure;
      }
      download.push(row);
    }

    const sheetWS = XLSX.utils.json_to_sheet(download);
    sheetWS['!cols'] = [];
    for (let i = 0; i < totalRows; i++) {
      sheetWS['!cols'].push({ wch: 30 });
    }
    const dt = moment(new Date()).format('YYYY.MM.DD_hh.mm');
    const sn = this.currentSheet.display.toLowerCase().replace(' ', '_');

    return {
      sheet: sheetWS,
      sheetName: this.currentSheet.display,
      name: `ASCT+B-Reporter_${sn}_${dt}_Report.xlsx`,
    };
  }

  downloadReport(i = -1) {
    const wb = XLSX.utils.book_new();
    const allReport = [];

    /**
     * When all reports need to be downloaded
     */
    if (i === -1) {
      allReport.push(this.downloadData());
      this.ga.event(GaAction.CLICK, GaCategory.REPORT, 'Download Full Report');

      if (this.compareReport) {
        for (const [sheet, _unused] of this.compareReport.entries()) {
          allReport.push(this.downloadCompareSheetReport(sheet));
        }
      }
    } else {
      /**
       * When a single compare sheet report needs to be downloaded
       * Not firing a Google Analytics event in this case since the downloadCompareSheetReport() method already does so.
       */
      allReport.push(this.downloadCompareSheetReport(i));
    }

    for (const book of allReport) {
      XLSX.utils.book_append_sheet(wb, book.sheet, book.sheetName);
    }

    XLSX.writeFile(wb, allReport[0].name);
  }

  downloadReportByOrgan() {
    const sheetName = 'countByOrgan';
    const fileName = 'countsByOrgans';
    const targetTableElm = document.getElementById('countsByOrgans');
    const allReport: ReturnType<typeof this.downloadData>[] = [];

    const organsList: string[] = [];

    const wb = XLSX.utils.table_to_book(targetTableElm, {
      sheet: sheetName,
    } as XLSX.Table2SheetOpts);

    this.fullDataByOrgan.forEach((data) => {
      organsList.push(data[0].organName);
      this.reportService.makeReportData(this.currentSheet, data, this.bmType);
      allReport.push(this.downloadData());
    });

    this.reportService.makeReportData(this.currentSheet, this.sheetData, this.bmType);

    let i = 0;
    for (const book of allReport) {
      XLSX.utils.book_append_sheet(wb, book.sheet, organsList[i]);
      i += 1;
    }

    XLSX.writeFile(wb, `${fileName}.xlsx`);
  }

  downloadCompareSheetReport(i: number) {
    this.clickButton = true;
    const totalRows = 6;
    const sheet = this.compareReport[i];
    const keyMapper = {
      identicalAS: 'Identical Anatomical Structures',
      newAS: 'New Anatomical Structres',
      identicalCT: 'Identical Cell Types',
      newCT: 'New Cell Types',
      identicalB: 'Identical Biomarkers',
      newB: 'New Biomarkers',
    };

    let download: Record<string, string>[] = [];
    const keys = Object.keys(this.compareReport[i]);

    for (const key of keys) {
      if (typeof sheet[key as keyof CompareReport] === 'object' && key in keyMapper) {
        for (const [idx, value] of (sheet[key as keyof CompareReport] as string[]).entries()) {
          const t: Record<string, string> = {};
          t[keyMapper[key as keyof typeof keyMapper]] = value;

          if (download[idx]) {
            download[idx] = { ...download[idx], ...t };
          } else {
            download.push(t);
          }
        }
      }
    }
    download = this.getBMCTAS(sheet.identicalBMCTPair as unknown as BmCtPairings[], download);
    const sheetWS = XLSX.utils.json_to_sheet(download, {
      header: Object.values(keyMapper),
    });

    sheetWS['!cols'] = [];
    for (let j = 0; j < totalRows; j++) {
      sheetWS['!cols'].push({ wch: 30 });
    }
    const dt = moment(new Date()).format('YYYY.MM.DD_hh.mm');
    const sn = sheet.title.toLowerCase().replace(' ', '_');

    this.ga.event(GaAction.CLICK, GaCategory.REPORT, 'Compare sheet download', sn as never);

    return {
      sheet: sheetWS,
      sheetName: sheet.title,
      name: `ASCT+B-Reporter_Derived_${sn}_${dt}_Report.xlsx`,
    };
  }

  getBMCTAS(bmCtPairs: BmCtPairings[], download: Record<string, string>[]) {
    const AS_CT_BM: Set<string> = new Set<string>();
    let index = 0;
    bmCtPairs.forEach((pair) => {
      const newPair = `${pair.AS_NAME} (${pair.AS_ID}), ${pair.CT_NAME} (${pair.CT_ID}), ${pair.BM_NAME}(${pair.BM_ID})`;
      if (!AS_CT_BM.has(newPair)) {
        AS_CT_BM.add(newPair);
        const t = {
          '': '',
          AS: `${pair.AS_NAME} (${pair.AS_ID})`,
          CT: `${pair.CT_NAME} (${pair.CT_ID})`,
          Biomarker: `${pair.BM_NAME} (${pair.BM_ID})`,
        };

        if (download[index]) {
          download[index] = { ...download[index], ...t };
        } else {
          download.push(t);
        }
        index += 1;
      }
    });
    return download;
  }
}
<app-sidenav>
  <div header>
    <app-sidenav-header
      [title]="'Report for ' + currentSheet.display"
      [download]="true"
      (downloadFn)="downloadReport()"
      [tooltipString]="'Various statistics calculated from the data'"
      (closeSideNav)="closeReport.emit()"
    >
    </app-sidenav-header>
  </div>

  <div body class="report">
    <mat-tab-group mat-stretch-tabs class="tabs px-4 mt-4">
      <mat-tab [label]="'Main Sheet'">
        <div class="content">
          <br />
          <div class="h5">Overview</div>
          <br />

          <div class="overview">
            <p class="text-muted mb-3">
              <small class="fw-bolder">UNIQUE ENTITIES</small>
            </p>
            <div class="d-flex justify-content-between align-content-center pr-5 h6">
              <span class="fw-normal">Anatomical structures</span>
              <span class="number fw-bolder numerical-padding">{{ reportData.anatomicalStructures.length }}</span>
            </div>
            <hr />
            <div class="d-flex justify-content-between align-content-center pr-5 h6">
              <span class="fw-normal">Cell types </span>
              <span class="number fw-bolder">{{ reportData.cellTypes.length }}</span>
            </div>
            <hr />
            <div class="d-flex justify-content-between align-content-center pr-5 h6">
              <span class="fw-normal">Biomarkers </span>
              <span class="number fw-bolder">{{ reportData.biomarkers.length }}</span>
            </div>
            <hr />
            <br />

            <p class="text-muted mb-3">
              <small class="fw-bolder">ENTITY LINKS</small>
            </p>
            <div class="d-flex justify-content-between align-content-center pr-5 h6">
              <span class="fw-normal"
                >Anatomical Structures <span class="badge bg-danger">part_of</span> AS links
              </span>
              <span class="number fw-bolder">{{ total_AS_AS }}</span>
            </div>
            <hr />
            <div class="d-flex justify-content-between align-content-center pr-5 h6">
              <span class="fw-normal">Cell Types <span class="badge badge-primary">located_in</span> AS links </span>
              <span class="number fw-bolder">{{ total_AS_CT }}</span>
            </div>
            <hr />
            <div class="d-flex justify-content-between align-content-center pr-5 h6">
              <span class="fw-normal">Biomarker <span class="badge bg-success">characterizes</span> CT links </span>
              <span class="number fw-bolder">{{ total_CT_B }}</span>
            </div>
            <hr />
            <br />

            <p class="text-muted mb-3">
              <small class="fw-bold">ONTOLOGY LINKS</small>
            </p>
            <div *ngFor="let report of ontologyLinkGraphData">
              <ngx-charts-advanced-pie-chart
                [customColors]="customColors"
                [view]="[600, 175]"
                [results]="report.results"
                class="w-100"
                [label]="report.label"
              >
              </ngx-charts-advanced-pie-chart>
            </div>
          </div>

          <br />

          <div class="h5 mt-3 mb-3">Details</div>

          <div class="details pr-4">
            <div *ngIf="countsByOrgan.data.length > 1">
              <div class="count-by-organ-title">
                <p class="text-muted mb-3">
                  <small class="fw-normal">Counts by Organ</small>
                </p>
                <div class="display-option" #tooltip="matTooltip" matTooltip="Export as Xlsx">
                  <button mat-icon-button (click)="downloadReportByOrgan()" class="mr-2">
                    <mat-icon>get_app</mat-icon>
                  </button>
                </div>
              </div>

              <table
                mat-table
                matSort
                id="countsByOrgans"
                [dataSource]="countsByOrgan"
                class="mat-elevation-z8 count_by_organ_table"
              >
                <caption class="sr-only">
                  Counts by Organ
                </caption>
                <!-- Organ Name  -->
                <ng-container matColumnDef="organName">
                  <th mat-sort-header mat-header-cell *matHeaderCellDef id="organName">Organ</th>
                  <td mat-cell *matCellDef="let element">
                    {{ element.organName | titlecase }}
                  </td>
                  <td mat-footer-cell *matFooterCellDef>Total Counts</td>
                </ng-container>

                <!-- hraVersion Column -->
                <ng-container matColumnDef="tableVersion">
                  <th mat-header-cell *matHeaderCellDef [hidden]="true" class="center_align" id="tableVersion">
                    table_version
                  </th>
                  <td mat-cell [hidden]="true" *matCellDef="let element" class="center_align">
                    {{ element.tableVersion ? element.tableVersion : 'unknown' }}
                  </td>
                  <td mat-footer-cell [hidden]="true" class="center_align" *matFooterCellDef>
                    {{ '' }}
                  </td>
                </ng-container>

                <!-- ASWithNoCT Column -->
                <ng-container matColumnDef="ASWithNoCT">
                  <th mat-header-cell *matHeaderCellDef [hidden]="true" class="center_align" id="ASWithNoCT">
                    ASWithNoCT
                  </th>
                  <td mat-cell [hidden]="true" *matCellDef="let element" class="center_align">
                    {{ element.ASWithNoCT ? element.ASWithNoCT : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" [hidden]="true" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'ASWithNoCT') }}
                  </td>
                </ng-container>

                <!-- CTWithNoB Column -->
                <ng-container matColumnDef="CTWithNoB">
                  <th mat-header-cell *matHeaderCellDef [hidden]="true" class="center_align" id="CTWithNoB">
                    CTWithNoB
                  </th>
                  <td mat-cell [hidden]="true" *matCellDef="let element" class="center_align">
                    {{ element.CTWithNoB ? element.CTWithNoB : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" [hidden]="true" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'CTWithNoB') }}
                  </td>
                </ng-container>

                <!-- ASWithNoLink Column -->
                <ng-container matColumnDef="ASWithNoLink">
                  <th mat-header-cell *matHeaderCellDef [hidden]="true" class="center_align" id="ASWithNoLink">
                    ASWithNoLink
                  </th>
                  <td mat-cell [hidden]="true" *matCellDef="let element" class="center_align">
                    {{ element.ASWithNoLink ? element.ASWithNoLink : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" [hidden]="true" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'ASWithNoLink') }}
                  </td>
                </ng-container>

                <!-- CTWithNoLink Column -->
                <ng-container matColumnDef="CTWithNoLink">
                  <th mat-header-cell *matHeaderCellDef [hidden]="true" class="center_align" id="CTWithNoLink">
                    CTWithNoLink
                  </th>
                  <td mat-cell [hidden]="true" *matCellDef="let element" class="center_align">
                    {{ element.CTWithNoLink ? element.CTWithNoLink : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" [hidden]="true" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'CTWithNoLink') }}
                  </td>
                </ng-container>

                <!-- BWithNoLink Column -->
                <ng-container matColumnDef="BWithNoLink">
                  <th mat-header-cell *matHeaderCellDef [hidden]="true" class="center_align" id="BWithNoLink">
                    BWithNoLink
                  </th>
                  <td mat-cell [hidden]="true" *matCellDef="let element" class="center_align">
                    {{ element.BWithNoLink ? element.BWithNoLink : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" [hidden]="true" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'BWithNoLink') }}
                  </td>
                </ng-container>

                <!-- AS_AS Column -->
                <ng-container matColumnDef="AS_AS">
                  <th mat-header-cell *matHeaderCellDef class="center_align" id="AS_AS">AS_AS</th>
                  <td mat-cell *matCellDef="let element" class="center_align">
                    {{ element.AS_AS ? element.AS_AS : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'AS_AS') }}
                  </td>
                </ng-container>

                <!-- AS_CT Column -->
                <ng-container matColumnDef="AS_CT">
                  <th mat-header-cell *matHeaderCellDef class="center_align" id="AS_CT">AS_CT</th>
                  <td mat-cell *matCellDef="let element" class="center_align">
                    {{ element.AS_CT ? element.AS_CT : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'AS_CT') }}
                  </td>
                </ng-container>

                <!-- CT_BM Column -->
                <ng-container matColumnDef="CT_BM">
                  <th mat-header-cell *matHeaderCellDef class="center_align" id="CT_BM">CT_BM</th>
                  <td mat-cell *matCellDef="let element" class="center_align">
                    {{ element.CT_BM ? element.CT_BM : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'CT_BM') }}
                  </td>
                </ng-container>

                <!-- Anatomical Structures Column -->
                <ng-container matColumnDef="anatomicalStructures">
                  <th mat-header-cell *matHeaderCellDef class="center_align" id="anatomicalStructures">AS</th>
                  <td mat-cell *matCellDef="let element" class="center_align">
                    {{ element.anatomicalStructures ? element.anatomicalStructures : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'anatomicalStructures') }}
                  </td>
                </ng-container>

                <!-- Cell Types Column -->
                <ng-container matColumnDef="cellTypes">
                  <th mat-header-cell *matHeaderCellDef class="center_align" id="cellTypes">CT</th>
                  <td mat-cell *matCellDef="let element" class="center_align">
                    {{ element.cellTypes ? element.cellTypes : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'cellTypes') }}
                  </td>
                </ng-container>

                <!-- Biomarkers Columns -->
                <ng-container matColumnDef="b_total">
                  <th mat-header-cell *matHeaderCellDef class="center_align" id="b_total">B_Total</th>
                  <td mat-cell *matCellDef="let element" class="center_align">
                    {{ element.biomarkers ? element.biomarkers : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, 'biomarkers') }}
                  </td>
                </ng-container>
                <ng-container *ngFor="let biomarker of biomarkersSeperateNames" matColumnDef="{{ biomarker.name }}">
                  <th mat-header-cell class="center_align" id="{{ biomarker.name }}" *matHeaderCellDef>
                    {{ biomarker.type }}
                  </th>
                  <td mat-cell class="center_align" *matCellDef="let element">
                    {{ element[biomarker.name] ? element[biomarker.name] : 0 }}
                  </td>
                  <td mat-footer-cell class="center_align" *matFooterCellDef>
                    {{ getTotals(countsByOrgan.data, biomarker.name) }}
                  </td>
                </ng-container>
                <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
                <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
                <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>
              </table>
            </div>
            <p class="text-muted my-3">
              <small class="fw-normal">Alphabetically sorted listings of all AS, CT, & B</small>
            </p>
            <mat-expansion-panel [expanded]="false">
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">
                    Unique Anatomical Structures
                    <span class="text-muted">({{ reportData.anatomicalStructures.length }})</span>
                  </div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div
                  *ngFor="let a of reportData.anatomicalStructures | orderBy: 'structure'"
                  class="py-1 d-flex justify-content-between align-items-center"
                >
                  <div class="h6 pr-2">
                    <span class="fw-normal"
                      >{{ a.structure }}
                      <span class="text-muted">({{ a.label ? a.label : 'label not found' }})</span></span
                    >
                  </div>

                  <div>
                    <span>{{ a.uberon }}</span>
                  </div>
                </div>
              </div>
            </mat-expansion-panel>
            <br />

            <mat-expansion-panel>
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">
                    Unique Cell Types
                    <span class="text-muted">({{ reportData.cellTypes.length }})</span>
                  </div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div
                  *ngFor="let a of reportData.cellTypes | orderBy: 'structure'"
                  class="py-1 d-flex justify-content-between align-items-center"
                >
                  <div class="h6">
                    <span class="fw-normal"
                      >{{ a.structure }}
                      <span class="text-muted">({{ a.label ? a.label : 'label not found' }})</span></span
                    >
                  </div>

                  <div>
                    <span>{{ a.link }}</span>
                  </div>
                </div>
              </div>
            </mat-expansion-panel>
            <br />

            <mat-expansion-panel>
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">
                    Unique biomarkers
                    <span class="text-muted">({{ reportData.biomarkers.length }})</span>
                  </div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div
                  *ngFor="let a of reportData.biomarkers | orderBy: 'structure'"
                  class="py-1 d-flex justify-content-between align-items-center"
                >
                  <div class="h6">
                    <span class="fw-normal">{{ a.structure }}</span>
                  </div>

                  <div>
                    <span>{{ a.link }}</span>
                  </div>
                </div>
              </div>
            </mat-expansion-panel>
            <br />

            <mat-expansion-panel *ngIf="countsByOrgan.data.length === 1">
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">Biomarker Counts By Type</div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div *ngFor="let a of biomarkersCounts" class="py-1 d-flex justify-content-between align-items-center">
                  <div class="h6">
                    <span class="fw-normal">{{ a.name + ' Biomarkers' | titlecase }}</span>
                  </div>

                  <div>
                    <span>{{ a.value }}</span>
                  </div>
                </div>
              </div>
            </mat-expansion-panel>
            <br />

            <p class="text-muted my-3">
              <small class="fw-normal">Missing Ontology Links</small>
            </p>

            <mat-expansion-panel>
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">
                    Anatomical Structures with no Uberon link
                    <span class="text-muted">({{ reportData.ASWithNoLink.length }})</span>
                  </div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div
                  *ngFor="let a of reportData.ASWithNoLink | orderBy: 'structure'"
                  class="py-1 d-flex justify-content-between align-items-center"
                >
                  <div class="h6">
                    <span class="fw-normal"
                      >{{ a.structure }}
                      <span class="text-muted">({{ a.label ? a.label : 'label not found' }})</span></span
                    >
                  </div>
                </div>
              </div>
            </mat-expansion-panel>
            <br />

            <mat-expansion-panel>
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">
                    Cell Types with no CL link
                    <span class="text-muted">({{ reportData.CTWithNoLink.length }})</span>
                  </div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div
                  *ngFor="let a of reportData.CTWithNoLink | orderBy: 'structure'"
                  class="py-1 d-flex justify-content-between align-items-center"
                >
                  <div class="h6">
                    <span class="fw-normal"
                      >{{ a.structure }}
                      <span class="text-muted">({{ a.label ? a.label : 'label not found' }})</span></span
                    >
                  </div>
                </div>
              </div>
            </mat-expansion-panel>
            <br />

            <mat-expansion-panel>
              <mat-expansion-panel-header>
                <mat-panel-title>
                  <div class="h6 m-0">
                    Biomarkers with no HGNC links
                    <span class="text-muted">({{ reportData.BWithNoLink.length }})</span>
                  </div>
                </mat-panel-title>
              </mat-expansion-panel-header>

              <div class="mt-2">
                <div
                  *ngFor="let a of reportData.BWithNoLink | orderBy: 'structure'"
                  class="py-1 d-flex justify-content-between align-items-center"
                >
                  <div class="h6">
                    <span class="fw-normal">{{ a.structure }}</span>
                  </div>
                </div>
              </div>
            </mat-expansion-panel>

            <br />
          </div>
          <br />
        </div>
      </mat-tab>
      <mat-tab *ngIf="!hideReportCompareTab" label="Compare Sheets">
        <div *ngIf="(compareData | async)?.data?.length === 0">
          <p class="i2">You have not linked any sheets to compare yet.</p>
        </div>
        <div *ngIf="((compareData | async)?.data?.length ?? 0) > 0">
          <br />
          <div *ngFor="let sheet of compareReport; let i = index">
            <mat-expansion-panel hideToggle="true" [disabled]="clickButton" (click)="clickButton = false">
              <mat-expansion-panel-header [style.backgroundColor]="sheet.color" class="compare">
                <mat-panel-title>
                  <div class="text-white h6 m-0">
                    {{ sheet.title }}
                  </div>
                </mat-panel-title>
                <mat-panel-description>
                  <button mat-icon-button (click)="downloadReport(i)" class="download-report">
                    <mat-icon>get_app</mat-icon>
                  </button>
                  <button mat-icon-button (click)="deleteCompareSheetReport(i)" class="delete-report">
                    <mat-icon>delete</mat-icon>
                  </button>
                </mat-panel-description>
              </mat-expansion-panel-header>

              <div class="pt-2">
                <p class="sheet-description pt-2">
                  {{ sheet.description }}
                </p>
                <div class="title2">Overview</div>

                <div class="overview">
                  <div class="i1">
                    <span>Identical anatomical structures: </span>
                    <span class="number">{{ sheet.identicalAS.length }}</span>
                  </div>
                  <div class="i1">
                    <span>Identical cell types: </span>
                    <span class="number">{{ sheet.identicalCT.length }}</span>
                  </div>
                  <div class="i1">
                    <span>Identical biomarkers: </span>
                    <span class="number">{{ sheet.identicalB.length }}</span>
                  </div>
                  <br />

                  <div class="i1">
                    <span>New anatomical structures: </span>
                    <span class="number">{{ sheet.newAS.length }}</span>
                  </div>
                  <div class="i1">
                    <span>New cell types: </span>
                    <span class="number">{{ sheet.newCT.length }}</span>
                  </div>
                  <div class="i1">
                    <span>New biomarkers: </span>
                    <span class="number">{{ sheet.newB.length }}</span>
                  </div>
                  <br />
                </div>

                <div class="title2">Details</div>

                <mat-expansion-panel>
                  <mat-expansion-panel-header class="mb-2">
                    <div class="report-expansion-header">Identical Anatomical Structures</div>
                  </mat-expansion-panel-header>
                  <div class="i2" *ngFor="let ia of sheet.identicalAS">
                    {{ ia }}
                  </div>
                </mat-expansion-panel>

                <mat-expansion-panel class="mt-2">
                  <mat-expansion-panel-header class="mb-2">
                    <div class="report-expansion-header">Identical Cell Types</div>
                  </mat-expansion-panel-header>
                  <div class="i2" *ngFor="let ia of sheet.identicalCT">
                    {{ ia }}
                  </div>
                </mat-expansion-panel>

                <mat-expansion-panel class="mt-2">
                  <mat-expansion-panel-header class="mb-2">
                    <div class="report-expansion-header">Identical Biomarkers</div>
                  </mat-expansion-panel-header>
                  <div class="i2" *ngFor="let ia of sheet.identicalB">
                    {{ ia }}
                  </div>
                </mat-expansion-panel>

                <mat-expansion-panel class="mt-2">
                  <mat-expansion-panel-header class="mb-2">
                    <div class="report-expansion-header">New Anatomical Structures</div>
                  </mat-expansion-panel-header>
                  <div class="i2" *ngFor="let ia of sheet.newAS">
                    {{ ia }}
                  </div>
                </mat-expansion-panel>

                <mat-expansion-panel class="mt-2">
                  <mat-expansion-panel-header class="mb-2">
                    <div class="report-expansion-header">New Cell Types</div>
                  </mat-expansion-panel-header>
                  <div class="i2" *ngFor="let ia of sheet.newCT">
                    {{ ia }}
                  </div>
                </mat-expansion-panel>

                <mat-expansion-panel class="mt-2">
                  <mat-expansion-panel-header class="mb-2">
                    <div class="report-expansion-header">New Biomarkers</div>
                  </mat-expansion-panel-header>
                  <div class="i2" *ngFor="let ia of sheet.newB">
                    {{ ia }}
                  </div>
                </mat-expansion-panel>
              </div>
            </mat-expansion-panel>

            <br />
          </div>
        </div>
      </mat-tab>
    </mat-tab-group>
  </div>
</app-sidenav>

./report.component.scss

.report {
  width: 43.75rem;
}
.download-report {
  color: white;
}
.count_by_organ_table {
  width: 100%;
  box-shadow: none;
  border: solid 1px #f5f5f5;
  border-collapse: collapse;
}
tr.mat-footer-row {
  font-weight: bold;
}
.count-by-organ-title {
  display: flex;
  justify-content: space-between;
}
th.mat-header-cell:last-of-type,
td.mat-cell:last-of-type,
td.mat-footer-cell:last-of-type {
  padding-right: unset !important;
}
.center_align {
  text-align: center;
}
.delete-report {
  margin-left: 0.25rem;
  margin-top: -0.1875rem;
  color: white;
}
.sheet-description {
  color: grey;
  font-style: italic;
}
.report-expansion-header {
  font-weight: 400;
  font-size: 12pt;
}
.date {
  color: grey;
  font-size: 9pt;
}
hr {
  margin-top: 0.625rem;
  margin-bottom: 0.625rem;
}

::ng-deep .mat-list-item-content {
  padding: 0 !important;
  margin-top: -0.625rem;
}

::ng-deep .mat-subheader {
  padding: 0 !important;
}

::ng-deep .mat-tab-body {
  text-align: left;
}

.content {
  margin-top: 0.9375rem;
  z-index: 1;
}

.title {
  font-size: 20pt;
  line-height: 1.6;
}

.title1 {
  font-size: 18pt;
  font-weight: 400;
  margin-bottom: 1.25rem;
}

.title2 {
  font-size: 14pt;
  font-weight: 400;
  margin-bottom: 0.9375rem;
}

.i1 {
  font-size: 14pt;
  margin-top: 0.625rem;
  margin-bottom: 0.625rem;
  font-weight: 300;
}

.i1:hover {
  color: #1976d2;
}

.i2 {
  font-size: 12pt;
  margin-top: 0.625rem;
  margin-bottom: 0.625rem;
  font-weight: 300;
}

.footer {
  position: absolute;
  bottom: 0rem;
  height: 3.75rem;
  left: 0rem;
  right: 0rem;
  padding-left: 0.3125rem;
  padding-right: 0.3125rem;
  padding-top: 0.9375rem;
  display: flex;
  z-index: 2;
  align-items: center;
  justify-content: space-between;
  border-top: 0.0625rem solid rgb(203, 203, 203);
}

// .overview {
//   font-size: 14pt;
// }

.number {
  font-weight: 400;
  padding-right: 3.1rem;
}

.details {
  font-size: 14pt;
}

.mat-expansion-panel:not([class*='mat-elevation-z']) {
  box-shadow: none;
}

.mat-expansion-panel-header:not(.compare) {
  background: #f5f5f5 !important;
}

.mat-expansion-panel-header:hover {
  opacity: 0.85 !important;
}

.compare .mat-expansion-panel-header-description {
  justify-content: flex-end !important;
  align-items: center;
  margin-right: 0 !important;
}

.compare .mat-expansion-panel-header-description {
  flex-basis: 0;
}

.compare .mat-expansion-panel-header-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

::ng-deep.mat-expansion-indicator {
  margin-top: -0.3125rem !important;
}

.example-spacer {
  flex: 1 1 auto;
}

.tabs {
  position: absolute;
  top: 4.0625rem;
  bottom: 3.125rem;
  overflow: auto;
  right: 0rem;
  left: 0rem;
  padding-left: 0.3125rem;
  padding-right: 0.3125rem;
  /* height: 100%; */
  /* flex: 1 1 auto; */
}
.loader {
  height: 100%;
  justify-content: center;
  align-items: center;
  display: flex;
  flex-direction: column;
}

.loader > embed {
  display: block;
  width: 9.375rem;
  height: 4.6875rem;
  text-align: center;
}

.dbtn {
  border: 0.0625rem solid #444a65;
  border-radius: 0.5rem;
  width: 100%;
  transition: all 0.3s;
}

.dbtn:hover {
  background-color: #444a65;
  color: white;
}

// CHART

::ng-deep .advanced-pie-legend .total-value {
  font-size: 1.25rem !important;
  font-weight: 600;
  margin-bottom: 0.3125rem !important;
}

::ng-deep .advanced-pie-legend .total-label {
  font-size: 1rem !important;
  margin-bottom: 0.625rem !important;
}

::ng-deep .advanced-pie-legend .legend-items-container .legend-items .legend-item .item-value {
  font-size: 1rem !important;
  font-weight: 600;
}

::ng-deep .advanced-pie-legend .legend-items-container .legend-items .legend-item .item-percent {
  display: none;
}

// ::ng-deep .advanced-pie-legend .legend-items-container .legend-items .legend-item .item-label {
// }

::ng-deep .advanced-pie-legend .legend-items-container .legend-items .legend-item .item-value {
  padding-bottom: 0.3125rem;
  padding-top: 0.3125rem;
}

.badge-primary {
  background-color: #377eb8 !important;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""