mosamatic2 2.0.7__py3-none-any.whl → 2.0.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mosamatic2 might be problematic. Click here for more details.

mosamatic2/cli.py CHANGED
@@ -6,6 +6,7 @@ from mosamatic2.commands import (
6
6
  createpngsfromsegmentations,
7
7
  dicom2nifti,
8
8
  selectslicefromscans,
9
+ createdicomsummary,
9
10
  )
10
11
  from mosamatic2.core.utils import show_doc_command
11
12
 
@@ -33,4 +34,5 @@ main.add_command(segmentmusclefatl3tensorflow.segmentmusclefatl3tensorflow)
33
34
  main.add_command(createpngsfromsegmentations.createpngsfromsegmentations)
34
35
  main.add_command(dicom2nifti.dicom2nifti)
35
36
  main.add_command(selectslicefromscans.selectslicefromscans)
37
+ main.add_command(createdicomsummary.createdicomsummary)
36
38
  main.add_command(show_doc_command(main)) # Special command to show long description for command
@@ -0,0 +1,61 @@
1
+ import click
2
+
3
+ from mosamatic2.core.tasks import CreateDicomSummaryTask
4
+
5
+
6
+ @click.command(help='Creates a DICOM summary inside a root directory')
7
+ @click.option(
8
+ '--directory',
9
+ required=True,
10
+ type=click.Path(exists=True),
11
+ help='Root directory with DICOM images (can be multiple scans)',
12
+ )
13
+ @click.option(
14
+ '--output',
15
+ required=True,
16
+ type=click.Path(),
17
+ help='Output directory'
18
+ )
19
+ @click.option(
20
+ '--overwrite',
21
+ type=click.BOOL,
22
+ default=False,
23
+ help='Overwrite [true|false]'
24
+ )
25
+ def createdicomsummary(directory, output, overwrite):
26
+ """
27
+ Creates a DICOM summary inside a root directory. Each patient should have
28
+ its own directory. Inside each patient's directory, there can be multiple
29
+ scans (called series) and multiple DICOM files per scan. The output of this
30
+ command is a file summary.txt (stored in the output directory) that contains
31
+ the following information:
32
+
33
+ - A list of patient directory names with the number of scans inside each
34
+ patient directory
35
+ - For each patient directory and scan directory the following information:
36
+ - Nr. of DICOM images in the scan
37
+ - Modality (e.g., CT or MRI)
38
+ - Image type (e.g., for Dixon scans can be in-phase, opposite-phase,
39
+ water or fat images)
40
+ - Rows/columns (size of the images)
41
+ - Pixel spacing (size of each pixel in mm^2)
42
+ - Slice thickness: (thickness of each image slice)
43
+
44
+ Parameters
45
+ ----------
46
+ --directory : str
47
+ Root directory with patient directories, scans and DICOM images
48
+
49
+ --output : str
50
+ Path to output directory
51
+
52
+ --overwrite : bool
53
+ Overwrite contents output directory [true|false]
54
+ """
55
+ task = CreateDicomSummaryTask(
56
+ inputs={'directory': directory},
57
+ params=None,
58
+ output=output,
59
+ overwrite=overwrite,
60
+ )
61
+ task.run()
@@ -4,15 +4,24 @@ from mosamatic2.core.utils import (
4
4
  load_dicom,
5
5
  is_jpeg2000_compressed,
6
6
  )
7
+ from mosamatic2.core.managers.logmanager import LogManager
8
+
9
+ LOG = LogManager()
7
10
 
8
11
 
9
12
  class DicomImage(FileData):
10
13
  def load(self):
11
14
  if self.path():
12
- if is_dicom(self.path()):
13
- p = load_dicom(self.path())
15
+ p = load_dicom(self.path())
16
+ if p:
14
17
  if is_jpeg2000_compressed(p):
15
18
  p.decompress()
16
19
  self.set_object(p)
17
20
  return True
21
+ # if is_dicom(self.path()):
22
+ # p = load_dicom(self.path())
23
+ # if is_jpeg2000_compressed(p):
24
+ # p.decompress()
25
+ # self.set_object(p)
26
+ # return True
18
27
  return False
