Skip to content
Open
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
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ WORKDIR $mc_path/multic/cli
RUN python -m slicer_cli_web.cli_list_entrypoint --list_cli
RUN python -m slicer_cli_web.cli_list_entrypoint MultiCompartmentSegment --help
RUN python -m slicer_cli_web.cli_list_entrypoint FeatureExtraction --help
RUN python -m slicer_cli_web.cli_list_entrypoint MultiCompartmentTrain --help


ENTRYPOINT ["/bin/bash", "docker-entrypoint.sh"]
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<title>Multi Compartment Segmentation</title>
<description>Segments multi-level structures from a whole-slide image</description>
<version>0.1.0</version>
<documentation-url>https://github.com/SarderLab/deeplab-WSI</documentation-url>
<documentation-url>https://github.com/SarderLab/Multi-Compartment-Segmentation</documentation-url>
<license>Apache 2.0</license>
<contributor>Sayat Mimar (UFL)</contributor>
<acknowledgements>This work is part of efforts in digital pathology by the Sarder Lab: UFL.</acknowledgements>
Expand Down
173 changes: 173 additions & 0 deletions multic/cli/MultiCompartmentTrain/MultiCompartmentTrain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import os
import sys
from glob import glob
import girder_client
from ctk_cli import CLIArgumentParser

sys.path.append("..")
from segmentationschool.utils.mask_to_xml import xml_create, xml_add_annotation, xml_add_region, xml_save
from segmentationschool.utils.xml_to_mask import write_minmax_to_xml

NAMES = ['cortical_interstitium','medullary_interstitium','non_globally_sclerotic_glomeruli','globally_sclerotic_glomeruli','tubules','arteries/arterioles']


def main(args):

folder = args.training_data_dir
base_dir_id = folder.split('/')[-2]
_ = os.system("printf '\nUsing data from girder_client Folder: {}\n'".format(folder))

_ = os.system("printf '\n---\n\nFOUND: [{}]\n'".format(args.init_modelfile))

gc = girder_client.GirderClient(apiUrl=args.girderApiUrl)
gc.setToken(args.girderToken)
# get files in folder
files = gc.listItem(base_dir_id)
xml_color=[65280]*(len(NAMES)+1)
cwd = os.getcwd()
print(cwd)
os.chdir(cwd)

tmp = folder

slides_used = []
ignore_label = len(NAMES)+1
for file in files:
slidename = file['name']
_ = os.system("printf '\n---\n\nFOUND: [{}]\n'".format(slidename))
skipSlide = 0

# get annotation
item = gc.getItem(file['_id'])
annot = gc.get('/annotation/item/{}'.format(item['_id']), parameters={'sort': 'updated'})
annot.reverse()
annot = list(annot)
_ = os.system("printf '\tfound [{}] annotation layers...\n'".format(len(annot)))

# create root for xml file
xmlAnnot = xml_create()

# all compartments
for class_,compart in enumerate(NAMES):

compart = compart.replace(' ','')
class_ +=1
# add layer to xml
xmlAnnot = xml_add_annotation(Annotations=xmlAnnot, xml_color=xml_color, annotationID=class_)

# test all annotation layers in order created
for iter,a in enumerate(annot):


try:
# check for annotation layer by name
a_name = a['annotation']['name'].replace(' ','')
except:
a_name = None

if a_name == compart:
# track all layers present
skipSlide +=1

pointsList = []

# load json data
_ = os.system("printf '\tloading annotation layer: [{}]\n'".format(compart))

a_data = a['annotation']['elements']

for data in a_data:
pointList = []
points = data['points']
for point in points:
pt_dict = {'X': round(point[0]), 'Y': round(point[1])}
pointList.append(pt_dict)
pointsList.append(pointList)

# write annotations to xml
for i in range(len(pointsList)):
pointList = pointsList[i]
xmlAnnot = xml_add_region(Annotations=xmlAnnot, pointList=pointList, annotationID=class_)

# print(a['_version'], a['updated'], a['created'])
break

if skipSlide != len(NAMES):
_ = os.system("printf '\tThis slide is missing annotation layers\n'")
_ = os.system("printf '\tSKIPPING SLIDE...\n'")
del xmlAnnot
continue # correct layers not present
# compart = 'ignore_label'
# # test all annotation layers in order created
# for iter,a in enumerate(annot):
# try:
# # check for annotation layer by name
# a_name = a['annotation']['name'].replace(' ','')
# except:
# a_name = None
# if a_name == compart:
# pointsList = []
# # load json data
# _ = os.system("printf '\tloading annotation layer: [{}]\n'".format(compart))
# a_data = a['annotation']['elements']
# for data in a_data:
# pointList = []
# if data['type'] == 'polyline':
# points = data['points']
# elif data['type'] == 'rectangle':
# center = data['center']
# width = data['width']/2
# height = data['height']/2
# points = [[ center[0]-width, center[1]-width ],[ center[0]+width, center[1]+width ]]
# for point in points:
# pt_dict = {'X': round(point[0]), 'Y': round(point[1])}
# pointList.append(pt_dict)
# pointsList.append(pointList)
# # write annotations to xml

