Skip to content

Commit

Permalink
Simple entry point. Fetch MAF records and write them to zip file
Browse files Browse the repository at this point in the history
  • Loading branch information
forus committed Dec 14, 2024
1 parent b420015 commit 84cb1d4
Show file tree
Hide file tree
Showing 8 changed files with 427 additions and 70 deletions.
78 changes: 78 additions & 0 deletions src/main/java/org/cbioportal/file/export/MafRecordFetcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.cbioportal.file.export;

import org.cbioportal.file.model.MafRecord;
import org.cbioportal.model.MolecularProfile;
import org.cbioportal.model.Mutation;
import org.cbioportal.service.MolecularProfileService;
import org.cbioportal.service.MutationService;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
public class MafRecordFetcher {

private final MolecularProfileService molecularProfileService;
private final MutationService mutationService;

public MafRecordFetcher(MolecularProfileService molecularProfileService, MutationService mutationService) {
this.molecularProfileService = molecularProfileService;
this.mutationService = mutationService;
}

public Iterator<MafRecord> fetch(Map<String, Set<String>> sampleIdsByStudyId) {
List<String> studyIds = List.copyOf(sampleIdsByStudyId.keySet());
List<String> molecularProfileStableIds = this.molecularProfileService.getMolecularProfilesInStudies(studyIds, "ID").stream()
.map(MolecularProfile::getStableId).toList();
List<String> sampleIds = List.copyOf(sampleIdsByStudyId.values().stream().flatMap(Set::stream).toList());
List<Integer> entrezGeneIds = List.of();
List<Mutation> mutationList = mutationService.getMutationsInMultipleMolecularProfiles(
molecularProfileStableIds, sampleIds, entrezGeneIds, "EXPORT", null, null, null, null);
return mutationList.stream()
.filter(mutation -> sampleIdsByStudyId.get(mutation.getStudyId()).contains(mutation.getSampleId()))
.map(mutation -> new MafRecord(
mutation.getGene().getHugoGeneSymbol(),
mutation.getGene().getEntrezGeneId().toString(),
mutation.getCenter(),
mutation.getNcbiBuild(),
mutation.getChr(),
mutation.getStartPosition(),
mutation.getEndPosition(),
"+",
mutation.getMutationType(),
mutation.getVariantType(),
mutation.getReferenceAllele(),
mutation.getTumorSeqAllele(),
//TODO check if this is correct
mutation.getTumorSeqAllele(),
mutation.getDbSnpRs(),
mutation.getDbSnpValStatus(),
mutation.getSampleId(),
mutation.getMatchedNormSampleBarcode(),
mutation.getMatchNormSeqAllele1(),
mutation.getMatchNormSeqAllele2(),
mutation.getTumorValidationAllele1(),
mutation.getTumorValidationAllele2(),
mutation.getMatchNormValidationAllele1(),
mutation.getMatchNormValidationAllele2(),
mutation.getVerificationStatus(),
mutation.getValidationStatus(),
mutation.getMutationStatus(),
mutation.getSequencingPhase(),
mutation.getSequenceSource(),
mutation.getValidationMethod(),
mutation.getScore() == null ? null : mutation.getScore().toString(),
mutation.getBamFile(),
mutation.getSequencer(),
//TODO how to calculate HgvpShort?
"",
mutation.getTumorAltCount(),
mutation.getTumorRefCount(),
mutation.getNormalAltCount(),
mutation.getNormalRefCount()
)).iterator();
}
}
8 changes: 4 additions & 4 deletions src/main/java/org/cbioportal/file/model/MafRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public record MafRecord(
/**
* Start position of event.
*/
Integer startPosition,
Long startPosition,

/**
* End position of event.
*/
Integer endPosition,
Long endPosition,

/**
* We assume that the mutation is reported for the + strand.
Expand Down Expand Up @@ -150,12 +150,12 @@ public record MafRecord(
String validationMethod,

/**
* Not used.
* Score
*/
String score,

/**
* Not used.
* The BAM file used to call the variant.
*/
String bamFile,

Expand Down
143 changes: 143 additions & 0 deletions src/main/java/org/cbioportal/model/Mutation.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ public class Mutation extends Alteration implements Serializable {
@JsonRawValue
@Schema(type = "java.util.Map")
private Object annotationJSON;
private String dbSnpRs;
private String dbSnpValStatus;
private String matchedNormSampleBarcode;
private String matchNormSeqAllele1;
private String matchNormSeqAllele2;
private String tumorValidationAllele1;
private String tumorValidationAllele2;
private String matchNormValidationAllele1;
private String matchNormValidationAllele2;
private String verificationStatus;
private String sequencingPhase;
private String sequenceSource;
private String validationMethod;
private BigDecimal score;
private String bamFile;
private String sequencer;

public String getCenter() {
return center;
Expand Down Expand Up @@ -213,4 +229,131 @@ public void setAnnotationJSON(String annotationJSON) {
this.annotationJSON = annotationJSON;
}

public String getDbSnpRs() {
return dbSnpRs;
}

public void setDbSnpRs(String dbSnpRs) {
this.dbSnpRs = dbSnpRs;
}

public String getDbSnpValStatus() {
return dbSnpValStatus;
}

public void setDbSnpValStatus(String dbSnpValStatus) {
this.dbSnpValStatus = dbSnpValStatus;
}

public String getMatchedNormSampleBarcode() {
return matchedNormSampleBarcode;
}

public void setMatchedNormSampleBarcode(String matchedNormSampleBarcode) {
this.matchedNormSampleBarcode = matchedNormSampleBarcode;
}

public String getMatchNormSeqAllele1() {
return matchNormSeqAllele1;
}

public void setMatchNormSeqAllele1(String matchNormSeqAllele1) {
this.matchNormSeqAllele1 = matchNormSeqAllele1;
}

public String getMatchNormSeqAllele2() {
return matchNormSeqAllele2;
}

public void setMatchNormSeqAllele2(String matchNormSeqAllele2) {
this.matchNormSeqAllele2 = matchNormSeqAllele2;
}

public String getTumorValidationAllele1() {
return tumorValidationAllele1;
}

public void setTumorValidationAllele1(String tumorValidationAllele1) {
this.tumorValidationAllele1 = tumorValidationAllele1;
}

public String getTumorValidationAllele2() {
return tumorValidationAllele2;
}

public void setTumorValidationAllele2(String tumorValidationAllele2) {
this.tumorValidationAllele2 = tumorValidationAllele2;
}

public String getMatchNormValidationAllele1() {
return matchNormValidationAllele1;
}

public void setMatchNormValidationAllele1(String matchNormValidationAllele1) {
this.matchNormValidationAllele1 = matchNormValidationAllele1;
}

public String getMatchNormValidationAllele2() {
return matchNormValidationAllele2;
}

public void setMatchNormValidationAllele2(String matchNormValidationAllele2) {
this.matchNormValidationAllele2 = matchNormValidationAllele2;
}

public String getVerificationStatus() {
return verificationStatus;
}

public void setVerificationStatus(String verificationStatus) {
this.verificationStatus = verificationStatus;
}

public String getSequencingPhase() {
return sequencingPhase;
}

public void setSequencingPhase(String sequencingPhase) {
this.sequencingPhase = sequencingPhase;
}

public String getSequenceSource() {
return sequenceSource;
}

public void setSequenceSource(String sequenceSource) {
this.sequenceSource = sequenceSource;
}

public String getValidationMethod() {
return validationMethod;
}

public void setValidationMethod(String validationMethod) {
this.validationMethod = validationMethod;
}

public BigDecimal getScore() {
return score;
}

public void setScore(BigDecimal score) {
this.score = score;
}

public String getBamFile() {
return bamFile;
}

public void setBamFile(String bamFile) {
this.bamFile = bamFile;
}

public String getSequencer() {
return sequencer;
}

public void setSequencer(String sequencer) {
this.sequencer = sequencer;
}
}
116 changes: 57 additions & 59 deletions src/main/java/org/cbioportal/service/impl/ExportService.java
Original file line number Diff line number Diff line change
@@ -1,76 +1,74 @@
package org.cbioportal.service.impl;

import org.apache.commons.lang3.tuple.Pair;
import org.cbioportal.model.*;
import org.cbioportal.file.export.MafRecordFetcher;
import org.cbioportal.file.export.MafRecordWriter;
import org.cbioportal.model.CancerStudy;
import org.cbioportal.model.Sample;
import org.cbioportal.service.*;
import org.cbioportal.service.exception.MolecularProfileNotFoundException;
import org.cbioportal.service.exception.PatientNotFoundException;
import org.cbioportal.service.exception.SampleNotFoundException;
import org.cbioportal.service.exception.StudyNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.cbioportal.service.util.SessionServiceRequestHandler;
import org.cbioportal.web.parameter.VirtualStudy;
import org.cbioportal.web.parameter.VirtualStudySamples;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class ExportService {

@Autowired
PatientService patientService;

@Autowired
SampleService sampleService;

@Autowired
ClinicalDataService clinicalDataService;

@Autowired
MutationService mutationService;

@Autowired
MolecularProfileService molecularProfileService;
private final StudyService studyService;
private final SessionServiceRequestHandler sessionServiceRequestHandler;
private final SampleService sampleService;
private final MafRecordFetcher mafRecordFetcher;

public ExportService(StudyService studyService,
SessionServiceRequestHandler sessionServiceRequestHandler,
SampleService sampleService,
MafRecordFetcher mafRecordFetcher) {
this.studyService = studyService;
this.sessionServiceRequestHandler = sessionServiceRequestHandler;
this.sampleService = sampleService;
this.mafRecordFetcher = mafRecordFetcher;
}

public void exportData(Map<String, List<String>> samples) throws SampleNotFoundException, StudyNotFoundException, PatientNotFoundException, MolecularProfileNotFoundException {
if (samples.size() > 1) {
//virtual study
public ByteArrayOutputStream exportStudyDataToZip(String studyId) throws IOException {
List<CancerStudy> studies = studyService.fetchStudies(List.of(studyId), "DETAILED");
Map<String, Set<String>> studyToSampleMap = new HashMap<>();
if (studies.isEmpty()) {
VirtualStudy virtualStudy = sessionServiceRequestHandler.getVirtualStudyById(studyId);
studyToSampleMap.putAll(
virtualStudy.getData().getStudies().stream().collect(Collectors.toMap(VirtualStudySamples::getId, VirtualStudySamples::getSamples)));
} else {
List<Sample> samples = sampleService.getAllSamplesInStudies(List.of(studyId), "ID", null, null, null, null);
studyToSampleMap.put(studyId, samples.stream().map(Sample::getStableId).collect(Collectors.toSet()));
}
for (Map.Entry<String, List<String>> studySamples: samples.entrySet()) {
String studyId = studySamples.getKey();
for (String sampleId: studySamples.getValue()) {
Sample sample = sampleService.getSampleInStudy(studyId, sampleId);
String patientStableId = sample.getPatientStableId();
String sampleStableId = sample.getStableId();
List<ClinicalData> sampleClinicalData = clinicalDataService.getAllClinicalDataOfSampleInStudy(studyId, sampleStableId, null, null, null, null, null, null);
for (ClinicalData sampleClinicalDatum : sampleClinicalData) {
ClinicalAttribute clinicalAttribute = sampleClinicalDatum.getClinicalAttribute();
sampleClinicalDatum.getAttrId();
sampleClinicalDatum.getAttrValue();
}
Patient patient = patientService.getPatientInStudy(studyId, patientStableId);
List<ClinicalData> patientClinicalData = clinicalDataService.getAllClinicalDataOfPatientInStudy(studyId, patientStableId, null, null, null, null, null, null);
for (ClinicalData patientClinicalDataItem : patientClinicalData) {
ClinicalAttribute clinicalAttribute = patientClinicalDataItem.getClinicalAttribute();
patientClinicalDataItem.getAttrId();
patientClinicalDataItem.getAttrValue();
}
}
List<MolecularProfileCaseIdentifier> molecularProfileCaseIdentifiers = molecularProfileService.getMolecularProfileCaseIdentifiers(List.of(studyId), studySamples.getValue());
for (MolecularProfileCaseIdentifier molecularProfileCaseIdentifier : molecularProfileCaseIdentifiers) {
MolecularProfile molecularProfile = molecularProfileService.getMolecularProfile(molecularProfileCaseIdentifier.getMolecularProfileId());
MolecularProfile.MolecularAlterationType molecularAlterationType = molecularProfile.getMolecularAlterationType();
molecularProfile.getDatatype();
molecularProfile.getName();
switch (molecularAlterationType) {
case MUTATION_EXTENDED -> {
List<Mutation> mutationList = mutationService.getMutationsInMultipleMolecularProfilesByGeneQueries(List.of(molecularProfileCaseIdentifier.getMolecularProfileId()), studySamples.getValue(), List.of(), "DETAILED", 10000, 1, null, null);
for (Mutation mutation : mutationList) {
mutation.getChr();
}
}
}
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
// Add files to the ZIP
StringWriter mafRecordsStringWriter = new StringWriter();
MafRecordWriter mafRecordWriter = new MafRecordWriter(mafRecordsStringWriter);
//TODO do not produce the file if no data has been retrieved
mafRecordWriter.write(mafRecordFetcher.fetch(studyToSampleMap));
addFileToZip(zipOutputStream, "data_mutation.txt", mafRecordsStringWriter.toString().getBytes());
}
return byteArrayOutputStream;
}

private void addFileToZip(ZipOutputStream zipOutputStream, String fileName, byte[] fileContent) throws IOException {
// Create a new ZIP entry for the file
ZipEntry zipEntry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(zipEntry);

// Write file content
zipOutputStream.write(fileContent);
zipOutputStream.closeEntry();
}
}
Loading

0 comments on commit 84cb1d4

Please sign in to comment.