@@ -8,6 +8,9 @@ from mosamatic2.core.tasks import (
8
8
  CreatePngsFromSegmentationsTask,
9
9
  CalculateScoresTask,
10
10
  )
11
+ from mosamatic2.core.managers.logmanager import LogManager
12
+
13
+ LOG = LogManager()
11
14
 
12
15
 
13
16
  class DefaultPipeline(Pipeline):
@@ -25,6 +28,7 @@ class DefaultPipeline(Pipeline):
25
28
  ]
26
29
  def __init__(self, inputs, params, output, overwrite):
27
30
  super(DefaultPipeline, self).__init__(inputs, params, output, overwrite)
31
+ LOG.info('Found {} images to process'.format(len(os.listdir(self.input('images')))))
28
32
  model_type = self.param('model_type')
29
33
  # segmentation_task_class = SegmentMuscleFatL3Task if model_type == 'pytorch' else SegmentMuscleFatL3TensorFlowTask
30
34
  segmentation_task_class = SegmentMuscleFatL3TensorFlowTask
@@ -25,8 +25,9 @@ class CreateDicomSummaryTask(Task):
25
25
  for root, dirs, files in os.walk(patient_dir_path):
26
26
  for f in files:
27
27
  f_path = os.path.join(root, f)
28
- if is_dicom(f_path):
29
- p = load_dicom(f_path, stop_before_pixels=True)
28
+ # if is_dicom(f_path):
29
+ p = load_dicom(f_path, stop_before_pixels=True)
30
+ if p:
30
31
  series_instance_uid = p.SeriesInstanceUID
31
32
  if not series_instance_uid in data[patient_dir_name].keys():
32
33
  data[patient_dir_name][series_instance_uid] = []
mosamatic2/core/utils.py CHANGED
@@ -14,10 +14,12 @@ from pydicom.uid import (
14
14
  ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian
15
15
  )
16
16
  from PIL import Image
17
+ from mosamatic2.core.managers.logmanager import LogManager
17
18
 
18
19
  warnings.filterwarnings("ignore", message="Invalid value for VR UI:", category=UserWarning)
19
20
 
20
21
  MUSCLE, VAT, SAT = 1, 5, 7
22
+ LOG = LogManager()
21
23
 
22
24
 
23
25
  def create_name_with_timestamp(prefix: str='') -> str:
@@ -102,17 +104,34 @@ def is_dicom(f):
102
104
  pydicom.dcmread(f, stop_before_pixels=True)
103
105
  return True
104
106
  except pydicom.errors.InvalidDicomError:
105
- return False
107
+ try:
108
+ pydicom.dcmread(f, stop_before_pixels=True, force=True)
109
+ return True
110
+ except pydicom.errors.InvalidDicomError:
111
+ pass
112
+ return False
106
113
 
107
114
 
108
115
  def load_dicom(f, stop_before_pixels=False):
109
- if is_dicom(f):
116
+ try:
110
117
  return pydicom.dcmread(f, stop_before_pixels=stop_before_pixels)
118
+ except pydicom.errors.InvalidDicomError:
119
+ try:
120
+ p = pydicom.dcmread(f, stop_before_pixels=stop_before_pixels, force=True)
121
+ if hasattr(p, 'SOPClassUID'):
122
+ if not hasattr(p.file_meta, 'TransferSyntaxUID'):
123
+ LOG.warning(f'DICOM file {f} does not have FileMetaData/TransferSyntaxUID, trying to fix...')
124
+ p.file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian
125
+ return p
126
+ except pydicom.errors.InvalidDicomError:
127
+ pass
111
128
  return None
112
129
 
113
130
 
114
131
  def is_jpeg2000_compressed(p):
115
- return p.file_meta.TransferSyntaxUID not in [ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian]
132
+ if hasattr(p.file_meta, 'TransferSyntaxUID'):
133
+ return p.file_meta.TransferSyntaxUID not in [ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian]
134
+ return False
116
135
 
117
136
 
118
137
  def is_numpy_array(value):
