Mercurial > hg > orthanc-tests
comparison Plugins/DicomWeb/Run.py @ 434:2c142e070f19 Orthanc-1.9.7
dicomweb: added test_multiframe_windowing
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 30 Aug 2021 18:13:08 +0200 |
parents | dd519677974d |
children | e769bcf2b94f |
comparison
equal
deleted
inserted
replaced
433:cb579ad96a6c | 434:2c142e070f19 |
---|---|
1396 self.assertEqual('JPEG', im1.format) | 1396 self.assertEqual('JPEG', im1.format) |
1397 | 1397 |
1398 im2 = GetImage(ORTHANC, args.wado + '?requestType=WADO&objectUID=%s&contentType=image/png' % INSTANCE) | 1398 im2 = GetImage(ORTHANC, args.wado + '?requestType=WADO&objectUID=%s&contentType=image/png' % INSTANCE) |
1399 self.assertEqual('PNG', im2.format) | 1399 self.assertEqual('PNG', im2.format) |
1400 | 1400 |
1401 im3 = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/1/rendered' % (STUDY, SERIES, INSTANCE)) | 1401 im3 = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/1/rendered?window=200,800,linear' % (STUDY, SERIES, INSTANCE)) |
1402 self.assertEqual('JPEG', im3.format) | 1402 self.assertEqual('JPEG', im3.format) |
1403 | 1403 |
1404 im4 = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/rendered' % (STUDY, SERIES, INSTANCE), | 1404 im4 = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/rendered?window=200,800,linear' % (STUDY, SERIES, INSTANCE), |
1405 headers = { 'Accept' : 'image/png' }) | 1405 headers = { 'Accept' : 'image/png' }) |
1406 self.assertEqual('PNG', im4.format) | 1406 self.assertEqual('PNG', im4.format) |
1407 | 1407 |
1408 im5 = GetImage(ORTHANC, '/instances/%s/rendered' % i, { 'Accept' : 'image/jpeg' }) | 1408 im5 = GetImage(ORTHANC, '/instances/%s/rendered' % i, { 'Accept' : 'image/jpeg' }) |
1409 self.assertEqual('JPEG', im5.format) | 1409 self.assertEqual('JPEG', im5.format) |
1414 for im in [ truth, im1, im2, im3, im4, im5, im6 ]: | 1414 for im in [ truth, im1, im2, im3, im4, im5, im6 ]: |
1415 self.assertEqual('L', im.mode) | 1415 self.assertEqual('L', im.mode) |
1416 self.assertEqual(512, im.size[0]) | 1416 self.assertEqual(512, im.size[0]) |
1417 self.assertEqual(512, im.size[1]) | 1417 self.assertEqual(512, im.size[1]) |
1418 | 1418 |
1419 im2.save('/tmp/a.png') | |
1420 im4.save('/tmp/b.png') | |
1421 im6.save('/tmp/c.png') | |
1422 | |
1423 # The following fails in DICOMweb plugin <= 1.2, as "/rendered" | 1419 # The following fails in DICOMweb plugin <= 1.2, as "/rendered" |
1424 # was redirecting to the "/preview" route of Orthanc | 1420 # was redirecting to the "/preview" route of Orthanc |
1425 # http://effbot.org/zone/pil-comparing-images.htm | 1421 # http://effbot.org/zone/pil-comparing-images.htm |
1426 self.assertTrue(ImageChops.difference(im1, im3).getbbox() is None) | 1422 self.assertLess(ImageChops.difference(im1, im3).getextrema() [1], 10) |
1423 self.assertLess(ImageChops.difference(im2, im4).getextrema() [1], 2) | |
1424 self.assertLess(ImageChops.difference(im3, im5).getextrema() [1], 10) | |
1425 self.assertLess(ImageChops.difference(im4, im6).getextrema() [1], 2) | |
1427 self.assertTrue(ImageChops.difference(im1, im5).getbbox() is None) | 1426 self.assertTrue(ImageChops.difference(im1, im5).getbbox() is None) |
1428 self.assertTrue(ImageChops.difference(im2, im4).getbbox() is None) | |
1429 self.assertTrue(ImageChops.difference(im2, im6).getbbox() is None) | 1427 self.assertTrue(ImageChops.difference(im2, im6).getbbox() is None) |
1430 self.assertTrue(ImageChops.difference(im3, im5).getbbox() is None) | |
1431 self.assertTrue(ImageChops.difference(im4, im6).getbbox() is None) | |
1432 | 1428 |
1433 bbox = ImageChops.difference(im2, truth).getbbox() | 1429 bbox = ImageChops.difference(im2, truth).getbbox() |
1434 if bbox != None: | 1430 if bbox != None: |
1435 # Tolerance of just 1 pixel of difference (needed on Windows) | 1431 # Tolerance of just 1 pixel of difference (needed on Windows) |
1436 #print(im2.getpixel((238,275))) # => 255 | 1432 #print(im2.getpixel((238,275))) # => 255 |
1473 self.assertEqual("Hello1", b[0]["0008103E"]["Value"][0]) | 1469 self.assertEqual("Hello1", b[0]["0008103E"]["Value"][0]) |
1474 | 1470 |
1475 | 1471 |
1476 DoDelete(ORTHANC, 'instances/%s' % a) | 1472 DoDelete(ORTHANC, 'instances/%s' % a) |
1477 a = UploadInstance(ORTHANC, 'Issue195-bis.dcm') ['ID'] | 1473 a = UploadInstance(ORTHANC, 'Issue195-bis.dcm') ['ID'] |
1478 URI = 'dicom-web/studies/1.2.276.0.7230010.3.1.2.8323329.23653.1620311964.865418/series/1.2.276.0.7230010.3.1.3.8323329.23653.1620311964.865419/instances/1.2.276.0.7230010.3.1.4.8323329.23653.1620311964.865420' | 1474 URI = 'dicom-web/studies/1.2.276.0.7230010.3.1.2.8323329.6792.1625504071.652468/series/1.2.276.0.7230010.3.1.3.8323329.6792.1625504071.652469/instances/1.2.276.0.7230010.3.1.4.8323329.6792.1625504071.652470' |
1479 b = DoGet(ORTHANC, '%s/metadata' % URI, | 1475 b = DoGet(ORTHANC, '%s/metadata' % URI, |
1480 headers = { 'Accept' : 'application/dicom+json' }) | 1476 headers = { 'Accept' : 'application/dicom+json' }) |
1481 | 1477 |
1482 self.assertEqual(1, len(b)) | 1478 self.assertEqual(1, len(b)) |
1483 self.assertEqual(5, len(b[0])) | 1479 self.assertEqual(5, len(b[0])) |
1484 | 1480 |
1485 # The expected result can be found by typing "dcm2json Database/Issue195-bis.dcm" | 1481 # The expected result can be found by typing "dcm2json ../../Database/Issue195-bis.dcm" |
1486 self.assertEqual(2, len(b[0]["00080018"])) | 1482 self.assertEqual(2, len(b[0]["00080018"])) |
1487 self.assertEqual("UI", b[0]["00080018"]["vr"]) | 1483 self.assertEqual("UI", b[0]["00080018"]["vr"]) |
1488 self.assertEqual("1.2.276.0.7230010.3.1.4.8323329.23653.1620311964.865420", | 1484 self.assertEqual("1.2.276.0.7230010.3.1.4.8323329.6792.1625504071.652470", |
1489 b[0]["00080018"]["Value"][0]) | 1485 b[0]["00080018"]["Value"][0]) |
1490 | 1486 |
1491 self.assertEqual(2, len(b[0]["0020000D"])) | 1487 self.assertEqual(2, len(b[0]["0020000D"])) |
1492 self.assertEqual("UI", b[0]["0020000D"]["vr"]) | 1488 self.assertEqual("UI", b[0]["0020000D"]["vr"]) |
1493 self.assertEqual("1.2.276.0.7230010.3.1.2.8323329.23653.1620311964.865418", | 1489 self.assertEqual("1.2.276.0.7230010.3.1.2.8323329.6792.1625504071.652468", |
1494 b[0]["0020000D"]["Value"][0]) | 1490 b[0]["0020000D"]["Value"][0]) |
1495 | 1491 |
1496 self.assertEqual(2, len(b[0]["0020000E"])) | 1492 self.assertEqual(2, len(b[0]["0020000E"])) |
1497 self.assertEqual("UI", b[0]["0020000E"]["vr"]) | 1493 self.assertEqual("UI", b[0]["0020000E"]["vr"]) |
1498 self.assertEqual("1.2.276.0.7230010.3.1.3.8323329.23653.1620311964.865419", | 1494 self.assertEqual("1.2.276.0.7230010.3.1.3.8323329.6792.1625504071.652469", |
1499 b[0]["0020000E"]["Value"][0]) | 1495 b[0]["0020000E"]["Value"][0]) |
1500 | 1496 |
1501 self.assertEqual(2, len(b[0]["0008103E"])) | 1497 self.assertEqual(2, len(b[0]["00084567"])) |
1502 self.assertEqual("UN", b[0]["0008103E"]["vr"]) | 1498 self.assertEqual("UN", b[0]["00084567"]["vr"]) |
1503 self.assertEqual('http://%s:%s%s' % (args.server, args.rest, '/%s/bulk/0008103e' % URI), | 1499 self.assertEqual('http://%s:%s%s' % (args.server, args.rest, '/%s/bulk/00084567' % URI), |
1504 b[0]["0008103E"]["BulkDataURI"]) | 1500 b[0]["00084567"]["BulkDataURI"]) |
1505 | 1501 |
1506 c = DoGet(ORTHANC, '%s/bulk/0008103e' % URI) | 1502 c = DoGet(ORTHANC, '%s/bulk/00084567' % URI) |
1507 self.assertTrue('Content-Length: 2\r\n' in c) | 1503 self.assertTrue('Content-Length: 2\r\n' in c) |
1508 index = c.find('\r\n\r\n') | 1504 index = c.find('\r\n\r\n') |
1509 self.assertEqual(0x42, ord(c[index + 4])) | 1505 self.assertEqual(0x42, ord(c[index + 4])) |
1510 self.assertEqual(0x00, ord(c[index + 5])) | 1506 self.assertEqual(0x00, ord(c[index + 5])) |
1511 | 1507 |
1512 # Case of an empty value, fails in Orthanc <= 1.9.2 because of issue #195 | 1508 # Case of an empty value, fails in Orthanc <= 1.9.2 because of issue #195 |
1513 self.assertEqual(1, len(b[0]["00081030"])) | 1509 self.assertEqual(1, len(b[0]["00084565"])) |
1514 self.assertEqual("UN", b[0]["00081030"]["vr"]) | 1510 self.assertEqual("UN", b[0]["00084565"]["vr"]) |
1515 | 1511 |
1516 | 1512 |
1513 | |
1514 | |
1515 def test_multiframe_windowing(self): | |
1516 # Fixed in DICOMweb 1.7 | |
1517 def GetLinear(x, c, w): | |
1518 # http://dicom.nema.org/MEDICAL/dicom/2019a/output/chtml/part03/sect_C.11.2.html#sect_C.11.2.1.2.1 | |
1519 ymin = 0.0 | |
1520 ymax = 255.0 | |
1521 if float(x) <= float(c) - 0.5 - (float(w) - 1.0) / 2.0: | |
1522 return ymin | |
1523 elif float(x) > float(c) - 0.5 + (float(w) - 1.0) / 2.0 : | |
1524 return ymax | |
1525 else: | |
1526 return ((float(x) - (float(c) - 0.5)) / (float(w) - 1.0) + 0.5) * (ymax - ymin) + ymin | |
1527 | |
1528 def GetLinearExact(x, c, w): | |
1529 # http://dicom.nema.org/MEDICAL/dicom/2019a/output/chtml/part03/sect_C.11.2.html#sect_C.11.2.1.3.2 | |
1530 ymin = 0.0 | |
1531 ymax = 255.0 | |
1532 if float(x) <= float(c) - float(w) / 2.0: | |
1533 return ymin | |
1534 elif float(x) > float(c) + float(w) / 2.0: | |
1535 return ymax | |
1536 else: | |
1537 return (float(x) - float(c)) / float(w) * (ymax- ymin) + ymin | |
1538 | |
1539 def GetSigmoid(x, c, w): | |
1540 # http://dicom.nema.org/MEDICAL/dicom/2019a/output/chtml/part03/sect_C.11.2.html#sect_C.11.2.1.3.1 | |
1541 ymin = 0.0 | |
1542 ymax = 255.0 | |
1543 return (ymax - ymin) / (1.0 + math.exp(-4 * (float(x) - float(c)) / float(w))) | |
1544 | |
1545 self.assertAlmostEqual(GetLinear(10, 0, 100), 154.54545454545456) | |
1546 self.assertAlmostEqual(GetLinear(-1000, 2048, 4096), 0) | |
1547 self.assertAlmostEqual(GetLinear(5096, 2048, 4096), 255) | |
1548 self.assertAlmostEqual(GetLinear(333, 2048, 4096), 20.7362637362637) | |
1549 self.assertAlmostEqual(GetLinear(16, 127, 256), 17) | |
1550 | |
1551 self.assertAlmostEqual(GetLinearExact(-1000, 2048, 4096), 0) | |
1552 self.assertAlmostEqual(GetLinearExact(5096, 2048, 4096), 255) | |
1553 self.assertAlmostEqual(GetLinearExact(150, 127, 256), 22.91015625) | |
1554 | |
1555 self.assertAlmostEqual(GetSigmoid(150, 127, 256), 150.166728345797) | |
1556 | |
1557 UploadInstance(ORTHANC, 'MultiframeWindowing.dcm') | |
1558 STUDY = '1.2.840.113619.2.176.2025.1499492.7391.1175285944.390' | |
1559 SERIES = '1.2.840.113619.2.176.2025.1499492.7391.1175285944.394' | |
1560 INSTANCE = '1.2.840.113619.2.176.2025.1499492.7040.1175286242.109' | |
1561 | |
1562 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/1/rendered?window=127,256,linear' % (STUDY, SERIES, INSTANCE)) | |
1563 self.assertLessEqual(abs(GetLinear(0x00, 127, 256) - im.getpixel((0, 0))), 1) | |
1564 self.assertLessEqual(abs(GetLinear(0x10, 127, 256) - im.getpixel((1, 0))), 1) | |
1565 self.assertLessEqual(abs(GetLinear(0x20, 127, 256) - im.getpixel((0, 1))), 1.1) | |
1566 self.assertLessEqual(abs(GetLinear(0x30, 127, 256) - im.getpixel((1, 1))), 1.1) | |
1567 | |
1568 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/1/rendered?window=0,256,linear-exact' % (STUDY, SERIES, INSTANCE)) | |
1569 self.assertLessEqual(abs(GetLinearExact(0x00, 0, 256) - im.getpixel((0, 0))), 1) | |
1570 self.assertLessEqual(abs(GetLinearExact(0x10, 0, 256) - im.getpixel((1, 0))), 1) | |
1571 self.assertLessEqual(abs(GetLinearExact(0x20, 0, 256) - im.getpixel((0, 1))), 1.2) | |
1572 self.assertLessEqual(abs(GetLinearExact(0x30, 0, 256) - im.getpixel((1, 1))), 1.2) | |
1573 | |
1574 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/1/rendered?window=127,256,sigmoid' % (STUDY, SERIES, INSTANCE)) | |
1575 self.assertLessEqual(abs(GetSigmoid(0x00, 127, 256) - im.getpixel((0, 0))), 3) | |
1576 self.assertLessEqual(abs(GetSigmoid(0x10, 127, 256) - im.getpixel((1, 0))), 1) | |
1577 self.assertLessEqual(abs(GetSigmoid(0x20, 127, 256) - im.getpixel((0, 1))), 1) | |
1578 self.assertLessEqual(abs(GetSigmoid(0x30, 127, 256) - im.getpixel((1, 1))), 1) | |
1579 | |
1580 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/1/rendered?window=16,128,linear' % (STUDY, SERIES, INSTANCE)) | |
1581 self.assertLessEqual(abs(GetLinear(0x00, 16, 128) - im.getpixel((0, 0))), 1) | |
1582 self.assertLessEqual(abs(GetLinear(0x10, 16, 128) - im.getpixel((1, 0))), 1) | |
1583 self.assertLessEqual(abs(GetLinear(0x20, 16, 128) - im.getpixel((0, 1))), 2) | |
1584 self.assertLessEqual(abs(GetLinear(0x30, 16, 128) - im.getpixel((1, 1))), 2) | |
1585 | |
1586 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/2/rendered?window=127,256,linear' % (STUDY, SERIES, INSTANCE)) | |
1587 ri = 100.0 | |
1588 rs = 1.0 | |
1589 self.assertLessEqual(abs(GetLinear(0x00 * rs + ri, 127, 256) - im.getpixel((0, 0))), 1) | |
1590 self.assertLessEqual(abs(GetLinear(0x10 * rs + ri, 127, 256) - im.getpixel((1, 0))), 1) | |
1591 self.assertLessEqual(abs(GetLinear(0x20 * rs + ri, 127, 256) - im.getpixel((0, 1))), 1) | |
1592 self.assertLessEqual(abs(GetLinear(0x30 * rs + ri, 127, 256) - im.getpixel((1, 1))), 1) | |
1593 | |
1594 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/3/rendered?window=127,256,linear' % (STUDY, SERIES, INSTANCE)) | |
1595 ri = 0.0 | |
1596 rs = 2.0 | |
1597 self.assertLessEqual(abs(GetLinear(0x00 * rs + ri, 127, 256) - im.getpixel((0, 0))), 1) | |
1598 self.assertLessEqual(abs(GetLinear(0x10 * rs + ri, 127, 256) - im.getpixel((1, 0))), 1.1) | |
1599 self.assertLessEqual(abs(GetLinear(0x20 * rs + ri, 127, 256) - im.getpixel((0, 1))), 1) | |
1600 self.assertLessEqual(abs(GetLinear(0x30 * rs + ri, 127, 256) - im.getpixel((1, 1))), 1) | |
1601 | |
1602 im = GetImage(ORTHANC, '/dicom-web/studies/%s/series/%s/instances/%s/frames/4/rendered?window=127,256,linear' % (STUDY, SERIES, INSTANCE)) | |
1603 ri = 100.0 | |
1604 rs = 2.0 | |
1605 self.assertLessEqual(abs(GetLinear(0x00 * rs + ri, 127, 256) - im.getpixel((0, 0))), 1) | |
1606 self.assertLessEqual(abs(GetLinear(0x10 * rs + ri, 127, 256) - im.getpixel((1, 0))), 1) | |
1607 self.assertLessEqual(abs(GetLinear(0x20 * rs + ri, 127, 256) - im.getpixel((0, 1))), 1) | |
1608 self.assertLessEqual(abs(GetLinear(0x30 * rs + ri, 127, 256) - im.getpixel((1, 1))), 1) | |
1609 | |
1610 | |
1517 try: | 1611 try: |
1518 print('\nStarting the tests...') | 1612 print('\nStarting the tests...') |
1519 unittest.main(argv = [ sys.argv[0] ] + args.options) | 1613 unittest.main(argv = [ sys.argv[0] ] + args.options) |
1520 | 1614 |
1521 finally: | 1615 finally: |