nodes: 0, module; 1, function_definition; 2, function_name:organize_dir; 3, parameters; 4, block; 5, identifier:orig_dir; 6, expression_statement; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, for_statement; 12, expression_statement; 13, expression_statement; 14, for_statement; 15, for_statement; 16, string; 17, assignment; 18, assignment; 19, assignment; 20, assignment; 21, identifier:dup; 22, identifier:dups; 23, block; 24, assignment; 25, assignment; 26, identifier:key; 27, identifier:clustered; 28, block; 29, pattern_list; 30, call; 31, block; 32, string_content:scans through the given directory and organizes DICOMs that look similar into subdirectories
  
      output directory is the ``orig_dir`` with ``-sorted`` appended to the end; 33, identifier:tags; 34, list; 35, identifier:orig_dir; 36, call; 37, identifier:files; 38, call; 39, identifier:dups; 40, call; 41, expression_statement; 42, for_statement; 43, identifier:clustered; 44, call; 45, identifier:output_dir; 46, binary_operator:'%s-sorted' % orig_dir; 47, if_statement; 48, for_statement; 49, expression_statement; 50, expression_statement; 51, expression_statement; 52, try_statement; 53, identifier:r; 54, identifier:ds; 55, identifier:fs; 56, attribute; 57, argument_list; 58, for_statement; 59, tuple; 60, comment:# Subj ID; 61, tuple; 62, comment:# Date; 63, tuple; 64, comment:# Time; 65, tuple; 66, comment:# Descr; 67, attribute; 68, argument_list; 69, identifier:scan_dir; 70, argument_list; 71, identifier:find_dups; 72, argument_list; 73, call; 74, identifier:each_dup; 75, subscript; 76, block; 77, identifier:cluster_files; 78, argument_list; 79, string; 80, identifier:orig_dir; 81, comparison_operator:(0x8,0x31) in clustered[key]['info']; 82, block; 83, identifier:t; 84, identifier:tags; 85, block; 86, assignment; 87, assignment; 88, call; 89, block; 90, except_clause; 91, else_clause; 92, identifier:os; 93, identifier:walk; 94, identifier:output_dir; 95, keyword_argument; 96, identifier:d; 97, identifier:ds; 98, block; 99, integer:0x10; 100, integer:0x20; 101, integer:0x8; 102, integer:0x21; 103, integer:0x8; 104, integer:0x31; 105, integer:0x8; 106, integer:0x103e; 107, identifier:orig_dir; 108, identifier:rstrip; 109, string; 110, identifier:orig_dir; 111, keyword_argument; 112, keyword_argument; 113, identifier:files; 114, attribute; 115, argument_list; 116, identifier:dup; 117, slice; 118, expression_statement; 119, try_statement; 120, delete_statement; 121, identifier:files; 122, string_content:%s-sorted; 123, tuple; 124, subscript; 125, expression_statement; 126, if_statement; 127, identifier:run_name; 128, binary_operator:'-'.join([scrub_fname(str(clustered[key]['info'][x])) for x in tags])+'-%d_images' %len(clustered[key]['files']); 129, identifier:run_dir; 130, call; 131, attribute; 132, argument_list; 133, if_statement; 134, identifier:IOError; 135, block; 136, block; 137, identifier:topdown; 138, False; 139, expression_statement; 140, if_statement; 141, string_content:/; 142, identifier:tags; 143, identifier:tags; 144, identifier:md5_hash; 145, True; 146, identifier:nl; 147, identifier:notify; 148, binary_operator:'Found duplicates of %s...' % dup[0]; 149, integer:1; 150, call; 151, block; 152, except_clause; 153, parenthesized_expression; 154, integer:0x8; 155, integer:0x31; 156, subscript; 157, string; 158, assignment; 159, comparison_operator:t not in clustered[key]['info']; 160, block; 161, call; 162, binary_operator:'-%d_images' %len(clustered[key]['files']); 163, attribute; 164, argument_list; 165, identifier:nl; 166, identifier:notify; 167, binary_operator:'Moving files into %s' % run_dir; 168, not_operator; 169, block; 170, expression_statement; 171, for_statement; 172, assignment; 173, comparison_operator:len(os.listdir(dname))==0; 174, block; 175, string; 176, subscript; 177, attribute; 178, argument_list; 179, expression_statement; 180, identifier:IOError; 181, block; 182, subscript; 183, identifier:clustered; 184, identifier:key; 185, string_content:info; 186, subscript; 187, call; 188, identifier:t; 189, subscript; 190, expression_statement; 191, attribute; 192, argument_list; 193, string; 194, call; 195, attribute; 196, identifier:join; 197, identifier:output_dir; 198, identifier:run_name; 199, string; 200, identifier:run_dir; 201, call; 202, expression_statement; 203, call; 204, identifier:f; 205, subscript; 206, block; 207, identifier:dname; 208, call; 209, call; 210, integer:0; 211, expression_statement; 212, string_content:Found duplicates of %s...; 213, identifier:dup; 214, integer:0; 215, identifier:nl; 216, identifier:notify; 217, binary_operator:'\tdeleting %s' % each_dup; 218, call; 219, expression_statement; 220, identifier:files; 221, identifier:each_dup; 222, subscript; 223, tuple; 224, identifier:str; 225, argument_list; 226, subscript; 227, string; 228, assignment; 229, string; 230, identifier:join; 231, list_comprehension; 232, string_content:-%d_images; 233, identifier:len; 234, argument_list; 235, identifier:os; 236, identifier:path; 237, string_content:Moving files into %s; 238, attribute; 239, argument_list; 240, call; 241, attribute; 242, argument_list; 243, subscript; 244, string; 245, try_statement; 246, attribute; 247, argument_list; 248, identifier:len; 249, argument_list; 250, call; 251, string; 252, identifier:each_dup; 253, attribute; 254, argument_list; 255, call; 256, subscript; 257, string; 258, integer:0x8; 259, integer:0x31; 260, call; 261, identifier:clustered; 262, identifier:key; 263, string_content:info; 264, subscript; 265, string; 266, string_content:-; 267, call; 268, for_in_clause; 269, subscript; 270, attribute; 271, identifier:exists; 272, identifier:run_dir; 273, attribute; 274, argument_list; 275, identifier:nl; 276, identifier:notify; 277, binary_operator:'Error: failed to create directory %s' % run_dir; 278, identifier:clustered; 279, identifier:key; 280, string_content:files; 281, block; 282, except_clause; 283, attribute; 284, identifier:join; 285, identifier:r; 286, identifier:d; 287, call; 288, attribute; 289, argument_list; 290, string_content; 291, identifier:os; 292, identifier:remove; 293, identifier:each_dup; 294, attribute; 295, argument_list; 296, identifier:clustered; 297, identifier:key; 298, string_content:info; 299, identifier:int; 300, argument_list; 301, subscript; 302, identifier:t; 303, string_content:_; 304, identifier:scrub_fname; 305, argument_list; 306, identifier:x; 307, identifier:tags; 308, subscript; 309, string; 310, identifier:os; 311, identifier:path; 312, identifier:os; 313, identifier:makedirs; 314, identifier:run_dir; 315, string; 316, identifier:run_dir; 317, expression_statement; 318, if_statement; 319, expression_statement; 320, tuple; 321, block; 322, identifier:os; 323, identifier:path; 324, attribute; 325, argument_list; 326, identifier:os; 327, identifier:remove; 328, identifier:dname; 329, escape_sequence:\t; 330, identifier:nl; 331, identifier:notify; 332, string; 333, call; 334, subscript; 335, string; 336, call; 337, identifier:clustered; 338, identifier:key; 339, string_content:files; 340, string_content:Error: failed to create directory %s; 341, assignment; 342, comparison_operator:dset_fname[0]=='.'; 343, block; 344, call; 345, identifier:IOError; 346, identifier:OSError; 347, pass_statement; 348, identifier:os; 349, identifier:listdir; 350, identifier:dname; 351, string_content; 352, identifier:float; 353, argument_list; 354, identifier:clustered; 355, identifier:key; 356, string_content:info; 357, identifier:str; 358, argument_list; 359, identifier:dset_fname; 360, subscript; 361, subscript; 362, string; 363, expression_statement; 364, attribute; 365, argument_list; 366, escape_sequence:\t; 367, subscript; 368, subscript; 369, call; 370, integer:1; 371, identifier:dset_fname; 372, integer:0; 373, string_content:.; 374, assignment; 375, identifier:os; 376, identifier:rename; 377, identifier:f; 378, call; 379, subscript; 380, tuple; 381, subscript; 382, identifier:x; 383, attribute; 384, argument_list; 385, identifier:dset_fname; 386, binary_operator:'_' + dset_fname[1:]; 387, attribute; 388, argument_list; 389, subscript; 390, string; 391, integer:0x8; 392, integer:0x31; 393, subscript; 394, string; 395, attribute; 396, identifier:split; 397, identifier:f; 398, string; 399, subscript; 400, attribute; 401, identifier:join; 402, identifier:run_dir; 403, identifier:dset_fname; 404, identifier:clustered; 405, identifier:key; 406, string_content:info; 407, identifier:clustered; 408, identifier:key; 409, string_content:info; 410, identifier:os; 411, identifier:path; 412, string_content:_; 413, identifier:dset_fname; 414, slice; 415, identifier:os; 416, identifier:path; 417, integer:1