mosamatic2/server.py CHANGED
@@ -7,6 +7,7 @@ from mosamatic2.core.tasks import CalculateScoresTask
7
7
  from mosamatic2.core.tasks import CreatePngsFromSegmentationsTask
8
8
  from mosamatic2.core.tasks import Dicom2NiftiTask
9
9
  from mosamatic2.core.tasks import SelectSliceFromScansTask
10
+ from mosamatic2.core.tasks import CreateDicomSummaryTask
10
11
 
11
12
  app = Flask(__name__)
12
13
 
@@ -122,6 +123,21 @@ def run_selectslicefromscans():
122
123
  return 'PASSED'
123
124
 
124
125
 
126
+ @app.route('/createdicomsummary')
127
+ def run_createdicomsummary():
128
+ directory = request.args.get('directory')
129
+ output = request.args.get('output')
130
+ overwrite = request.args.get('overwrite', default=True, type=bool)
131
+ task = CreateDicomSummaryTask(
132
+ inputs={'directory': directory},
133
+ params=None,
134
+ output=output,
135
+ overwrite=overwrite,
136
+ )
137
+ task.run()
138
+ return 'PASSED'
139
+
140
+
125
141
  def main():
126
142
  parser = argparse.ArgumentParser()
127
143
  parser.add_argument('--port', type=int, default=constants.MOSAMATIC2_SERVER_PORT)
@@ -1 +1 @@
1
- 2.0.7
1
+ 2.0.9
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mosamatic2
3
- Version: 2.0.7
3
+ Version: 2.0.9
4
4
  Summary:
5
5
  Author: Ralph Brecheisen
6
6
  Author-email: r.brecheisen@maastrichtuniversity.nl
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.11
10
10
  Requires-Dist: antspyx (>=0.5.4)
11
11
  Requires-Dist: dicom2nifti (>=2.6.2)
12
12
  Requires-Dist: flask (>=3.1.2)
13
+ Requires-Dist: moosez
13
14
  Requires-Dist: nibabel (>=5.3.2)
14
15
  Requires-Dist: numpy (>=1.26.4)
15
16
  Requires-Dist: openpyxl (>=3.1.5)
@@ -1,9 +1,10 @@
1
1
  models.py,sha256=Kx6oWKt7IpTTxrhBDrX61X-ZX12J7yPkJFuhVDsDHoQ,8807
2
2
  mosamatic2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  mosamatic2/app.py,sha256=RIUa5tvMYFcmEII4xZPLZZdx9dXWqBvwkxkl_R97Jkw,860
4
- mosamatic2/cli.py,sha256=RTogXBXiYW_EDTmnX7TXx2T22Yth_1AwLFiJP2IUDMc,1289
4
+ mosamatic2/cli.py,sha256=kqLdLCZCA7-xxgOOWohsCCrD6Jz3MamslmCl-41R2rA,1371
5
5
  mosamatic2/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  mosamatic2/commands/calculatescores.py,sha256=Lb8Q8L2yq7Tt6VBJ6_lltRuldrev_pac6fcgF-xzZyE,1984
7
+ mosamatic2/commands/createdicomsummary.py,sha256=qbVgWGIJPBL8vTBcAxfThloQ_q15OfQy5ohMprzZL4E,1955
7
8
  mosamatic2/commands/createpngsfromsegmentations.py,sha256=uUAQJVTqOkBCfENzi21RBNYvf6_nuesx1MeR3j_-7dM,1682
8
9
  mosamatic2/commands/dicom2nifti.py,sha256=4hMvglxdOid7p7P_Jc-Tudsf93JRMlYaQsEQctLq2d4,1015
9
10
  mosamatic2/commands/rescaledicomimages.py,sha256=25QdCzB5s0sRwkTb3o5zco2bIwy6LttNf7i97kGBDYQ,1280
@@ -12,7 +13,7 @@ mosamatic2/commands/selectslicefromscans.py,sha256=3398PM2uBcxF6wpb0-c-Itp_qxoAx
12
13
  mosamatic2/constants.py,sha256=MVYMwO-x2jQSN37o3zNkRseVQ1nYRA3mLv3v_Q0Mlds,1284
13
14
  mosamatic2/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
