Commit 6115cbd9 authored by payno's avatar payno
Browse files

Merge branch 'add_test_projections' into 'master'

Add test projections

See merge request !3
parents 2a78dc35 4704c811
Pipeline #15508 passed with stages
in 1 minute and 34 seconds
......@@ -35,7 +35,6 @@ from lxml import etree
import json
import io
from typing import Union
from silx.io.url import DataUrl
from ..scanbase import TomoScanBase
from .utils import get_parameters_frm_par_or_info, extract_urls_from_edf
from ..unitsystem import metricsystem
......@@ -79,6 +78,7 @@ class EDFTomoScan(TomoScanBase):
self.__pixel_size = None
self.__ref_on = None
self.__scan_range = None
self.update()
@docstring(TomoScanBase.tomo_n)
@property
......@@ -205,35 +205,14 @@ class EDFTomoScan(TomoScanBase):
' the projections')
return {}
n_projection = self.tomo_n
radios = EDFTomoScan.get_proj_paths(self.path)
sorted_keys = list(radios.keys())
sorted_keys.sort()
data_urls = []
# create one DataUrl per projection
for key in sorted_keys:
radio = radios[key]
edf_reader = fabio.open(radio)
if edf_reader.nframes is 1:
data_urls.append(DataUrl(file_path=radio, scheme='fabio'))
else:
data_urls.extend(extract_urls_from_edf(file_=radio))
if n_projection is None:
raise ValueError('unable to get n projection')
if len(data_urls) < n_projection:
mes = 'incoherence between the number of projection found (%s)' \
'and the number of theoretical projection (%s). Maybe the ' \
'acquisition is not complete ?' % (len(data_urls), n_projection)
_logger.warning(mes)
data_urls = EDFTomoScan.get_proj_urls(self.path)
return TomoScanBase.map_urls_on_scan_range(urls=data_urls,
n_projection=n_projection,
scan_range=self.scan_range)
@docstring(TomoScanBase.update)
def update(self):
self.projections = EDFTomoScan.get_proj_angle_url(self.path)
self.projections = EDFTomoScan.get_proj_urls(self.path)
self._darks = EDFTomoScan.get_darks_url(self.path)
self._flats = EDFTomoScan.get_refs_url(self.path)
......@@ -251,7 +230,7 @@ class EDFTomoScan(TomoScanBase):
return self
@staticmethod
def get_proj_paths(scan: str) -> dict:
def get_proj_urls(scan: str) -> dict:
"""
Return the dict of radios / projection for the given scan.
Keys of the dictionary is the slice number
......@@ -263,19 +242,19 @@ class EDFTomoScan(TomoScanBase):
:return: dict of radios files with radio index as key and file as value
:rtype: dict
"""
files = dict({})
urls = dict({})
if(scan is None) or not(os.path.isdir(scan)):
return files
return urls
if os.path.isdir(scan):
for f in os.listdir(scan):
if EDFTomoScan.is_a_proj_path(f, scan):
if EDFTomoScan.is_a_proj_path(fileName=f, scanID=scan):
gfile = os.path.join(scan, f)
index = EDFTomoScan.guess_index_frm_file_name(gfile)
files.update(extract_urls_from_edf(start_index=index,
urls.update(extract_urls_from_edf(start_index=index,
file_=gfile))
return files
return urls
@staticmethod
def is_a_proj_path(fileName: str, scanID: str) -> bool:
......
......@@ -182,7 +182,7 @@ class HDF5TomoScan(TomoScanBase):
if self.master_file is None or not os.path.exists(self.master_file):
return
with h5py.File(self.master_file, 'r') as h5_file:
urls = []
urls = {}
if (self._entry in h5_file and
HDF5TomoScan._PROJ_PATH in h5_file[self._entry]):
image = h5_file[self._entry][HDF5TomoScan._PROJ_PATH]
......@@ -214,7 +214,7 @@ class HDF5TomoScan(TomoScanBase):
slice_number = slice_data[2]
silx_url = DataUrl(file_path=file_path, data_path=data_path,
data_slice=(slice_number,), scheme=scheme)
urls.append(silx_url)
urls[i_slice] = silx_url
return urls
@docstring(TomoScanBase.tomo_n)
......
......@@ -50,7 +50,9 @@ class _ScanMock:
:param scan_path:
:param n_radio:
:param n_ini_radio:
:param n_ini_radio: number of radio existing at t time. If None,
will create all the radio and consider the
acquisition as finished
:param n_extra_radio:
:param scan_range:
:param n_recons:
......@@ -74,10 +76,16 @@ class _ScanMock:
self.write_metadata(n_radio=n_radio, scan_range=scan_range,
ref_n=ref_n, dark_n=dark_n)
if n_ini_radio is None:
n_ini_radio = n_radio + n_extra_radio
call_acqui_end = True
else:
call_acqui_end = False
for i_radio in range(n_ini_radio):
self.add_radio(i_radio)
for i_extra_radio in range(n_extra_radio):
self.add_radio(i_extra_radio)
self.add_radio(n_radio+i_extra_radio)
for i_recons in range(n_recons):
self.add_reconstruction(i_recons)
for i_recons in range(n_pag_recons):
......@@ -85,6 +93,9 @@ class _ScanMock:
if recons_vol is True:
self.add_recons_vol()
if call_acqui_end is True:
self.end_acquisition()
def add_radio(self, index=None):
raise NotImplementedError('Base class')
......@@ -229,14 +240,14 @@ class MockEDF(_ScanMock):
self._last_radio_index += 1
index_ = self._last_radio_index
file_name = os.path.basename(self.scan_path) + '_{0:04d}'.format(index_) + ".edf"
f = os.path.join(self.scan_path, file_name)
if not os.path.exists(f):
data = self._get_radio_data(index=index_)
assert data.shape == (self.det_width, self.det_height)
edf_writer = fabio.edfimage.EdfImage(data=data,
header={"tata": "toto"})
edf_writer.write(f)
file_name = os.path.basename(self.scan_path) + '_{0:04d}'.format(index_) + ".edf"
f = os.path.join(self.scan_path, file_name)
if not os.path.exists(f):
data = self._get_radio_data(index=index_)
assert data.shape == (self.det_width, self.det_height)
edf_writer = fabio.edfimage.EdfImage(data=data,
header={"tata": "toto"})
edf_writer.write(f)
@staticmethod
def mockReconstruction(folder, nRecons=5, nPagRecons=0, volFile=False):
......
......@@ -77,7 +77,7 @@ class TestScanFactory(unittest.TestCase):
self.assertTrue(isinstance(scan, EDFTomoScan))
class FTSerieReconstructionTest(unittest.TestCase):
class TestDarksFlats(unittest.TestCase):
"""unit test for the FTSerieReconstruction functions"""
def setUp(self):
def saveData(data, _file, folder):
......@@ -145,6 +145,45 @@ class FTSerieReconstructionTest(unittest.TestCase):
self.assertTrue(12 not in self.acquiTwoFlats.flats)
class TestProjections(unittest.TestCase):
"""Test that the """
def setUp(self) -> None:
self.folder = tempfile.mkdtemp()
def tearDown(self) -> None:
shutil.rmtree(self.folder)
def testProjectionNoExtra(self):
mock = MockEDF(scan_path=self.folder, n_radio=10, n_extra_radio=0)
mock.end_acquisition()
scan = EDFTomoScan(scan=self.folder)
self.assertEqual(len(scan.projections), 10)
def testProjectionUpdate(self):
mock = MockEDF(scan_path=self.folder, n_radio=10, n_ini_radio=3)
scan = EDFTomoScan(scan=self.folder)
self.assertEqual(len(scan.projections), 3)
mock.add_radio()
self.assertEqual(len(scan.projections), 3)
scan.update()
self.assertEqual(len(scan.projections), 4)
self.assertTrue(isinstance(scan.projections[0], silx.io.url.DataUrl))
def testProjectionWithExtraRadio(self):
mock = MockEDF(scan_path=self.folder, n_radio=11, n_extra_radio=2,
scan_range=180)
mock.end_acquisition()
scan = EDFTomoScan(scan=self.folder)
self.assertEqual(len(scan.projections), 11+2)
proj_angle_dict = scan.get_proj_angle_url()
self.assertEqual(len(proj_angle_dict), 11+2)
self.assertTrue(90 in proj_angle_dict)
self.assertTrue(180 in proj_angle_dict)
self.assertTrue('90(1)' in proj_angle_dict)
self.assertTrue('0(1)' in proj_angle_dict)
self.assertTrue(360 not in proj_angle_dict)
class TestScanValidatorFindFiles(unittest.TestCase):
"""Function testing the getReconstructionsPaths function is correctly
functioning"""
......@@ -175,7 +214,7 @@ class TestScanValidatorFindFiles(unittest.TestCase):
shutil.rmtree(self.path)
def testGetRadioPaths(self):
nFound = len(EDFTomoScan.get_proj_paths(self.path))
nFound = len(EDFTomoScan.get_proj_urls(self.path))
self.assertTrue(nFound == self.N_RADIO)
......@@ -338,8 +377,8 @@ class TestScanBaseJSON(unittest.TestCase):
def suite():
test_suite = unittest.TestSuite()
for ui in (TestScanFactory, FTSerieReconstructionTest,
TestScanValidatorFindFiles, TestRadioPath,
for ui in (TestScanFactory, TestDarksFlats,
TestScanValidatorFindFiles, TestRadioPath, TestProjections,
TestTomoBaseHashable):
test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ui))
return test_suite
......
......@@ -74,9 +74,14 @@ class TestHDF5Scan(HDF5TestBaseClass):
self.assertFalse(url_1.is_absolute())
self.assertEquals(url_1.scheme(), 'silx')
def testFrames(self):
def testProjections(self):
projections = self.scan.projections
self.assertEqual(len(projections), 100)
proj_1 = projections[0]
self.assertEqual(proj_1.file_path(),
'../../../../../../users/opid19/W:/clemence/visualtomo/data_test2/tomo0001/tomo_0000.h5')
self.assertEqual(proj_1.data_slice(), ('0',))
self.assertTrue(100 not in projections)
@unittest.skip('no valid hdf5 acquisition defined yet')
def testDark(self):
......
......@@ -31,6 +31,7 @@ __date__ = "09/10/2019"
import os
import logging
from typing import Union
from collections import OrderedDict
logger = logging.getLogger(__name__)
......@@ -235,10 +236,14 @@ class TomoScanBase:
:type: float
:return: angle in degree as key and url as value
:rtype: dict
:raises: ValueError if the number of extra images found and scan_range
are incoherent
"""
assert n_projection is not None
res = {}
ordered_url = OrderedDict(sorted(urls.items(), key= lambda x: x))
res = {}
# deal with the 'standard' acquisitions
for proj_i in range(n_projection):
angle = proj_i * scan_range / (n_projection -1)
......@@ -250,7 +255,7 @@ class TomoScanBase:
if len(urls) > n_projection:
# deal with extra images (used to check if the sampled as moved for
# example)
extraImgs = urls[n_projection:]
extraImgs = list(ordered_url.keys())[n_projection:]
if len(extraImgs) in (4, 5):
if scan_range < 360:
logger.warning('incoherent data information to retrieve'
......@@ -278,8 +283,6 @@ class TomoScanBase:
res['90(1)'] = extraImgs[0]
res['0(1)'] = extraImgs[1]
else:
logger.warning('incoherent data information to retrieve scan'
'extra images angle')
for i_extra, extra in enumerate(extraImgs):
res['? (' + str(i_extra) + ')'] = extra
raise ValueError('incoherent data information to retrieve scan'
'extra images angle')
return res
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment