use of com.github.lindenb.jvarkit.util.Hershey in project jvarkit by lindenb.
the class BamStage method repaintCanvas.
/**
* repaint the canvas area
*/
private void repaintCanvas() {
final boolean showClip = this.canvasShowClip.isSelected();
final boolean showReadName = this.canvasShowReadName.isSelected();
final int baseSize = this.canvasBaseSizeCombo.getValue();
final double canvaswidth = this.canvas.getCanvas().getWidth();
final double canvasheight = this.canvas.getCanvas().getHeight();
final GraphicsContext gc = this.canvas.getCanvas().getGraphicsContext2D();
gc.setFill(Color.WHITE);
gc.fillRect(0, 0, canvaswidth, canvasheight);
double y = baseSize * 2;
final List<SAMRecord> records = getDisplayableSamRecordStream().collect(Collectors.toList());
if (records.isEmpty())
return;
final long genomicIndex = (long) this.canvasScrollHGenomicLoc.getValue();
final ContigPos contigStart = super.convertGenomicIndexToContigPos(genomicIndex);
if (contigStart == null)
return;
final int chromStart = contigStart.position;
final int chromLen = (int) (canvaswidth / baseSize);
if (chromLen == 0)
return;
/* pileup record */
final List<List<XYRecord>> yxrows = new ArrayList<>();
for (final SAMRecord rec : records) {
if (!rec.getReferenceName().equals(contigStart.getContig())) {
continue;
}
final XYRecord newxy = new XYRecord(rec);
if (rec.getStart() > (chromStart + chromLen))
break;
if (rec.getEnd() < (chromStart))
continue;
int z = 0;
for (z = 0; z < yxrows.size(); ++z) {
final List<XYRecord> row = yxrows.get(z);
final XYRecord lastyx = row.get(row.size() - 1);
if (lastyx.getEnd() + 2 < newxy.getStart()) {
newxy.y = z;
row.add(newxy);
break;
}
}
if (z == yxrows.size()) {
newxy.y = z;
final List<XYRecord> row = new ArrayList<>();
row.add(newxy);
yxrows.add(row);
}
}
final Function<Integer, Double> position2pixel = new Function<Integer, Double>() {
@Override
public Double apply(Integer pos) {
return ((pos - (double) chromStart) / (double) chromLen) * canvaswidth;
}
};
final Hershey hershey = new Hershey();
// paint contig lines
hershey.paint(gc, contigStart.getContig(), 1, 0, baseSize * contigStart.getContig().length(), baseSize - 2);
// paint vertical lines
for (int x = chromStart; x < chromStart + chromLen; ++x) {
double px = position2pixel.apply(x);
gc.setStroke(x % 10 == 0 ? Color.BLACK : Color.GRAY);
gc.setLineWidth(x % 10 == 0 ? 5 : 0.5);
gc.strokeLine(px, baseSize, px, canvasheight);
if (x % 10 == 0) {
String s = String.valueOf(x);
gc.setLineWidth(1.0);
hershey.paint(gc, s, px, baseSize, baseSize * s.length(), baseSize - 1);
}
}
gc.setLineWidth(1);
for (int yy = (int) this.canvasScrolVInCoverage.getValue(); y < canvasheight && yy < yxrows.size(); ++yy, y += baseSize) {
final List<XYRecord> row = yxrows.get(yy);
for (final XYRecord rec : row) {
/* paint record */
int baseIndex = 0;
int refIndex = rec.getStart();
final byte[] bases = rec.record.getReadBases();
final Function<Integer, String> getBaseAt = new Function<Integer, String>() {
@Override
public String apply(Integer readPos) {
char c;
if (showReadName) {
if (rec.record.getReadNameLength() <= readPos)
return "";
c = rec.record.getReadName().charAt(readPos);
} else if (bases == null || bases.length <= readPos) {
return "";
} else {
c = (char) bases[readPos];
}
c = (rec.record.getReadNegativeStrandFlag() ? Character.toLowerCase(c) : Character.toUpperCase(c));
return String.valueOf(c);
}
};
final Function<Integer, Color> getColorAt = new Function<Integer, Color>() {
public Color apply(final Integer readPos) {
if (bases == null || bases.length <= readPos) {
return Color.BLACK;
}
return JfxNgs.BASE2COLOR.apply((char) bases[readPos]);
}
};
gc.setLineWidth(1.0);
// arrow end
{
double endpos = position2pixel.apply(rec.record.getReadNegativeStrandFlag() ? rec.getStart() : rec.getEnd() + 1);
double radius = baseSize / 4.0;
gc.setFill(Color.BLACK);
gc.fillOval(endpos - radius, y + baseSize / 2.0 - radius, radius * 2, radius * 2);
}
final Set<Integer> referenceEvents = new HashSet<>();
for (final CigarElement ce : rec.record.getCigar()) {
switch(ce.getOperator()) {
case P:
break;
case I:
{
baseIndex += ce.getLength();
referenceEvents.add(refIndex);
break;
}
case D:
case N:
{
gc.setFill(Color.RED);
for (int x = 0; x < ce.getLength(); ++x) {
gc.fillRect(position2pixel.apply(refIndex), y, baseSize, baseSize - 1);
refIndex++;
}
break;
}
case H:
{
if (showClip) {
gc.setFill(Color.YELLOW);
for (int x = 0; x < ce.getLength(); ++x) {
gc.fillRect(position2pixel.apply(refIndex), y, baseSize, baseSize - 1);
refIndex++;
}
} else {
// NO refIndex+=ce.getLength();
}
break;
}
case S:
{
if (showClip) {
for (int x = 0; x < ce.getLength(); ++x) {
gc.setFill(Color.YELLOW);
gc.fillRect(position2pixel.apply(refIndex), y, baseSize, baseSize - 1);
gc.setStroke(getColorAt.apply(baseIndex));
hershey.paint(gc, getBaseAt.apply(baseIndex), position2pixel.apply(refIndex), y, baseSize - 1, baseSize - 2);
refIndex++;
baseIndex++;
}
} else {
baseIndex += ce.getLength();
// NO refIndex+=ce.getLength();
}
break;
}
case EQ:
case X:
case M:
{
for (int x = 0; x < ce.getLength(); ++x) {
gc.setFill(ce.getOperator() == CigarOperator.X ? Color.RED : Color.LIGHTGRAY);
gc.fillRect(position2pixel.apply(refIndex), y, baseSize, baseSize - 1);
gc.setStroke(getColorAt.apply(baseIndex));
hershey.paint(gc, getBaseAt.apply(baseIndex), position2pixel.apply(refIndex), y, baseSize - 1, baseSize - 2);
refIndex++;
baseIndex++;
}
break;
}
default:
break;
}
if (refIndex > chromStart + chromLen)
break;
}
gc.setStroke(Color.BLACK);
gc.strokeRect(position2pixel.apply(rec.getStart()), y, position2pixel.apply(rec.getEnd() + 1) - position2pixel.apply(rec.getStart()), baseSize - 1);
for (final Integer pos : referenceEvents) {
double x = position2pixel.apply(pos);
gc.setStroke(Color.RED);
gc.setLineWidth(0.5);
gc.strokeLine(x, y, x, y + baseSize);
}
/* end paint record */
}
}
gc.setStroke(Color.BLACK);
gc.rect(0, 0, canvaswidth - 1, canvasheight - 1);
}
use of com.github.lindenb.jvarkit.util.Hershey in project jvarkit by lindenb.
the class VcfToHilbert method doWork.
@Override
public int doWork(final List<String> args) {
if (this.imgOut == null) {
LOG.error("output image file not defined");
return -1;
}
if (this.imageWidth < 1) {
LOG.error("Bad image size:" + this.imageWidth);
return -1;
}
VcfIterator iter = null;
try {
iter = this.openVcfIterator(oneFileOrNull(args));
final VCFHeader header = iter.getHeader();
this.dict = header.getSequenceDictionary();
if (this.dict == null) {
throw new JvarkitException.FastaDictionaryMissing("no dict in input");
}
final List<String> samples = header.getSampleNamesInOrder();
if (samples.isEmpty()) {
throw new JvarkitException.SampleMissing("no.sample.in.vcf");
}
LOG.info("N-Samples:" + samples.size());
double marginWidth = (this.imageWidth - 2) * 0.05;
this.sampleWidth = ((this.imageWidth - 2) - marginWidth) / samples.size();
LOG.info("sample Width:" + sampleWidth);
BufferedImage img = new BufferedImage(this.imageWidth, this.imageWidth, BufferedImage.TYPE_INT_RGB);
this.g = (Graphics2D) img.getGraphics();
this.g.setColor(Color.WHITE);
this.g.fillRect(0, 0, imageWidth, imageWidth);
g.setColor(Color.BLACK);
final Hershey hershey = new Hershey();
EvalCurve evalCurve = new EvalCurve();
evalCurve.run();
this.genomicSizePerCurveUnit = ((double) dict.getReferenceLength() / (double) (evalCurve.count));
if (this.genomicSizePerCurveUnit < 1)
this.genomicSizePerCurveUnit = 1;
LOG.info("genomicSizePerCurveUnit:" + genomicSizePerCurveUnit);
for (int x = 0; x < samples.size(); ++x) {
String samplex = samples.get(x);
double labelHeight = marginWidth;
if (labelHeight > 50)
labelHeight = 50;
g.setColor(Color.BLACK);
hershey.paint(g, samplex, marginWidth + x * sampleWidth, marginWidth - labelHeight, sampleWidth * 0.9, labelHeight * 0.9);
AffineTransform old = g.getTransform();
AffineTransform tr = AffineTransform.getTranslateInstance(marginWidth, marginWidth + x * sampleWidth);
tr.rotate(Math.PI / 2);
g.setTransform(tr);
hershey.paint(g, samplex, 0.0, 0.0, sampleWidth * 0.9, labelHeight * 0.9);
// g.drawString(this.tabixFile.getFile().getName(),0,0);
g.setTransform(old);
double tx = marginWidth + x * sampleWidth;
for (int y = 0; y < samples.size(); ++y) {
double ty = marginWidth + y * sampleWidth;
g.translate(tx, ty);
g.setColor(Color.BLUE);
g.draw(new Rectangle2D.Double(0, 0, sampleWidth, sampleWidth));
// paint each chromosome
paintReference();
g.translate(-tx, -ty);
}
}
LOG.info("genomicSizePerCurveUnit:" + (long) genomicSizePerCurveUnit * evalCurve.count + " " + dict.getReferenceLength() + " count=" + evalCurve.count);
LOG.info("Scanning variants");
final SAMSequenceDictionaryProgress progress = new SAMSequenceDictionaryProgress(this.dict);
while (iter.hasNext()) {
final VariantContext var = progress.watch(iter.next());
for (int x = 0; x < samples.size(); ++x) {
final String samplex = samples.get(x);
final Genotype gx = var.getGenotype(samplex);
if (!gx.isCalled())
continue;
double tx = marginWidth + x * sampleWidth;
for (int y = 0; y < samples.size(); ++y) {
final String sampley = samples.get(y);
final Genotype gy = var.getGenotype(sampley);
if (!gy.isCalled())
continue;
if (gx.isHomRef() && gy.isHomRef())
continue;
double ty = marginWidth + y * sampleWidth;
g.translate(tx, ty);
final PaintVariant paint = new PaintVariant(var, x, y);
paint.run();
g.translate(-tx, -ty);
}
}
}
progress.finish();
this.g.dispose();
// save file
LOG.info("saving " + imgOut);
if (imgOut != null) {
ImageIO.write(img, imgOut.getName().toLowerCase().endsWith(".png") ? "PNG" : "JPG", imgOut);
} else {
ImageIO.write(img, "PNG", stdout());
}
return 0;
} catch (final Exception err) {
LOG.error(err);
return -1;
} finally {
CloserUtil.close(iter);
}
}
use of com.github.lindenb.jvarkit.util.Hershey in project jvarkit by lindenb.
the class BamCmpCoverage method doWork.
@Override
public int doWork(final List<String> args) {
if (outputFile == null) {
LOG.error("output image file not defined");
return -1;
}
if (this.imgageSize < 1) {
LOG.error("Bad image size:" + this.imgageSize);
return -1;
}
if (this.minDepth < 0) {
LOG.error("Bad min depth : " + this.minDepth);
return -1;
}
if (this.minDepth >= this.maxDepth) {
LOG.error("Bad min<max depth : " + this.minDepth + "<" + this.maxDepth);
return 1;
}
if (this.bedFile != null) {
readBedFile(this.bedFile);
}
if (regionStr != null && this.intervals != null) {
LOG.error("bed and interval both defined.");
return -1;
}
try {
final ConcatSam.Factory concatSamFactory = new ConcatSam.Factory();
final SamReaderFactory srf = concatSamFactory.getSamReaderFactory();
srf.disable(SamReaderFactory.Option.EAGERLY_DECODE);
srf.disable(SamReaderFactory.Option.INCLUDE_SOURCE_IN_RECORDS);
srf.disable(SamReaderFactory.Option.VALIDATE_CRC_CHECKSUMS);
if (this.regionStr != null) {
concatSamFactory.addInterval(this.regionStr);
}
ConcatSam.ConcatSamIterator concatIter = concatSamFactory.open(args);
final SAMSequenceDictionary dict = concatIter.getFileHeader().getSequenceDictionary();
final Set<String> samples = concatIter.getFileHeader().getReadGroups().stream().map(RG -> this.samRecordPartition.apply(RG, "N/A")).collect(Collectors.toSet());
LOG.info("Samples:" + samples.size());
for (String sample : samples) {
this.sample2column.put(sample, this.sample2column.size());
}
// create image
LOG.info("Creating image " + this.imgageSize + "x" + this.imgageSize);
this.image = new BufferedImage(this.imgageSize, this.imgageSize, BufferedImage.TYPE_INT_RGB);
Graphics2D g = this.image.createGraphics();
this.marginWidth = this.imgageSize * 0.05;
double drawingWidth = (this.imgageSize - 1) - marginWidth;
this.sampleWidth = drawingWidth / samples.size();
// g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.imgageSize, this.imgageSize);
g.setColor(Color.BLACK);
Hershey hershey = new Hershey();
for (final String sample_x : samples) {
double labelHeight = marginWidth;
if (labelHeight > 50)
labelHeight = 50;
g.setColor(Color.BLACK);
hershey.paint(g, sample_x, marginWidth + sample2column.get(sample_x) * sampleWidth, marginWidth - labelHeight, sampleWidth * 0.9, labelHeight * 0.9);
AffineTransform old = g.getTransform();
AffineTransform tr = AffineTransform.getTranslateInstance(marginWidth, marginWidth + sample2column.get(sample_x) * sampleWidth);
tr.rotate(Math.PI / 2);
g.setTransform(tr);
hershey.paint(g, sample_x, 0.0, 0.0, sampleWidth * 0.9, labelHeight * 0.9);
// g.drawString(this.tabixFile.getFile().getName(),0,0);
g.setTransform(old);
for (String sample_y : samples) {
Rectangle2D rect = new Rectangle2D.Double(marginWidth + sample2column.get(sample_x) * sampleWidth, marginWidth + sample2column.get(sample_y) * sampleWidth, sampleWidth, sampleWidth);
g.setColor(Color.BLUE);
g.draw(new Line2D.Double(rect.getMinX(), rect.getMinY(), rect.getMaxX(), rect.getMaxY()));
g.setColor(Color.BLACK);
g.draw(rect);
}
}
// ceate bit-array
BitSampleMatrix bitMatrix = new BitSampleMatrix(samples.size());
// preivous chrom
// int prev_tid=-1;
BufferedList<Depth> depthList = new BufferedList<Depth>();
g.setColor(Color.BLACK);
SAMSequenceDictionaryProgress progress = new SAMSequenceDictionaryProgress(dict).logger(LOG);
LOG.info("Scanning bams...");
while (concatIter.hasNext()) {
final SAMRecord rec = progress.watch(concatIter.next());
if (this.samRecordFilter.filterOut(rec))
continue;
final String sample = this.samRecordPartition.getPartion(rec, "N/A");
final int sample_id = this.sample2column.get(sample);
final Cigar cigar = rec.getCigar();
if (cigar == null || cigar.isEmpty())
continue;
int refPos = rec.getAlignmentStart();
/* cleanup front pos */
while (!depthList.isEmpty()) {
final Depth front = depthList.getFirst();
if (front.tid != rec.getReferenceIndex().intValue() || front.pos < refPos) {
paint(bitMatrix, front);
depthList.removeFirst();
continue;
} else {
break;
}
}
for (final CigarElement ce : cigar.getCigarElements()) {
final CigarOperator op = ce.getOperator();
if (!op.consumesReferenceBases())
continue;
if (op.consumesReadBases()) {
for (int i = 0; i < ce.getLength(); ++i) {
Depth depth = null;
int pos = refPos + i;
// ignore non-overlapping BED
if (this.intervals != null && !this.intervals.containsOverlapping(new Interval(rec.getReferenceName(), pos, pos))) {
continue;
} else if (depthList.isEmpty()) {
depth = new Depth();
depth.pos = pos;
depth.tid = rec.getReferenceIndex();
depthList.add(depth);
} else if (depthList.getLast().pos < pos) {
Depth prev = depthList.getLast();
while (prev.pos < pos) {
depth = new Depth();
depth.pos = prev.pos + 1;
depth.tid = rec.getReferenceIndex();
depthList.add(depth);
prev = depth;
}
depth = prev;
} else {
int lastPos = depthList.get(depthList.size() - 1).pos;
int distance = lastPos - pos;
int indexInList = (depthList.size() - 1) - (distance);
if (indexInList < 0) {
// can appen when BED declared and partially overlap the read
continue;
}
depth = depthList.get((depthList.size() - 1) - (distance));
if (depth.pos != pos) {
LOG.error(" " + pos + " vs " + depth.pos + " " + lastPos);
return -1;
}
}
depth.depths[sample_id]++;
}
}
refPos += ce.getLength();
}
}
while (!depthList.isEmpty()) {
// paint(g,depthList.remove(0));
paint(bitMatrix, depthList.remove(0));
}
progress.finish();
concatIter.close();
concatIter = null;
for (int x = 0; x < bitMatrix.n_samples; ++x) {
for (int y = 0; y < bitMatrix.n_samples; ++y) {
LOG.info("Painting...(" + x + "/" + y + ")");
paint(g, bitMatrix.get(x, y));
}
}
g.dispose();
// save file
LOG.info("saving " + this.outputFile);
if (this.outputFile.getName().toLowerCase().endsWith(".png")) {
ImageIO.write(this.image, "PNG", this.outputFile);
} else {
ImageIO.write(this.image, "JPG", this.outputFile);
}
return 0;
} catch (final Exception err) {
LOG.error(err);
return -1;
} finally {
}
}
Aggregations