15
  mosamatic2/core/data/__init__.py,sha256=j9iGqUTJlGF0N0gPrzzpe_Dhv0Bj9c6FdQ1g7U-_j2g,298
15
- mosamatic2/core/data/dicomimage.py,sha256=jv1KIZBgN3SFjqgjXcPG_cx23RPauJ2TF1CzA9vj3Z8,484
16
+ mosamatic2/core/data/dicomimage.py,sha256=e4n-xw5FP_bmvjgPUSg_wPDkByYscaEm3TWAzjd935Y,786
16
17
  mosamatic2/core/data/dicomimageseries.py,sha256=OZkNi15crL8nEA-PGYsM0k9NMi2mMHRvDRePr_-czvA,849
17
18
  mosamatic2/core/data/dixonseries.py,sha256=kq9fy65MSM2XwiScqp7b3rQ09JmpyGwbG6ldZsuPRrM,516
18
19
  mosamatic2/core/data/filedata.py,sha256=hCnpizGqOpxzIADJkDS2_NSmKVLL1u49TYjSJE5UXQo,515
@@ -24,14 +25,14 @@ mosamatic2/core/managers/logmanager.py,sha256=NEaXvhl0aILjBbK710GaWanVuuNvB51HpH
24
25
  mosamatic2/core/managers/logmanagerlistener.py,sha256=Gaig07yjBnyQq9I8sN85olTEeDCDyCFQnEJdwzvmgvc,99
25
26
  mosamatic2/core/pipelines/__init__.py,sha256=Esb4TQFvY2soU2dfQPgVlhfTx1LdxYrPBiuAKDosHqA,85
26
27
  mosamatic2/core/pipelines/defaultpipeline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- mosamatic2/core/pipelines/defaultpipeline/defaultpipeline.py,sha256=EUblRhLZXhslz9bdBmx8v9yjpgOdsHviqQZ5elK8gNQ,2901
28
+ mosamatic2/core/pipelines/defaultpipeline/defaultpipeline.py,sha256=Bme0r_shnrllWYCYDNc6cLM2fQC2yD8RJKpRdoh_6Uc,3077
28
29
  mosamatic2/core/pipelines/pipeline.py,sha256=mRxKXLKwgKDpc8R9mCI6gDKGJ2lKVxRQ__Sf0Mfn_Qc,384
29
30
  mosamatic2/core/singleton.py,sha256=FV0k_LlOCmFhlWN6gf1c2x7YXWyd8-7DsIMvOKrI6NY,224
30
31
  mosamatic2/core/tasks/__init__.py,sha256=w03AyCk2BQ6gGPBEKhtad6lt9WuwHC-nMztv7wQNwb4,759
31
32
  mosamatic2/core/tasks/calculatescorestask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
33
  mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py,sha256=jEbogrEnEtMbmfQ8KOGSUdGMhdeX69Bv01-82faRIlY,6617
33
34
  mosamatic2/core/tasks/createdicomsummarytask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- mosamatic2/core/tasks/createdicomsummarytask/createdicomsummarytask.py,sha256=TebP3bI_TAUa93mp5XtnPW5NSVFMvbvb-CQAQnh6RfY,2932
35
+ mosamatic2/core/tasks/createdicomsummarytask/createdicomsummarytask.py,sha256=kcdwIBnoAXexok2j6_tF_s6gwvn2DvjLwe_VhdODpbM,2957
35
36
  mosamatic2/core/tasks/createpngsfromsegmentationstask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
37
  mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py,sha256=1UpOsp1CH668BQ0g4tALou_tFgisC306VcvqOKSDuTo,1884
37
38
  mosamatic2/core/tasks/dicom2niftitask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -44,15 +45,15 @@ mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorf
44
45
  mosamatic2/core/tasks/selectslicefromscanstask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
46
  mosamatic2/core/tasks/selectslicefromscanstask/selectslicefromscanstask.py,sha256=1a_QHcIdS4VB39cNEBniaaDzUx3k8DcR0wCtdr8G1d0,4586
46
47
  mosamatic2/core/tasks/task.py,sha256=APPnid6dpSGkPuDqU1vm2RIMR5vkpvbP1CPHUMjympg,1691
