@@ -67,14 +67,21 @@ def read_cubelist(cube_list : Path):
67
67
list
68
68
list of files
69
69
"""
70
+ files = []
71
+
70
72
with open (cube_list ) as c :
71
73
content = c .read ()
72
74
content = content .strip ()
73
75
files = content .split ("\n " )
74
- return files
76
+
77
+ for i in range (len (files )):
78
+ files [i ] = os .path .abspath (files [i ])
79
+ return files
80
+
75
81
76
82
77
- def segment (img_path : Path , nlines : int = MAX_LEN ):
83
+
84
+ def segment (img_path : Path , workdir : Path , nlines : int = MAX_LEN ):
78
85
"""
79
86
Segments an image into multiple parts.
80
87
@@ -97,19 +104,28 @@ def segment(img_path : Path, nlines : int = MAX_LEN):
97
104
98
105
segment_metadata = {}
99
106
try :
100
- ret = kisis .segment (img_path , nl = nlines , overlap = 0 , pref__ = "$ISISROOT/IsisPreferences" )
107
+ # change workdir so output goes there
108
+ oldpwd = os .getcwd ()
109
+
110
+ # create if it doesn't exist
111
+ workdir .mkdir (parents = True , exist_ok = True )
112
+ work_img = workdir / img_path .name
113
+ shutil .copyfile (img_path , work_img )
114
+ ret = kisis .segment (work_img , nl = nlines , overlap = 0 , pref__ = "$ISISROOT/IsisPreferences" )
115
+ os .remove (work_img )
116
+
101
117
log .debug (f"{ ret } " )
102
118
segment_metadata = pvl .loads (filter_progress (ret .stdout ))
103
119
104
120
# comes nested in a "results" group, trim it off
105
121
segment_metadata = [s [1 ] for s in segment_metadata ]
106
122
107
- glob_str = str (img_path . parent / img_path .stem ) + ".segment*"
123
+ glob_str = str (workdir / img_path .stem ) + ".segment*"
108
124
log .debug (f"globbing segments: glob({ glob_str } )" )
109
125
segments = sorted (glob (glob_str ))
110
-
126
+
111
127
log .debug (f"segments: { segments } " )
112
-
128
+
113
129
i = 0
114
130
for s , meta in zip (segments , segment_metadata ):
115
131
i += 1
@@ -133,19 +149,27 @@ def segment(img_path : Path, nlines : int = MAX_LEN):
133
149
134
150
135
151
def generate_cnet (params , images ):
136
-
137
- match_segment_n = images ["match" ]["Segment" ]
152
+ if isinstance (images ["match" ], list ):
153
+ images_match_n = images ["match" ][0 ]
154
+ else :
155
+ images_match_n = images ["match" ]
156
+ match_segment_n = images_match_n ["Segment" ]
138
157
from_segment_n = images ["from" ][0 ]["Segment" ]
139
158
159
+ print (images )
160
+ workdir = Path (params ["WORKDIR" ])
161
+
140
162
new_params = deepcopy (params )
141
163
new_params .pop ("NL" )
142
164
new_params .pop ("MINAREA" )
143
165
new_params .pop ("MINTHICKNESS" )
144
-
166
+ new_params .pop ("WORKDIR" )
167
+
168
+
145
169
# make sure none of these keys are still in the params
146
170
new_params .pop ("FROMLIST" , None )
147
171
new_params .pop ("FROM" , None )
148
- new_params ["MATCH" ] = images [ "match" ] ["Path" ]
172
+ new_params ["MATCH" ] = images_match_n ["Path" ]
149
173
150
174
og_onet = Path (params ["ONET" ])
151
175
og_tolist = Path (params ["TOLIST" ])
@@ -158,7 +182,7 @@ def generate_cnet(params, images):
158
182
159
183
match_stem = Path (new_params ["MATCH" ]).stem
160
184
161
- fromlist_path = Path (og_tolist . parent / f"from_images_segment{ from_segment_n } .lis" )
185
+ fromlist_path = Path (workdir / f"from_images_segment{ from_segment_n } .lis" )
162
186
from_stem = fromlist_path .stem
163
187
164
188
if "debuglog" in new_params :
@@ -168,49 +192,40 @@ def generate_cnet(params, images):
168
192
169
193
new_params ["NETWORKID" ] = og_networkid + f"_{ match_segment_n } _{ from_stem } "
170
194
new_params ["POINTID" ] = og_pointid + f"_{ match_segment_n } _{ from_stem } "
171
- new_params ["ONET" ] = f"{ og_onet .parent / og_onet . stem } _{ match_segment_n } _{ from_stem } .net"
172
- new_params ["TOLIST" ] = f"{ og_tolist .parent / og_tolist . stem } _{ match_segment_n } _{ from_stem } .lis"
173
-
195
+ new_params ["ONET" ] = f"{ og_onet .stem } _{ match_segment_n } _{ from_stem } .net"
196
+ new_params ["TOLIST" ] = f"{ og_tolist .stem } _{ match_segment_n } _{ from_stem } .lis"
197
+
174
198
log .debug (new_params )
175
199
200
+ overlapfromlist = workdir / f"{ og_tolist .stem } _{ match_segment_n } _{ from_stem } _overlap_fromlist.lis"
201
+ overlaptolist = workdir / f"{ og_tolist .stem } _{ match_segment_n } _{ from_stem } .overlaps"
202
+
176
203
# check for overlaps
177
204
is_overlapping = []
178
- for image in from_images :
179
- with tempfile .TemporaryDirectory () as tmpdir :
180
- tmpdir = Path (tmpdir )
181
- overlapfromlist = tmpdir / "fromlist.lis"
182
- overlaptolist = tmpdir / "tolist.lis"
183
-
184
- kisis .fromlist .make ([* from_images , new_params ["MATCH" ]], overlapfromlist )
185
-
186
- try :
187
- kisis .findimageoverlaps (fromlist = overlapfromlist , overlaplist = overlaptolist )
188
- except subprocess .CalledProcessError as err :
189
- print ('Had an ISIS error:' )
190
- print (' ' .join (err .cmd ))
191
- print (err .stdout )
192
- print (err .stderr )
193
- raise err
194
-
195
- ret = kisis .overlapstats (fromlist = overlapfromlist , overlaplist = overlaptolist , pref__ = "$ISISROOT/IsisPreferences" )
196
- stats = pvl .loads (filter_progress (ret .stdout ))
197
- log .debug (f"overlap stats: { ret .stdout } " )
198
-
199
- # first, throw it out if there is no overlap whatsoever
200
- is_pair_overlapping = not any ([k [1 ].get ("NoOverlap" , "" ) == new_params ["MATCH" ] for k in stats ])
201
-
202
- if is_pair_overlapping :
203
- is_thick_enough = stats ["Results" ]["ThicknessMinimum" ] > float (params .get ("MINTHICKNESS" , 0 ))
204
- is_area_large_enough = stats ["Results" ]["AreaMinimum" ] > float (params .get ("MINAREA" , 0 ))
205
- is_pair_overlapping = all ([is_thick_enough , is_area_large_enough ])
206
- is_overlapping .append (is_pair_overlapping )
207
- else : # not overlapping
208
- is_overlapping .append (False )
209
-
210
- # mask images
211
- from_images = list (compress (from_images , is_overlapping ))
212
- log .debug (f"From images overlapping Match: { from_images } " )
205
+ all_images = [* from_images , new_params ["MATCH" ]]
206
+ print ("ALL IMAGES: " , " " .join (all_images ))
207
+ kisis .fromlist .make (all_images , overlapfromlist )
213
208
209
+ try :
210
+ kisis .findimageoverlaps (fromlist = overlapfromlist , overlaplist = overlaptolist )
211
+ except subprocess .CalledProcessError as err :
212
+ print ('Find Image Overlaps Had an ISIS error:' )
213
+ print (' ' .join (err .cmd ))
214
+ print (err .stdout )
215
+ print (err .stderr )
216
+ return "No Overlaps From FindImageOverlaps"
217
+
218
+ ret = kisis .overlapstats (fromlist = overlapfromlist , overlaplist = overlaptolist , pref__ = "$ISISROOT/IsisPreferences" )
219
+ stats = pvl .loads (filter_progress (ret .stdout ))
220
+ log .debug (f"overlap stats: { ret .stdout } " )
221
+
222
+ # # first, throw it out if there is no overlap whatsoever
223
+ # has_overlap = not any([len(k[1].get("NoOverlap", "")) == new_params["MATCH"] for k in stats])
224
+
225
+ # # mask images
226
+ # from_images = list(compress(from_images, is_overlapping))
227
+ log .debug (f"From images overlapping Match: { from_images } " )
228
+ log .debug (f"Has overlaps list: { is_overlapping } " )
214
229
215
230
if from_images :
216
231
log .debug (f"FROMLIST: { from_images } " )
@@ -221,32 +236,35 @@ def generate_cnet(params, images):
221
236
else :
222
237
log .debug (f"{ fromlist_path } already exists" )
223
238
new_params ["FROMLIST" ] = str (fromlist_path )
239
+
240
+ log .debug (f"Running FindFeatures with Params: { new_params } " )
224
241
225
242
try :
226
243
ret = kisis .findfeatures (** new_params )
227
244
log .debug (f"returned: { ret } " )
228
245
except subprocess .CalledProcessError as err :
229
- log .debug ('Had an ISIS error:' )
246
+ log .debug ('Find Features Had an ISIS error:' )
230
247
log .debug (' ' .join (err .cmd ))
231
248
log .debug (err .stdout )
232
249
log .debug (err .stderr )
233
- return "ERROR"
234
250
235
- segmented_net = cnet .from_isis (new_params ["ONET" ])
251
+ if os .path .exists (new_params ["ONET" ]):
252
+ segmented_net = cnet .from_isis (new_params ["ONET" ])
236
253
237
- # starting sample in inclusive, so subtract 1
238
- segmented_net .loc [segmented_net .serialnumber == images [ "match" ][ " SN" ], "line" ] += images [ "match" ] ["StartingLine" ]- 1
254
+ # starting sample in inclusive, so subtract 1
255
+ segmented_net .loc [segmented_net .serialnumber == images_match_n [ " SN" ], "line" ] += images_match_n ["StartingLine" ]- 1
239
256
240
- # offset the images
241
- for k , image in enumerate (images ["from" ]):
242
- image_sn = image ["SN" ]
257
+ # offset the images
258
+ for k , image in enumerate (images ["from" ]):
259
+ image_sn = image ["SN" ]
243
260
244
- # starting sample is inclusive, so subtract 1
245
- segmented_net .loc [segmented_net .serialnumber == image_sn , "line" ] += starting_lines [k ]- 1
246
- cnet .to_isis (segmented_net , new_params ["ONET" ], targetname = "moon" )
247
-
248
- from_originals = [image ["Original" ] for image in images ["from" ]]
249
- return {"onet" : new_params ["ONET" ], "original_images" : from_originals }
261
+ # starting sample is inclusive, so subtract 1
262
+ segmented_net .loc [segmented_net .serialnumber == image_sn , "line" ] += starting_lines [k ]- 1
263
+ cnet .to_isis (segmented_net , new_params ["ONET" ], targetname = "moon" )
264
+
265
+ from_originals = [image ["Original" ] for image in images ["from" ]]
266
+ return {"onet" : new_params ["ONET" ], "original_images" : from_originals }
267
+ return "No Overlap"
250
268
else :
251
269
return "No Overlap"
252
270
@@ -274,7 +292,7 @@ def merge(d1, d2, k):
274
292
return v1 + v2
275
293
276
294
277
- def findFeaturesSegment (ui ):
295
+ def findFeaturesSegment (ui , workdir ):
278
296
"""
279
297
findFeaturesSegment Calls FindFeatures on segmented images
280
298
@@ -313,41 +331,69 @@ def findFeaturesSegment(ui):
313
331
else :
314
332
nthreads = int (multiprocessing .cpu_count ())
315
333
316
- pool = ThreadPool (ceil (nthreads / len (img_list )))
317
- output = pool .map_async (segment , img_list )
334
+ pool = ThreadPool (nthreads )
335
+ starmap_args = []
336
+ for image in img_list :
337
+ starmap_args .append ([image , workdir , ui .GetInteger ("NL" )])
338
+ output = pool .starmap_async (segment , starmap_args )
318
339
pool .close ()
319
340
pool .join ()
320
341
output = output .get ()
342
+ match_segments = segment (os .path .abspath (ui .GetCubeName ("match" )), workdir , ui .GetInteger ("NL" ))
321
343
322
- match_segments = segment (ui .GetCubeName ("match" ), ui .GetInteger ("NL" ))
323
- from_segments = reduce (lambda d1 ,d2 : {k : merge (d1 , d2 , k ) for k in set (d1 )| set (d2 )}, output )
344
+ if len (img_list ) > 1 :
345
+ from_segments = reduce (lambda d1 ,d2 : {k : merge (d1 , d2 , k ) for k in set (d1 )| set (d2 )}, output )
346
+ else :
347
+ # img_list = 1
348
+ from_segments = output [0 ]
349
+ for seg , value in from_segments .items ():
350
+ og_value = value
351
+ from_segments [seg ] = [og_value ]
352
+
324
353
segment_paths = [s ["Path" ] for sublist in list (from_segments .values ()) for s in sublist ]
325
354
segment_paths = segment_paths + [s ["Path" ] for s in list (match_segments .values ())]
326
355
327
356
# re-generate footprints
328
- pool = ThreadPool (ceil ( nthreads / len ( segment_paths )) )
357
+ pool = ThreadPool (nthreads )
329
358
output = pool .map_async (footprintinit , segment_paths )
330
359
pool .close ()
331
360
pool .join ()
332
361
output = output .get ()
333
362
log .debug (f"{ output } " )
334
363
335
- image_sets = list (itertools .product (match_segments .values (), from_segments .values ()))
336
-
364
+ # Remove redundant overlapping pairs
365
+ x = match_segments .values ()
366
+ y = from_segments .values ()
367
+ # x,y = (x,y) if len(x) > len(y) else (y,x)
368
+ image_cartesian = list (itertools .product (x , y ))
369
+ image_sets = image_cartesian
370
+ # for i in image_cartesian:
371
+ # if i[0][0]["Segment"] >= i[1]["Segment"]:
372
+ # image_sets.append(i)
373
+
337
374
# restructure things to be easier to manage
338
375
job_dicts = []
339
376
for im in image_sets :
340
377
match = im [0 ]
341
378
from_images = im [1 ]
379
+ if not isinstance (from_images , list ):
380
+ # from_images must be list type
381
+ from_images_list = []
382
+ from_images_list .append (from_images )
383
+ from_images = from_images_list
342
384
job_dicts .append ({
343
385
"match" : match ,
344
386
"from" : from_images
345
- })
346
-
387
+ })
388
+
347
389
# get params as a dictionary
348
390
params = ui .GetParams ()
391
+ if is_workdir_temp :
392
+ params ["WORKDIR" ] = workdir
349
393
350
- pool = ThreadPool (ceil (nthreads / len (job_dicts )))
394
+ # findfeatures is already threaded, limit python threads by the maxthreads
395
+ # parameter, no maththreads_findfeatures * maxthreads_python <= maxthreads
396
+ pool = ThreadPool (int (nthreads / len (job_dicts )))
351
397
starmap_args = list (zip ([params ]* len (job_dicts ), job_dicts ))
352
398
output = pool .starmap_async (generate_cnet , starmap_args )
353
399
pool .close ()
@@ -369,11 +415,11 @@ def findFeaturesSegment(ui):
369
415
tolists = [set (o ["original_images" ]) for o in output if isinstance (o , dict )]
370
416
371
417
final_images = set .union (* tolists )
372
- final_images .add (ui .GetCubeName ("match" ))
418
+ final_images .add (os . path . abspath ( ui .GetCubeName ("match" ) ))
373
419
374
420
log .debug (f"merged images: { final_images } " )
375
421
kisis .fromlist .make (final_images , Path (ui .GetFileName ("tolist" )))
376
-
422
+
377
423
if len (onets ) > 1 :
378
424
try :
379
425
kisis .cnetmerge (clist = onet_list , onet = ui .GetFileName ("onet" ), networkid = ui .GetAsString ("networkid" ), description = f"{ ui .GetString ('description' )} " )
@@ -386,9 +432,23 @@ def findFeaturesSegment(ui):
386
432
# Dont merge
387
433
shutil .copy (onets [0 ], ui .GetFileName ("onet" ))
388
434
389
- log .info (f"COMPLETE, wrote { ui .GetFileName ("onet" )} " )
390
-
391
- if __name__ == "__main__" :
435
+ if __name__ == "__main__" :
392
436
ui = astroset .init_application (sys .argv )
393
- findFeaturesSegment (ui )
394
-
437
+ is_workdir_temp = not ui .WasEntered ("WorkDir" )
438
+ workdir = Path (tempfile .TemporaryDirectory ().name )
439
+ if ui .WasEntered ("Workdir" ):
440
+ workdir = Path (ui .GetFileName ("Workdir" ))
441
+
442
+ try :
443
+ findFeaturesSegment (ui , workdir )
444
+ except Exception as e :
445
+ if is_workdir_temp :
446
+ shutil .rmtree (workdir )
447
+ raise e
448
+
449
+ # log.info(f"COMPLETE, wrote: {ui.GetFileName("onet")}")
450
+ if is_workdir_temp :
451
+ shutil .rmtree (workdir )
452
+ log .info ("Complete" )
453
+ else :
454
+ log .info ("Intermediate files written to %s" , workdir )
0 commit comments