Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions DicomAnnotUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def create_annotation_dicom(annot_arrays, slide_file, geojson):

# add the annotation data
ds.AnnotationGroupSequence = []
i = 0
i = 1
idx = 1
point_indices = []
# make the array first?
Expand Down Expand Up @@ -298,7 +298,7 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
newFeature = deepcopy(featureTemplate)
newFeature['geometry']['type'] = "Ellipse"
newFeature['geometry']['coordinates'] = [center_x, center_y]
newFeature['geometry']["radius"] = [major_axis_length,minor_axis_length],
newFeature['geometry']["radius"] = [major_axis_length,minor_axis_length]
newFeature['geometry']["rotation"] = rotation
newFeature['bound']['type'] = "Point"
newFeature['bound']['coordinates'] = [center_x, center_y]
Expand Down Expand Up @@ -378,11 +378,15 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
#print("prev", prevIndex, "idx", idx)
# make a thing
points = coordinates_array[prevIndex:end_idx, :]
points = np.concatenate((points, [points[0]]))
polygon = np.concatenate((points, [points[0]]))
#print('len(points)', len(points))
if len(points) > 0:
newFeature = deepcopy(featureTemplate)
newFeature['geometry']['coordinates'].append(points.tolist())
if x.GraphicType == "POLYLINE":
newFeature['geometry']['type'] = "Polyline"
newFeature['geometry']['coordinates'].append(points.tolist())
else:
newFeature['geometry']['coordinates'].append(polygon.tolist())
bounding_box = _makeBound(points)
# [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y],[min_x, min_y]]
newFeature['bound']['coordinates'].append(bounding_box)
Expand All @@ -401,10 +405,14 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
# and the bound
# then add the last one
points = coordinates_array[prevIndex:, :]
points = np.concatenate((points, [points[0]]))
polygon = np.concatenate((points, [points[0]]))
if len(points) > 0:
newFeature = deepcopy(featureTemplate)
newFeature['geometry']['coordinates'].append(points.tolist())
if x.GraphicType == "POLYLINE":
newFeature['geometry']['type'] = "Polyline"
newFeature['geometry']['coordinates'].append(points.tolist())
else:
newFeature['geometry']['coordinates'].append(polygon.tolist())
bounding_box = _makeBound(points)
# [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y],[min_x, min_y]]
newFeature['bound']['coordinates'].append(bounding_box)
Expand All @@ -422,9 +430,13 @@ def dicomToCamic(annot_path, image_dimensions, output_file, source_url=None, sli
else:
# whole thing at once. Only do area and circumference here.
points = coordinates_array
points = np.concatenate((points, [points[0]]))
polygon = np.concatenate((points, [points[0]]))
newFeature = deepcopy(featureTemplate)
newFeature['geometry']['coordinates'].append(points.tolist())
if x.GraphicType == "POLYLINE":
newFeature['geometry']['type'] = "Polyline"
newFeature['geometry']['coordinates'].append(points.tolist())
else:
newFeature['geometry']['coordinates'].append(polygon.tolist())
bounding_box = _makeBound(points)
# [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y],[min_x, min_y]]
newFeature['bound']['coordinates'].append(bounding_box)
Expand Down
44 changes: 40 additions & 4 deletions SlideServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import hashlib
from urllib.parse import urlparse
from dicomweb_client.api import DICOMwebClient
import aiohttp
import asyncio

from DicomAnnotUtils import dicomToCamic
import pydicom
Expand Down Expand Up @@ -59,6 +61,12 @@
app.config['SECRET_KEY'] = os.urandom(24)
app.config['ROI_FOLDER'] = "/images/roiDownload"

download_folder = os.getenv('DOWNLOAD_FOLDER', app.config['UPLOAD_FOLDER'])
app.config['DOWNLOAD_FOLDER'] = download_folder

if os.getenv("ALLOW_DOWNLOAD_ZIP") == "True":
ALLOWED_EXTENSIONS.add("zip")

#creating a uploading folder if it doesn't exist
if not os.path.exists(app.config['TEMP_FOLDER']):
os.mkdir(app.config['TEMP_FOLDER'])
Expand Down Expand Up @@ -311,7 +319,7 @@ def getSlide(image_name):
image_name = secure_relative_path(image_name)
if not verify_extension(image_name):
return flask.Response(json.dumps({"error": "Bad image type requested"}), status=400, mimetype='text/json')
folder = app.config['UPLOAD_FOLDER']
folder = app.config['DOWNLOAD_FOLDER']
if os.sep in image_name:
folder_and_file = image_name.rsplit(os.sep, 1)
folder = os.path.join(folder, folder_and_file[0])
Expand Down Expand Up @@ -775,7 +783,7 @@ def find_referenced_image_by_files(source_url, study, ds):
# If the instance is not found in the study
return None, None

def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
def OLDdownloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
instance_url = source_url + f"/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}"
response = requests.get(instance_url, stream=True)
if response.status_code == 200:
Expand All @@ -788,9 +796,9 @@ def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn)
if chunk:
if not dicom_started:
# Check if the chunk contains "\r\n\r\n""
if b"\r\n\r\n" in chunk:
start_idx = chunk.find(b"\r\n\r\n")
if start_idx != -1:
# Find the position of "\r\n\r\n"" in the chunk
start_idx = chunk.find(b"\r\n\r\n")
file.write(chunk[start_idx + 4:])
# Set dicom_started to True
dicom_started = True
Expand All @@ -805,6 +813,34 @@ def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn)
else:
print(f"Failed to retrieve DICOM instance. Status code: {response.status_code}")

def downloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
asyncio.run(doDownloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn))

async def doDownloadRawDicom(source_url, study_uid, series_uid, instance_uid, output_fn):
instance_url = source_url + f"/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}"
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(instance_url) as resp:
reader = aiohttp.MultipartReader.from_response(resp)
metadata = None
filedata = None
while True:
part = await reader.next()
if part is None:
break
else:
#print(dir(part))
#filedata = await part.read(decode=False)
app.logger.info("Working on file: " + output_fn)
with open(output_fn, 'wb') as fd:
while True:
part_chunk = await part.read_chunk(1024*1024)
if part_chunk is None or len(part_chunk)==0:
break
else:
fd.write(part_chunk)



# dicom web based routes

def doDicomSlideDownloads(source_url, study, series, instance_list, camic_slide_id):
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ google-auth-oauthlib
pycurl
pydicom
dicomweb-client
pymongo
pymongo
aiohttp
Loading