Skip to content

Commit 62c6131

Browse files
authored
Merge pull request #91 from camicroscope/develop
for 3.12.1
2 parents d95830f + 33008a5 commit 62c6131

3 files changed

Lines changed: 62 additions & 13 deletions

File tree

DicomAnnotUtils.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def create_annotation_dicom(annot_arrays, slide_file, geojson):
134134

135135
# add the annotation data
136136
ds.AnnotationGroupSequence = []
137-
i = 0
137+
i = 1
138138
idx = 1
139139
point_indices = []
140140
# make the array first?
@@ -298,7 +298,7 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
298298
newFeature = deepcopy(featureTemplate)
299299
newFeature['geometry']['type'] = "Ellipse"
300300
newFeature['geometry']['coordinates'] = [center_x, center_y]
301-
newFeature['geometry']["radius"] = [major_axis_length,minor_axis_length],
301+
newFeature['geometry']["radius"] = [major_axis_length,minor_axis_length]
302302
newFeature['geometry']["rotation"] = rotation
303303
newFeature['bound']['type'] = "Point"
304304
newFeature['bound']['coordinates'] = [center_x, center_y]
@@ -378,11 +378,15 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
378378
#print("prev", prevIndex, "idx", idx)
379379
# make a thing
380380
points = coordinates_array[prevIndex:end_idx, :]
381-
points = np.concatenate((points, [points[0]]))
381+
polygon = np.concatenate((points, [points[0]]))
382382
#print('len(points)', len(points))
383383
if len(points) > 0:
384384
newFeature = deepcopy(featureTemplate)
385-
newFeature['geometry']['coordinates'].append(points.tolist())
385+
if x.GraphicType == "POLYLINE":
386+
newFeature['geometry']['type'] = "Polyline"
387+
newFeature['geometry']['coordinates'].append(points.tolist())
388+
else:
389+
newFeature['geometry']['coordinates'].append(polygon.tolist())
386390
bounding_box = _makeBound(points)
387391
# [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y],[min_x, min_y]]
388392
newFeature['bound']['coordinates'].append(bounding_box)
@@ -401,10 +405,14 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
401405
# and the bound
402406
# then add the last one
403407
points = coordinates_array[prevIndex:, :]
404-
points = np.concatenate((points, [points[0]]))
408+
polygon = np.concatenate((points, [points[0]]))
405409
if len(points) > 0:
406410
newFeature = deepcopy(featureTemplate)
407-
newFeature['geometry']['coordinates'].append(points.tolist())
411+
if x.GraphicType == "POLYLINE":
412+
newFeature['geometry']['type'] = "Polyline"
413+
newFeature['geometry']['coordinates'].append(points.tolist())
414+
else:
415+
newFeature['geometry']['coordinates'].append(polygon.tolist())
408416
bounding_box = _makeBound(points)
409417
# [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y],[min_x, min_y]]
410418
newFeature['bound']['coordinates'].append(bounding_box)
@@ -422,9 +430,13 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
422430
else:
423431
# whole thing at once. Only do area and circumference here.
424432
points = coordinates_array
425-
points = np.concatenate((points, [points[0]]))
433+
polygon = np.concatenate((points, [points[0]]))
426434
newFeature = deepcopy(featureTemplate)
427-
newFeature['geometry']['coordinates'].append(points.tolist())
435+
if x.GraphicType == "POLYLINE":
436+
newFeature['geometry']['type'] = "Polyline"
437+
newFeature['geometry']['coordinates'].append(points.tolist())
438+
else:
439+
newFeature['geometry']['coordinates'].append(polygon.tolist())
428440
bounding_box = _makeBound(points)
429441
# [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y],[min_x, min_y]]
430442
newFeature['bound']['coordinates'].append(bounding_box)

SlideServer.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import hashlib
3232
from urllib.parse import urlparse
3333
from dicomweb_client.api import DICOMwebClient
34+
import aiohttp
35+
import asyncio
3436

3537
from DicomAnnotUtils import dicomToCamic
3638
import pydicom
@@ -59,6 +61,12 @@
5961
app.config['SECRET_KEY'] = os.urandom(24)
6062
app.config['ROI_FOLDER'] = "/images/roiDownload"
6163

64+
download_folder = os.getenv('DOWNLOAD_FOLDER', app.config['UPLOAD_FOLDER'])
65+
app.config['DOWNLOAD_FOLDER'] = download_folder
66+
67+
if os.getenv("ALLOW_DOWNLOAD_ZIP") == "True":
68+
ALLOWED_EXTENSIONS.add("zip")
69+
6270
#creating a uploading folder if it doesn't exist
6371
if not os.path.exists(app.config['TEMP_FOLDER']):
6472
os.mkdir(app.config['TEMP_FOLDER'])
@@ -311,7 +319,7 @@ def getSlide(image_name):
311319
image_name = secure_relative_path(image_name)
312320
if not verify_extension(image_name):
313321
return flask.Response(json.dumps({"error": "Bad image type requested"}), status=400, mimetype='text/json')
314-
folder = app.config['UPLOAD_FOLDER']
322+
folder = app.config['DOWNLOAD_FOLDER']
315323
if os.sep in image_name:
316324
folder_and_file = image_name.rsplit(os.sep, 1)
317325
folder = os.path.join(folder, folder_and_file[0])
@@ -775,7 +783,7 @@ def find_referenced_image_by_files(source_url, study, ds):
775783
# If the instance is not found in the study
776784
return None, None
777785

778-
def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
786+
def OLDdownloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
779787
instance_url = source_url + f"/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}"
780788
response = requests.get(instance_url, stream=True)
781789
if response.status_code == 200:
@@ -788,9 +796,9 @@ def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn)
788796
if chunk:
789797
if not dicom_started:
790798
# Check if the chunk contains "\r\n\r\n""
791-
if b"\r\n\r\n" in chunk:
799+
start_idx = chunk.find(b"\r\n\r\n")
800+
if start_idx != -1:
792801
# Find the position of "\r\n\r\n"" in the chunk
793-
start_idx = chunk.find(b"\r\n\r\n")
794802
file.write(chunk[start_idx + 4:])
795803
# Set dicom_started to True
796804
dicom_started = True
@@ -805,6 +813,34 @@ def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn)
805813
else:
806814
print(f"Failed to retrieve DICOM instance. Status code: {response.status_code}")
807815

816+
def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
817+
asyncio.run(doDownloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn))
818+
819+
async def doDownloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
820+
instance_url = source_url + f"/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}"
821+
async with aiohttp.ClientSession(trust_env=True) as session:
822+
async with session.get(instance_url) as resp:
823+
reader = aiohttp.MultipartReader.from_response(resp)
824+
metadata = None
825+
filedata = None
826+
while True:
827+
part = await reader.next()
828+
if part is None:
829+
break
830+
else:
831+
#print(dir(part))
832+
#filedata = await part.read(decode=False)
833+
app.logger.info("Working on file: " + output_fn)
834+
with open(output_fn, 'wb') as fd:
835+
while True:
836+
part_chunk = await part.read_chunk(1024*1024)
837+
if part_chunk is None or len(part_chunk)==0:
838+
break
839+
else:
840+
fd.write(part_chunk)
841+
842+
843+
808844
# dicom web based routes
809845

810846
def doDicomSlideDownloads(source_url, study, series, instance_list, camic_slide_id):

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ google-auth-oauthlib
1313
pycurl
1414
pydicom
1515
dicomweb-client
16-
pymongo
16+
pymongo
17+
aiohttp

0 commit comments

Comments
 (0)