47
- mosamatic2/core/utils.py,sha256=zh44FNOWxNKuZ4FcM7VIfMvdlzOr4AA8_PJ1r-6_83k,10855
48
- mosamatic2/server.py,sha256=jiUc7-aFaDMSY2hg6BhMC9C2FU4V2OrMBSoiIAP8Zcs,4158
48
+ mosamatic2/core/utils.py,sha256=iib_o_dD4hnqGIgOxLOfvMFOqLZOpt0iT_8Oarkmdjs,11723
49
+ mosamatic2/server.py,sha256=-cZ9BPsZUXoINKqwhCHN8c59mlvzzDXzTVxsYt9au70,4644
49
50
  mosamatic2/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
51
  mosamatic2/ui/mainwindow.py,sha256=nV9RqqSZVoVbU2opJIk7E3n4GvZWtuDETxmzwzmx4mg,13099
51
52
  mosamatic2/ui/resources/icons/mosamatic2.icns,sha256=OfhC-diJTIgaNMOezxKKilGsY7mRkaGdU5dGr0MOjIA,2994125
52
53
  mosamatic2/ui/resources/icons/mosamatic2.ico,sha256=ySD3RYluHK3pgS0Eas7eKrVk_AskdLQ4qs_IT-wNhq4,12229
53
54
  mosamatic2/ui/resources/icons/spinner.gif,sha256=rvaac6GUZauHSPFSOLWr0RmLfjmtZih2Q8knQ2WP3Po,16240
54
55
  mosamatic2/ui/resources/images/body-composition.jpg,sha256=KD-BudbXwThB4lJOZZN-ad5-TZRaaZ5cKTH0Ar1TOZs,21227
55
- mosamatic2/ui/resources/VERSION,sha256=KwH-299m3oBSV3-QDLRQdLqL7fYkxUJhV8qlxIIJb74,8
56
+ mosamatic2/ui/resources/VERSION,sha256=GK-SWujODPcbTcVr82R22iPUlrjhCG6gyHU--L4NyBQ,8
56
57
  mosamatic2/ui/settings.py,sha256=YEVHYJIfNsqMO3v1pjzgh7Pih9GGoUX7S9s8S-sBNUk,2121
57
58
  mosamatic2/ui/utils.py,sha256=6bbPIrh4RJ_yhQKNZrgPbL4XeUEogjIjbk_e5c3QS5g,853
58
59
  mosamatic2/ui/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -84,7 +85,7 @@ mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualizatio
84
85
  mosamatic2/ui/widgets/panels/visualizations/visualization.py,sha256=JvqTJi7cCGYK1-wrN2oURdCOBoPS2clVUyYglhkoVJg,178
85
86
  mosamatic2/ui/widgets/splashscreen.py,sha256=MS-OczOWfwwEQNQd-JWe9_Mh57css0cSQgbu973rwQo,4056
86
87
  mosamatic2/ui/worker.py,sha256=v7e3gq7MUudgpB1BJW-P7j5wurzu6-HG5m7I6WHgJp0,699
87
- mosamatic2-2.0.7.dist-info/entry_points.txt,sha256=MCUpKkgbej1clgp8EqlLQGs0BIKwGPcBPiVWLfGz9Gw,126
88
- mosamatic2-2.0.7.dist-info/METADATA,sha256=aX9U18Z7h4eR4CR3bRliqeGp8VIwSiBGvw9d42MpowU,1467
89
- mosamatic2-2.0.7.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
90
- mosamatic2-2.0.7.dist-info/RECORD,,
88
+ mosamatic2-2.0.9.dist-info/entry_points.txt,sha256=MCUpKkgbej1clgp8EqlLQGs0BIKwGPcBPiVWLfGz9Gw,126
89
+ mosamatic2-2.0.9.dist-info/METADATA,sha256=ghYgnAGDjhsgKeX6PpcMuQ_Dr2ZkEI4HMXkMXBRpLW8,1489
90
+ mosamatic2-2.0.9.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
91
+ mosamatic2-2.0.9.dist-info/RECORD,,