Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package br.ufc.deti.ecgweb.domain.exam; import br.ufc.deti.ecgweb.application.controller.ServiceUploadDuplicatedActionException; import br.ufc.deti.ecgweb.domain.client.*; import br.ufc.deti.ecgweb.domain.repositories.AnnotationRepository; import br.ufc.deti.ecgweb.domain.repositories.DoctorRepository; import br.ufc.deti.ecgweb.domain.repositories.EcgChannelRepository; import br.ufc.deti.ecgweb.domain.repositories.EcgFileRepository; import br.ufc.deti.ecgweb.domain.repositories.EcgReportRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import br.ufc.deti.ecgweb.domain.repositories.EcgRepository; import br.ufc.deti.ecgweb.domain.repositories.EcgSignalRangeRepository; import br.ufc.deti.ecgweb.domain.repositories.EcgSignalRepository; import br.ufc.deti.ecgweb.domain.repositories.MitBihClientRepository; import br.ufc.deti.ecgweb.domain.repositories.PWaveRepository; import br.ufc.deti.ecgweb.domain.repositories.PatientRepository; import br.ufc.deti.ecgweb.domain.repositories.QrsComplexRepository; import br.ufc.deti.ecgweb.domain.repositories.TWaveRepository; import br.ufc.deti.ecgweb.utils.algorithms.AbstractComplexQrsAlgorithm; import br.ufc.deti.ecgweb.utils.algorithms.AbstractPWaveAlgorithm; import br.ufc.deti.ecgweb.utils.algorithms.AbstractTWaveAlgorithm; import br.ufc.deti.ecgweb.utils.algorithms.EcgArtifacts; import br.ufc.deti.ecgweb.utils.algorithms.PWaveAlgorithmFactory; import br.ufc.deti.ecgweb.utils.algorithms.QrsComplexAlgorithmFactory; import br.ufc.deti.ecgweb.utils.algorithms.TWaveAlgorithmFactory; import br.ufc.deti.ecgweb.utils.ecgformat.HL7FormatImpl; import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.springframework.transaction.annotation.Transactional; /** * * @author Marcelo Araujo Lima */ @Service public class EcgService { private final Lock lock = new ReentrantLock(true); private static final Map<Long, File> uploadFileMap = Collections.synchronizedMap(new HashMap<Long, File>()); /*@Autowired private Logger logger;*/ //private Logger logger = (Logger) LoggerFactory.getLogger(EcgService.class); @Autowired private PatientRepository patientRepository; @Autowired private DoctorRepository doctorRepository; @Autowired private EcgRepository ecgRepository; @Autowired private EcgReportRepository ecgReportRepository; @Autowired private EcgChannelRepository ecgChannelRepository; @Autowired private EcgSignalRepository ecgSignalRepository; @Autowired private MitBihClientRepository mitbihRepository; @Autowired private QrsComplexRepository qrsComplexRepository; @Autowired private PWaveRepository pWaveRepository; @Autowired private TWaveRepository tWaveRepository; @Autowired private EcgSignalRangeRepository ecgSignalRangeRepository; @Autowired private EcgFileRepository ecgFileRepository; @Autowired private AnnotationRepository annotationRepository; public synchronized void addUploadFile(Long key, File file) { uploadFileMap.put(key, file); } public synchronized void removeUploadFile(Long key) { uploadFileMap.remove(key); } public synchronized File getUploadFile(Long key) { return uploadFileMap.get(key); } @Transactional public void addEcg(Long clientId, LocalDateTime examDate, Long sampleRate, Long durationMs, Long baseLine, Long gain, Boolean finished, String description) { Ecg ecg = new Ecg(); ecg.setExamDate(examDate); ecg.setSampleRate(sampleRate); ecg.setBaseLine(baseLine); ecg.setGain(gain); ecg.setFinished(finished); ecg.setDescription(description); ecgRepository.save(ecg); Patient patient = patientRepository.findOne(clientId); patient.addEcgExam(ecg); patientRepository.save(patient); } public List<Ecg> listAllEcgsPerPatient(Long patientId) { Patient patient = patientRepository.findOne(patientId); return patient.getExams(); } @Transactional public void editReport(Long ecgId, String report) { EcgReport report_ = new EcgReport(); report_.setReport(report); ecgReportRepository.save(report_); Ecg ecg = ecgRepository.findOne(ecgId); ecg.setReport(report_); ecgRepository.save(ecg); } public String getReport(Long ecgId) { Ecg ecg = ecgRepository.findOne(ecgId); if (ecg.getReport() == null) { return ""; } return ecg.getReport().getReport(); } @Transactional public void setEcgStatus(Long ecgId) { Ecg ecg = ecgRepository.findOne(ecgId); ecg.setFinished(true); ecgRepository.save(ecg); } @Transactional public void addEcgChannel(Long ecgId, EcgLeadType leadType) { Ecg ecg = ecgRepository.findOne(ecgId); EcgChannel channel = new EcgChannel(); channel.setLeadType(leadType); channel.setEcg(ecg); ecgChannelRepository.save(channel); ecg.addChannel(channel); ecgRepository.save(ecg); } public List<EcgChannel> getChannels(Long ecgId) { Ecg ecg = ecgRepository.findOne(ecgId); return ecg.getChannels(); } @Transactional public void addEcgSignal(Long channelId, Integer idx, Double intensity) { EcgSignal signal = new EcgSignal(); signal.setSampleIdx(idx); signal.setyIntensity(intensity); ecgSignalRepository.save(signal); EcgChannel channel = ecgChannelRepository.findOne(channelId); channel.addSignal(signal); ecgChannelRepository.save(channel); } public List<EcgSignal> getSignals(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); return channel.getSignals(); } public Long getNumberOfIndexByTime(Long channelId, Long timeWindow) { EcgChannel channel = ecgChannelRepository.findOne(channelId); Long frequency = channel.getEcg().getSampleRate(); Long numberOfSignals = (long) channel.getSignals().size(); double timeInSeconds = numberOfSignals / frequency; Double numberOfIndexInWindowSeconds = timeInSeconds / timeWindow; Long roundValue = Math.round(numberOfIndexInWindowSeconds); if (roundValue < numberOfIndexInWindowSeconds) { roundValue++; } System.out.println(numberOfIndexInWindowSeconds + ":" + roundValue); return roundValue; } public List<EcgSignal> getSignalsByTimeIndex(Long channelId, Long idx, Long timeInSeconds) { EcgChannel channel = ecgChannelRepository.findOne(channelId); Long frequency = channel.getEcg().getSampleRate(); Long firstIdx = frequency * timeInSeconds * idx; Long lastIndex = firstIdx + (frequency * timeInSeconds); List<EcgSignal> signals = channel.getSignals(); if (lastIndex >= signals.size()) lastIndex = (long) signals.size(); return signals.subList(firstIdx.intValue(), lastIndex.intValue()); } public List<EcgSignalRange> getQrsComplexFromAlgorithm(Long channelId, Long algorithmId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); List<EcgSignal> signals = channel.getSignals(); int sampleRate = channel.getEcg().getSampleRate().intValue(); AbstractComplexQrsAlgorithm algorithm = QrsComplexAlgorithmFactory .getComplexQrsAlgorithm(algorithmId.intValue()); if (algorithm == null) { return new ArrayList<EcgSignalRange>(); } return algorithm.getQrsComplex(signals, sampleRate); } public List<EcgSignalRange> getQrsComplex(Long channelId, Long doctorId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); if (channel.getQrsComplex() == null) { AbstractComplexQrsAlgorithm algorithm = QrsComplexAlgorithmFactory.getComplexQrsAlgorithm(1); setQrsComplex(doctorId, channelId, algorithm.getQrsComplex(channel.getSignals(), channel.getEcg().getSampleRate().intValue())); } return channel.getQrsComplex().getInterlvals(); } private void qrsDeleteAllSignalsRange(Doctor doctor, QrsComplex qrs, List<EcgSignalRange> signalsRange) { for (EcgSignalRange ecgSignalRange : signalsRange) { ecgSignalRangeRepository.delete(ecgSignalRange.getId()); } qrs.setDoctor(doctor); qrs.clearWaves(); qrsComplexRepository.saveAndFlush(qrs); } private void qrsUpdateSignalsRange(Doctor doctor, QrsComplex qrs, List<EcgSignalRange> signalsRange) { for (EcgSignalRange ecgSignalRange : signalsRange) { ecgSignalRangeRepository.saveAndFlush(ecgSignalRange); qrs.addInterval(ecgSignalRange); } qrs.setDoctor(doctor); qrsComplexRepository.saveAndFlush(qrs); } @Transactional public void setQrsComplex(Long doctorId, Long channelId, List<EcgSignalRange> signalsRange) { Doctor doctor = doctorRepository.findOne(doctorId); EcgChannel channel = ecgChannelRepository.findOne(channelId); QrsComplex qrs = channel.getQrsComplex(); if (qrs == null) { qrs = new QrsComplex(); qrsUpdateSignalsRange(doctor, qrs, signalsRange); channel.setQrsComplex(qrs); ecgChannelRepository.save(channel); } else { qrsDeleteAllSignalsRange(doctor, qrs, qrs.getInterlvals()); qrsUpdateSignalsRange(doctor, qrs, signalsRange); } } private void pWaveDeleteAllSignalsRange(Doctor doctor, PWave pWave, List<EcgSignalRange> signalsRange) { for (EcgSignalRange ecgSignalRange : signalsRange) { ecgSignalRangeRepository.delete(ecgSignalRange.getId()); } pWave.setDoctor(doctor); pWave.clearWaves(); pWaveRepository.saveAndFlush(pWave); } private void pWaveUpdateSignalsRange(Doctor doctor, PWave pWave, List<EcgSignalRange> signalsRange) { for (EcgSignalRange ecgSignalRange : signalsRange) { ecgSignalRangeRepository.saveAndFlush(ecgSignalRange); pWave.addInterval(ecgSignalRange); } pWave.setDoctor(doctor); pWaveRepository.saveAndFlush(pWave); } @Transactional public void setPWave(Long doctorId, Long channelId, List<EcgSignalRange> signalsRange) { Doctor doctor = doctorRepository.findOne(doctorId); EcgChannel channel = ecgChannelRepository.findOne(channelId); PWave pWave = channel.getpWave(); if (pWave == null) { pWave = new PWave(); pWaveUpdateSignalsRange(doctor, pWave, signalsRange); channel.setpWave(pWave); ecgChannelRepository.save(channel); } else { pWaveDeleteAllSignalsRange(doctor, pWave, pWave.getInterlvals()); pWaveUpdateSignalsRange(doctor, pWave, signalsRange); } } public List<EcgSignalRange> getPWaveFromAlgorithm(Long channelId, Long algorithmId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); List<EcgSignal> signals = channel.getSignals(); int sampleRate = channel.getEcg().getSampleRate().intValue(); AbstractPWaveAlgorithm algorithm = PWaveAlgorithmFactory.getPWaveAlgorithm(algorithmId.intValue()); return algorithm.getPWaves(signals, sampleRate); } public List<EcgSignalRange> getPWave(Long channelId, Long doctorId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); if (channel.getpWave() == null) { AbstractPWaveAlgorithm algorithm = PWaveAlgorithmFactory.getPWaveAlgorithm(2); setPWave(doctorId, channelId, algorithm.getPWaves(channel.getSignals(), channel.getEcg().getSampleRate().intValue())); } return channel.getpWave().getInterlvals(); } private void tWaveDeleteAllSignalsRange(Doctor doctor, TWave tWave, List<EcgSignalRange> signalsRange) { for (EcgSignalRange ecgSignalRange : signalsRange) { ecgSignalRangeRepository.delete(ecgSignalRange.getId()); } tWave.setDoctor(doctor); tWave.clearWaves(); tWaveRepository.saveAndFlush(tWave); } private void tWaveUpdateSignalsRange(Doctor doctor, TWave tWave, List<EcgSignalRange> signalsRange) { for (EcgSignalRange ecgSignalRange : signalsRange) { ecgSignalRangeRepository.saveAndFlush(ecgSignalRange); tWave.addInterval(ecgSignalRange); } tWave.setDoctor(doctor); tWaveRepository.saveAndFlush(tWave); } @Transactional public void setTWave(Long doctorId, Long channelId, List<EcgSignalRange> signalsRange) { Doctor doctor = doctorRepository.findOne(doctorId); EcgChannel channel = ecgChannelRepository.findOne(channelId); TWave tWave = channel.gettWave(); if (tWave == null) { tWave = new TWave(); tWaveUpdateSignalsRange(doctor, tWave, signalsRange); channel.settWave(tWave); ecgChannelRepository.save(channel); } else { tWaveDeleteAllSignalsRange(doctor, tWave, tWave.getInterlvals()); tWaveUpdateSignalsRange(doctor, tWave, signalsRange); } } public List<EcgSignalRange> getTWaveFromAlgorithm(Long channelId, Long algorithmId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); List<EcgSignal> signals = channel.getSignals(); int sampleRate = channel.getEcg().getSampleRate().intValue(); AbstractTWaveAlgorithm algorithm = TWaveAlgorithmFactory.getTWaveAlgorithm(algorithmId.intValue()); return algorithm.getTWaves(signals, sampleRate); } public List<EcgSignalRange> getTWave(Long channelId, Long doctorId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); if (channel.gettWave() == null) { AbstractTWaveAlgorithm algorithm = TWaveAlgorithmFactory.getTWaveAlgorithm(2); setTWave(doctorId, channelId, algorithm.getTWaves(channel.getSignals(), channel.getEcg().getSampleRate().intValue())); } return channel.gettWave().getInterlvals(); } public List<RRInterval> getRRPlot(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); List<EcgSignal> signals = channel.getSignals(); QrsComplex qrs = channel.getQrsComplex(); List<EcgSignalRange> qrsRanges; if (qrs == null || qrs.getInterlvals().isEmpty()) { qrsRanges = getQrsComplexFromAlgorithm(channelId, (long) 1); } else { qrsRanges = qrs.getInterlvals(); } return EcgArtifacts.getRRIntervals(signals, qrsRanges, channel.getEcg().getSampleRate()); } public Double getHeartRate(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); QrsComplex qrs = channel.getQrsComplex(); List<EcgSignalRange> qrsRanges; if (qrs == null || qrs.getInterlvals().isEmpty()) { qrsRanges = getQrsComplexFromAlgorithm(channelId, (long) 1); } else { qrsRanges = qrs.getInterlvals(); } return EcgArtifacts.getHeartRate(qrsRanges, channel.getEcg().getSampleRate()); } public Double getQrsDuration(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); QrsComplex qrs = channel.getQrsComplex(); List<EcgSignalRange> qrsRanges; if (qrs == null || qrs.getInterlvals().isEmpty()) { qrsRanges = getQrsComplexFromAlgorithm(channelId, (long) 1); } else { qrsRanges = qrs.getInterlvals(); } return EcgArtifacts.getWaveDuration(qrsRanges, channel.getEcg().getSampleRate()); } public Double getPWaveDuration(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); PWave pWave = channel.getpWave(); List<EcgSignalRange> pRanges; if (pWave == null || pWave.getInterlvals().isEmpty()) { pRanges = getPWaveFromAlgorithm(channelId, (long) 1); } else { pRanges = pWave.getInterlvals(); } return EcgArtifacts.getWaveDuration(pRanges, channel.getEcg().getSampleRate()); } public Double getTWaveDuration(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); TWave tWave = channel.gettWave(); List<EcgSignalRange> tRanges; if (tWave == null || tWave.getInterlvals().isEmpty()) { tRanges = getTWaveFromAlgorithm(channelId, (long) 1); } else { tRanges = tWave.getInterlvals(); } return EcgArtifacts.getWaveDuration(tRanges, channel.getEcg().getSampleRate()); } @Transactional public void addAnnotation(Long channelId, Long doctorId, String comment, Long firstIdx, Long lastIdx) { EcgChannel channel = ecgChannelRepository.findOne(channelId); Doctor doctor = doctorRepository.findOne(doctorId); EcgAnnotation annotation = new EcgAnnotation(); annotation.setComment(comment); annotation.setFisrtIdx(firstIdx); annotation.setLastIdx(lastIdx); annotation.setDoctor(doctor); annotationRepository.save(annotation); channel.addAnnotation(annotation); ecgChannelRepository.save(channel); } @Transactional public void removeAnnotationAtIndex(Long channelId, Long idx) { EcgChannel channel = ecgChannelRepository.findOne(channelId); channel.removeAnnotationIdx(idx); ecgChannelRepository.save(channel); } @Transactional public void removeAllAnnotation(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); channel.clearAnnotations(); ecgChannelRepository.save(channel); } public List<EcgAnnotation> getAnnotations(Long channelId) { EcgChannel channel = ecgChannelRepository.findOne(channelId); return channel.getAnnotations(); } @Transactional(timeout = 0) public void importEcg(Long patientId, File file, String ecgFileKey) throws IOException { System.out.println("Map Size=" + uploadFileMap.size()); EcgFileType type = EcgFileType.HL7; lock.lock(); try { if (getUploadFile(patientId) != null) { //Has upload file occurring throw new ServiceUploadDuplicatedActionException(); } else { addUploadFile(patientId, file); } } finally { lock.unlock(); } System.out.println("Map Size=" + uploadFileMap.size()); AbstractEcgFormat hl7 = new HL7FormatImpl(); hl7.loadInformationFromFile(file); String newfileName = ecgFileKey; Patient patient = patientRepository.findOne(patientId); EcgFile ecgFile = new EcgFile(); ecgFile.setDate(LocalDateTime.now()); ecgFile.setFileName(newfileName); ecgFile.setType(type); ecgFileRepository.save(ecgFile); Ecg ecg = new Ecg(); ecg.setBaseLine(hl7.getBaseLine()); ecg.setGain(hl7.getGain()); ecg.setSampleRate(hl7.getSampleRate()); ecg.setFinished(Boolean.FALSE); ecg.setFile(ecgFile); ecgRepository.save(ecg); for (int i = 0; i < hl7.getNumberOfChannels(); i++) { EcgChannel channel = new EcgChannel(); channel.setLeadType(hl7.getChannelType(i)); long count = 0; List<EcgSignal> signals = hl7.getChannelSignals(i); for (EcgSignal signal : signals) { count++; /*if (count == 30000) { break; }*/ EcgSignal signal_ = new EcgSignal(); signal_.setSampleIdx(signal.getSampleIdx()); signal_.setyIntensity(signal.getyIntensity()); ecgSignalRepository.save(signal_); channel.addSignal(signal_); if (count % 10000 == 0) { System.out.println(patientId + " : signal:" + count); } } channel.setEcg(ecg); ecgChannelRepository.save(channel); ecg.addChannel(channel); ecgRepository.save(ecg); } patient.addEcgExam(ecg); patientRepository.save(patient); ecg.setFinished(Boolean.TRUE); ecgRepository.save(ecg); Path pathIn = FileSystems.getDefault().getPath(file.getAbsolutePath()); Path pathOut = FileSystems.getDefault().getPath("/home/ecgs/" + newfileName); Files.copy(pathIn, pathOut); Files.deleteIfExists(pathIn); lock.lock(); try { removeUploadFile(patientId); } finally { lock.unlock(); } System.out.println("Map Size=" + uploadFileMap.size()); } public boolean isUploadOccurring(Long patientId, String ecgFileKey) { Patient patient = patientRepository.findOne(patientId); List<Ecg> ecgs = patient.getExams(); for (Ecg ecg : ecgs) { if (ecg.getFile().getFileName().compareTo(ecgFileKey) == 0) { if (ecg.getFinished()) return false; else return true; } } return false; } }