# for i in range(len(pointsList)):
# pointList = pointsList[i]
# xmlAnnot = xml_add_region(Annotations=xmlAnnot, pointList=pointList, annotationID=ignore_label)
# break

# include slide and fetch annotations
_ = os.system("printf '\tFETCHING SLIDE...\n'")
os.rename('{}/{}'.format(folder, slidename), '{}/{}'.format(tmp, slidename))
slides_used.append(slidename)

xml_path = '{}/{}.xml'.format(tmp, os.path.splitext(slidename)[0])
_ = os.system("printf '\tsaving a created xml annotation file: [{}]\n'".format(xml_path))
xml_save(Annotations=xmlAnnot, filename=xml_path)
write_minmax_to_xml(xml_path) # to avoid trying to write to the xml from multiple workers
del xmlAnnot
os.system("ls -lh '{}'".format(tmp))

trainlogdir=os.path.join(tmp, 'output')
if not os.path.exists(trainlogdir):
os.makedirs(trainlogdir)

_ = os.system("printf '\ndone retriving data...\nstarting training...\n\n'")


cmd = "python3 ../segmentationschool/segmentation_school.py --option {} --training_data_dir {} --init_modelfile {} --gpu {} --train_steps {} --num_workers {} --girderApiUrl {} --girderToken {}".format('train', tmp.replace(' ', '\ '), args.init_modelfile, args.gpu, args.training_steps, args.num_workers, args.girderApiUrl, args.girderToken)
print(cmd)
sys.stdout.flush()
os.system(cmd)

os.listdir(trainlogdir)
os.chdir(trainlogdir)
os.system('pwd')
os.system('ls -lh')

filelist = glob('*.pth')
latest_model = max(filelist, key=os.path.getmtime)

_ = os.system("printf '\n{}\n'".format(latest_model))
os.rename(latest_model, args.output_model)

_ = os.system("printf '\nDone!\n\n'")



if __name__ == "__main__":
main(CLIArgumentParser().parse_args())
75 changes: 75 additions & 0 deletions multic/cli/MultiCompartmentTrain/MultiCompartmentTrain.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<executable>
<category>HistomicsTK</category>
<title>Multi Compartment Training</title>
<description>Trains Multi compartment segmentation model</description>
<version>0.1.0</version>
<documentation-url>https://github.com/SarderLab/Multi-Compartment-Segmentation</documentation-url>
<license>Apache 2.0</license>
<contributor>Sayat Mimar (UFL)</contributor>
<acknowledgements>This work is part of efforts in digital pathology by the Sarder Lab: UFL.</acknowledgements>
<parameters>
<label>IO</label>
<description>Input/output parameters</description>
<directory>
<name>training_data_dir</name>
<label>Training Data Directory</label>
<description>Base Directory for the model</description>
<channel>input</channel>
<index>0</index>
</directory>
<file>
<name>init_modelfile</name>
<label>Model File</label>
<description> Trained model file</description>
<channel>input</channel>
<index>1</index>
</file>
<string>
<name>gpu</name>
<label>GPU IDs</label>
<description>A comma separated list of the GPU IDs that will be made avalable for training</description>
<default>0,1</default>
<index>2</index>
</string>
<integer>
<name>training_steps</name>
<label>Training steps</label>
<description>The number of steps used for network training. The network will see [steps * batch size] image patches during training</description>
<default>5000</default>
<index>3</index>
</integer>
<integer>
<name>num_workers</name>
<label>Number of workers</label>
<description>Number of workers for Dataloader</description>
<default>0</default>
<index>4</index>
</integer>
<file fileExtensions=".pth">
<name>output_model</name>
<label>Output Model Name</label>
<description>Select the name of the output model file produced. By default this will be saved in your Private folder.</description>
<channel>output</channel>
<index>5</index>
</file>
</parameters>
<parameters advanced="true">
<label>Girder API URL and Key</label>
<description>A Girder API URL and token for Girder client</description>
<string>
<name>girderApiUrl</name>
<longflag>api-url</longflag>
<label>Girder API URL</label>
<description>A Girder API URL (e.g., https://girder.example.com:443/api/v1)</description>
<default></default>
</string>
<string>
<name>girderToken</name>
<longflag>token</longflag>
<label>Girder API Token</label>
<description>A Girder token</description>
<default></default>
</string>
</parameters>
</executable>
3 changes: 3 additions & 0 deletions multic/cli/slicer_cli_list.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
},
"FeatureExtraction": {
"type" : "python"
},
"MultiCompartmentTrain": {
"type" : "python"
}
}
Loading