code: def organize_dir(orig_dir):
      '''scans through the given directory and organizes DICOMs that look similar into subdirectories
  
      output directory is the ``orig_dir`` with ``-sorted`` appended to the end'''
  
      tags = [
          (0x10,0x20),    # Subj ID
          (0x8,0x21),     # Date
          (0x8,0x31),     # Time
          (0x8,0x103e)    # Descr
      ]
      orig_dir = orig_dir.rstrip('/')
      files = scan_dir(orig_dir,tags=tags,md5_hash=True)
      dups = find_dups(files)
      for dup in dups:
          nl.notify('Found duplicates of %s...' % dup[0])
          for each_dup in dup[1:]:
              nl.notify('\tdeleting %s' % each_dup)
              try:
                  os.remove(each_dup)
              except IOError:
                  nl.notify('\t[failed]')
              del(files[each_dup])
  
      clustered = cluster_files(files)
      output_dir = '%s-sorted' % orig_dir
      for key in clustered:
          if (0x8,0x31) in clustered[key]['info']:
              clustered[key]['info'][(0x8,0x31)] = str(int(float(clustered[key]['info'][(0x8,0x31)])))
          for t in tags:
              if t not in clustered[key]['info']:
                  clustered[key]['info'][t] = '_'
          run_name = '-'.join([scrub_fname(str(clustered[key]['info'][x])) for x in tags])+'-%d_images' %len(clustered[key]['files'])
          run_dir = os.path.join(output_dir,run_name)
          nl.notify('Moving files into %s' % run_dir)
          try:
              if not os.path.exists(run_dir):
                  os.makedirs(run_dir)
          except IOError:
              nl.notify('Error: failed to create directory %s' % run_dir)
          else:
              for f in clustered[key]['files']:
                  try:
                      dset_fname = os.path.split(f)[1]
                      if dset_fname[0]=='.':
                          dset_fname = '_' + dset_fname[1:]
                      os.rename(f,os.path.join(run_dir,dset_fname))
                  except (IOError, OSError):
                      pass
      for r,ds,fs in os.walk(output_dir,topdown=False):
          for d in ds:
              dname = os.path.join(r,d)
              if len(os.listdir(dname))==0:
                  os.remove(dname)