From 8f9a125c162dbdb8486b804d810f2fa7a47fe501 Mon Sep 17 00:00:00 2001
From: azardilis <azardilis@gmail.com>
Date: Mon, 9 Mar 2020 15:48:06 +0000
Subject: [PATCH] Adds a dir for common packages that includes modules used
 across scripts

---
 common/LICENCE                                |   0
 common/README.md                              |   0
 common/common/L1L2_cells_ids.py               |  10 +
 common/common/__init__.py                     |   0
 .../__pycache__/L1L2_cells_ids.cpython-37.pyc | Bin 0 -> 11681 bytes
 .../__pycache__/__init__.cpython-37.pyc       | Bin 0 -> 143 bytes
 common/common/__pycache__/lin.cpython-37.pyc  | Bin 0 -> 16812 bytes
 common/common/__pycache__/seg.cpython-37.pyc  | Bin 0 -> 21873 bytes
 common/common/edict.py                        |  58 ++
 common/common/lin.py                          | 498 +++++++++++++++
 common/common/lin.py~                         | 546 ++++++++++++++++
 common/common/seg.py                          | 594 +++++++++++++++++
 common/common/seg.py~                         | 601 ++++++++++++++++++
 common/setup.py                               |  18 +
 common/setup.py~                              |   0
 15 files changed, 2325 insertions(+)
 create mode 100644 common/LICENCE
 create mode 100644 common/README.md
 create mode 100644 common/common/L1L2_cells_ids.py
 create mode 100644 common/common/__init__.py
 create mode 100644 common/common/__pycache__/L1L2_cells_ids.cpython-37.pyc
 create mode 100644 common/common/__pycache__/__init__.cpython-37.pyc
 create mode 100644 common/common/__pycache__/lin.cpython-37.pyc
 create mode 100644 common/common/__pycache__/seg.cpython-37.pyc
 create mode 100644 common/common/edict.py
 create mode 100644 common/common/lin.py
 create mode 100644 common/common/lin.py~
 create mode 100644 common/common/seg.py
 create mode 100644 common/common/seg.py~
 create mode 100644 common/setup.py
 create mode 100644 common/setup.py~

diff --git a/common/LICENCE b/common/LICENCE
new file mode 100644
index 0000000..e69de29
diff --git a/common/README.md b/common/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/common/common/L1L2_cells_ids.py b/common/common/L1L2_cells_ids.py
new file mode 100644
index 0000000..0d33309
--- /dev/null
+++ b/common/common/L1L2_cells_ids.py
@@ -0,0 +1,10 @@
+L1_10h =  [514, 515, 516, 517, 519, 520, 521, 522, 523, 527, 528, 529, 530, 532, 533, 534, 535, 536, 537, 538, 539, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 554, 555, 558, 122, 126, 129, 149, 158, 173, 183, 196, 197, 205, 211, 215, 232, 240, 247, 249, 265, 269, 274, 278, 280, 281, 285, 292, 293, 295, 307, 310, 322, 323, 332, 337, 342, 345, 352, 355, 362, 367, 372, 384, 385, 387, 391, 396, 401, 402, 405, 408, 409, 411, 417, 424, 430, 435, 439, 440, 447, 448, 451, 455, 456, 460, 461, 464, 465, 466, 470, 473, 474, 476, 479, 484, 485, 487, 489, 491, 494, 499, 501, 502, 504, 505, 506, 509, 510]
+L2_10h =  [518, 525, 120, 130, 135, 142, 148, 154, 162, 164, 170, 181, 182, 186, 193, 202, 204, 209, 210, 221, 223, 228, 229, 233, 238, 239, 242, 254, 279, 282, 286, 298, 302, 303, 305, 309, 316, 317, 318, 333, 339, 340, 346, 349, 350, 356, 358, 366, 368, 369, 371, 374, 379, 383, 386, 390, 398, 399, 404, 406, 407, 410, 412, 413, 415, 419, 426, 427, 429, 431, 432, 433, 434, 438, 445, 449, 453, 454, 457, 458, 459, 463, 467, 471, 472, 475, 477, 481, 482, 488, 492, 493, 497, 498, 500, 508, 511]
+L1_40h =  [112, 123, 126, 131, 134, 135, 140, 146, 149, 151, 166, 167, 185, 187, 195, 196, 205, 221, 222, 224, 227, 229, 232, 238, 239, 243, 246, 253, 255, 256, 260, 261, 272, 274, 275, 276, 282, 286, 288, 290, 303, 308, 317, 318, 319, 321, 322, 323, 326, 328, 333, 334, 343, 344, 350, 351, 354, 357, 358, 360, 361, 362, 363, 364, 366, 371, 372, 376, 378, 382, 386, 387, 388, 389, 390, 391, 392, 398, 400, 401, 402, 405, 406, 408, 409, 410, 412, 415, 417, 418, 420, 421, 422, 425, 428]
+L2_40h =  [257, 258, 259, 179, 266, 267, 269, 270, 237, 277, 278, 153, 218, 281, 154, 156, 285, 240, 291, 292, 293, 294, 369, 168, 297, 170, 299, 300, 301, 302, 306, 307, 310, 311, 313, 249, 193, 327, 200, 330, 331, 335, 336, 210, 340, 341, 342, 215, 345, 346, 207, 349, 223, 352, 356, 103, 242, 171, 359, 365, 110, 368, 113, 370, 235, 245, 169, 121, 217, 252, 125]
+L1_96h =  [28, 96, 101, 115, 116, 119, 122, 134, 149, 168, 172, 175, 185, 186, 192, 195, 209, 213, 215, 224, 229, 233, 234, 243, 260, 265, 266, 267, 274, 278, 279, 280, 281, 282, 283, 294, 299, 302, 303, 307, 310, 323, 333, 334, 342, 346, 347, 348, 349, 351, 352, 353, 360, 361, 364, 365, 369, 372, 373, 375, 377, 378, 379, 380, 381, 382, 385, 391, 392, 394, 397, 398, 399, 401, 402, 403, 406, 407, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430]
+L2_96h =  [384, 311, 386, 388, 389, 390, 263, 264, 393, 395, 396, 270, 400, 146, 404, 277, 408, 153, 284, 248, 197, 240, 164, 167, 296, 405, 300, 173, 142, 200, 306, 253, 309, 137, 314, 318, 321, 322, 324, 325, 198, 328, 329, 330, 331, 332, 205, 206, 336, 337, 212, 341, 343, 344, 345, 225, 354, 357, 358, 359, 232, 235, 237, 366, 367, 112, 371, 244, 245, 118, 376, 121, 374, 127, 125, 383]
+L1_120h =  [515, 699, 518, 769, 522, 526, 921, 531, 533, 534, 857, 536, 543, 544, 545, 546, 554, 555, 560, 561, 862, 566, 567, 569, 576, 577, 586, 781, 598, 599, 601, 783, 605, 607, 609, 99, 786, 112, 625, 627, 628, 633, 634, 637, 639, 640, 129, 875, 132, 135, 649, 139, 140, 657, 658, 659, 662, 663, 664, 155, 704, 672, 624, 676, 679, 683, 684, 685, 688, 177, 179, 692, 693, 695, 891, 697, 187, 188, 189, 192, 709, 710, 711, 201, 887, 915, 740, 212, 213, 726, 728, 890, 222, 739, 228, 742, 743, 233, 234, 747, 237, 751, 752, 753, 755, 756, 757, 246, 760, 766, 257, 261, 776, 265, 778, 779, 268, 269, 271, 785, 274, 787, 788, 279, 745, 644, 286, 901, 816, 845, 295, 808, 297, 811, 777, 818, 814, 815, 304, 817, 306, 819, 308, 311, 820, 827, 830, 319, 320, 834, 837, 838, 327, 328, 908, 330, 823, 333, 847, 848, 850, 853, 825, 856, 345, 911, 860, 350, 863, 352, 865, 866, 867, 868, 357, 358, 913, 872, 363, 876, 367, 880, 369, 882, 883, 372, 885, 375, 888, 378, 831, 892, 893, 894, 895, 896, 897, 386, 899, 900, 773, 902, 903, 904, 905, 906, 907, 396, 909, 398, 399, 912, 401, 914, 403, 916, 917, 918, 919, 920, 409, 922, 411, 412, 413, 926, 416, 798, 923, 924, 429, 430, 925, 432, 884, 448, 449, 454, 458, 461, 462, 463, 466, 473, 477, 910, 482, 749, 484, 489, 499, 502, 869, 506, 509, 510, 511]
+L2_120h =  [512, 516, 520, 523, 525, 528, 529, 542, 347, 548, 551, 553, 559, 562, 564, 570, 575, 578, 68, 582, 585, 588, 589, 79, 855, 597, 804, 600, 186, 606, 608, 97, 610, 611, 613, 615, 616, 619, 620, 621, 110, 623, 626, 629, 638, 127, 642, 643, 645, 648, 137, 656, 154, 156, 157, 158, 671, 673, 678, 167, 680, 682, 689, 691, 457, 698, 701, 702, 705, 706, 197, 289, 712, 718, 208, 723, 724, 214, 727, 729, 730, 731, 733, 735, 225, 738, 229, 744, 748, 238, 242, 244, 758, 761, 762, 252, 765, 768, 770, 771, 772, 774, 264, 780, 782, 272, 789, 278, 791, 280, 281, 794, 284, 861, 801, 802, 803, 292, 805, 806, 807, 296, 813, 302, 305, 821, 310, 824, 313, 314, 315, 829, 832, 323, 324, 822, 839, 840, 841, 842, 843, 332, 846, 852, 854, 343, 344, 346, 859, 826, 864, 870, 873, 874, 877, 878, 879, 881, 886, 376, 889, 382, 391, 392, 397, 835, 750, 406, 407, 408, 836, 414, 420, 421, 422, 427, 428, 754, 946, 670, 441, 444, 451, 844, 468, 471, 472, 476, 480, 481, 485, 486, 764, 490, 500, 501, 505, 507, 508, 784]
+L1_132h =  [71, 73, 89, 90, 92, 108, 109, 120, 121, 123, 127, 142, 158, 162, 164, 176, 177, 181, 182, 186, 197, 206, 208, 209, 215, 221, 222, 224, 234, 238, 248, 250, 252, 255, 258, 265, 267, 276, 277, 289, 291, 293, 300, 307, 308, 309, 315, 319, 322, 323, 324, 325, 328, 338, 352, 353, 356, 377, 378, 382, 383, 385, 387, 389, 394, 395, 396, 397, 400, 402, 403, 406, 407, 414, 420, 426, 427, 429, 436, 444, 446, 447, 454, 459, 466, 467, 473, 475, 480, 482, 483, 484, 492, 493, 494, 497, 498, 503, 507, 508, 513, 516, 517, 518, 520, 521, 527, 529, 530, 532, 536, 539, 541, 542, 543, 544, 545, 549, 553, 555, 557, 558, 559, 560, 562, 563, 577, 580, 582, 585, 587, 590, 591, 592, 601, 606, 607, 615, 616, 618, 619, 626, 628, 630, 635, 639, 640, 641, 643, 644, 646, 651, 661, 666, 677, 678, 682, 683, 688, 689, 697, 703, 707, 710, 711, 715, 716, 721, 723, 727, 730, 736, 739, 742, 744, 747, 748, 754, 758, 759, 761, 770, 771, 775, 788, 792, 793, 799, 800, 813, 821, 825, 827, 828, 829, 832, 835, 841, 842, 848, 849, 852, 853, 858, 859, 861, 868, 869, 879, 882, 886, 887, 890, 896, 899, 901, 905, 910, 911, 913, 921, 922, 923, 927, 936, 939, 943, 946, 947, 950, 957, 958, 960, 963, 968, 969, 970, 977, 978, 980, 985, 986, 996, 1000, 1004, 1008, 1013, 1014, 1016, 1019, 1024, 1029, 1031, 1033, 1039, 1040, 1045, 1047, 1048, 1049, 1052, 1053, 1067, 1071, 1079, 1086, 1087, 1088, 1092, 1093, 1094, 1097, 1100, 1102, 1104, 1105, 1106, 1117, 1118, 1123, 1126, 1127, 1128, 1129, 1132, 1134, 1139, 1142, 1143, 1144, 1145, 1151, 1155, 1163, 1164, 1166, 1169, 1177, 1179, 1183, 1184, 1191, 1192, 1194, 1195, 1196, 1200, 1201, 1203, 1205, 1208, 1210, 1211, 1215, 1219, 1221, 1223, 1224, 1228, 1230, 1231, 1234, 1235, 1237, 1239, 1242, 1247, 1254, 1255, 1258, 1259, 1260, 1263, 1266, 1268, 1269, 1270, 1272, 1273, 1274, 1275, 1276, 1279, 1281, 1282, 1283, 1284, 1285, 1286, 1288, 1292, 1294, 1300, 1301, 1302, 1303, 1304, 1306, 1308, 1309, 1310, 1311, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1340, 1344, 1345, 1346, 1348, 1350, 1351, 1354, 1355, 1356, 1357, 1360, 1363, 1369, 1370, 1371, 1374, 1375, 1376, 1377, 1379, 1382, 1383, 1384, 1386, 1387, 1389, 1392, 1393, 1394, 1395, 1396, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1417, 1418, 1452]
+L2_132h =  [512, 1025, 392, 1028, 598, 519, 1034, 1035, 524, 525, 526, 1197, 1041, 988, 534, 535, 1050, 602, 1054, 1055, 1058, 1059, 1060, 380, 550, 1063, 1065, 1066, 556, 1214, 1070, 1073, 1074, 53, 566, 1081, 1082, 575, 576, 1089, 1091, 1366, 1121, 72, 586, 1207, 1378, 79, 81, 594, 1107, 596, 1110, 612, 1114, 1115, 1116, 361, 1120, 97, 98, 1124, 614, 1297, 617, 1130, 1298, 110, 111, 624, 113, 1140, 629, 105, 122, 1147, 1148, 1149, 126, 1154, 363, 1156, 1157, 1158, 705, 1160, 1388, 935, 489, 141, 654, 1168, 146, 660, 1173, 663, 152, 1220, 1178, 667, 156, 1182, 671, 1185, 674, 1187, 1188, 1189, 1193, 1341, 685, 1198, 1199, 1165, 1399, 1202, 1204, 1206, 183, 184, 185, 1213, 702, 373, 192, 193, 1218, 195, 708, 228, 1222, 502, 200, 1225, 1226, 203, 1229, 720, 211, 1236, 213, 1240, 1241, 1244, 1245, 1246, 1248, 1232, 1250, 1252, 1253, 232, 233, 1261, 1262, 1264, 1265, 242, 243, 638, 1271, 760, 249, 762, 251, 1277, 1278, 725, 1280, 959, 773, 774, 1287, 1289, 778, 779, 1293, 785, 274, 1299, 1103, 790, 791, 282, 1307, 796, 797, 798, 437, 801, 290, 390, 487, 1320, 297, 298, 1135, 304, 305, 820, 734, 312, 826, 317, 830, 1343, 198, 321, 1347, 326, 1249, 1352, 329, 330, 844, 846, 653, 1361, 335, 339, 1364, 1365, 854, 569, 1368, 740, 1372, 349, 741, 367, 866, 867, 256, 1381, 871, 360, 1385, 362, 875, 364, 877, 1390, 1391, 1342, 372, 1397, 1398, 745, 888, 933, 374, 1257, 892, 381, 384, 878, 902, 833, 904, 548, 909, 237, 912, 920, 245, 916, 348, 408, 409, 855, 412, 413, 926, 419, 345, 241, 623, 327, 428, 430, 925, 1096, 755, 949, 951, 440, 500, 955, 445, 816, 1321, 964, 965, 753, 457, 971, 1380, 462, 976, 931, 1358, 984, 676, 987, 476, 478, 479, 1170, 763, 485, 998, 999, 1001, 490, 1003, 1367, 1005, 1009, 1011, 1217, 766, 1227, 681, 668, 1176, 1020, 1021, 945]
diff --git a/common/common/__init__.py b/common/common/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/common/common/__pycache__/L1L2_cells_ids.cpython-37.pyc b/common/common/__pycache__/L1L2_cells_ids.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b625b0d491786ec38d5b49865e9914b726b6cf61
GIT binary patch
literal 11681
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
E0l|9q`~Uy|

literal 0
HcmV?d00001

diff --git a/common/common/__pycache__/__init__.cpython-37.pyc b/common/common/__pycache__/__init__.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..19fec233ee28f7a3f8a9731001549ede26956b8a
GIT binary patch
literal 143
zcmZ?b<>g`k0&k_XI1v39M8E(ekl_Ht#VkM~g&~+hlhJP_LlH<ALHx4N&&bbB)lV!+
zuPn+e)-Os;OU%fOPc2Ezi8nGZGSE-X&&|!xgHiGEnR%Hd@$q^EmA5!-a`RJ4b5iX<
JCVmED1^_J%As_$%

literal 0
HcmV?d00001

diff --git a/common/common/__pycache__/lin.cpython-37.pyc b/common/common/__pycache__/lin.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..eac3d3c486ca32d2f01e700fa68d5f251a9f26f8
GIT binary patch
literal 16812
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

literal 0
HcmV?d00001

diff --git a/common/common/__pycache__/seg.cpython-37.pyc b/common/common/__pycache__/seg.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..51c47c8b7428722ffce143168c611ed13dbca604
GIT binary patch
literal 21873
zcmcJ1YmggPc3!^#G%%Rqa5&;i5;c5CtDz){4@s-t)srKQ#1%DSNQ$BmX+aQ;0Wrb=
z;O!o21`EV%k9I{RR^&}w@s?}t%*6XB+euZ*b|ve$QYpKf^5*5N^ZL<oxspod2UB@$
zD$XCpmCE;>+udk@pmw!MW~y)BzJ2>X&g-6Y?zuQUIax69_h-kJzw~dPHH`njhxl(F
zGSA`iS4_k349{#DB~$KJ$->=g+N(~<G4;F5YPOV<yxnwH^QFAxon~QmqBMbg#>;v+
z&-L<N!JF`k-lR9>?eM0(o!*SM%bWG?@^*WByuIE&Z@+i9caL{(eP5~glHncj?t9Ph
z?yF61+NCKx&v^&&d{CZu;Q5eu7|)00c^c10y!-Kde{CA|cX|(apLx$H&3F%b^SJNw
zj`F{5dk-yJ-oxG_@0q39xNO<<j(Lxw<Sy^HcLKF{d#`z?yvI<o$9vp+0wsIB&w5Yd
zzR&xd_j%m+dtdOL!u@XVY3~`_@A01Xp2PiK?|JVu?gzXD?*-iN^Ir58ai8;E@?OUM
zpm)amBJPL0SG=>hANF4LmT*7fnHP-tbGL|rrFk=SFE*B!7aPqQ^IomiskS>C$U7_T
zMyq5!|5C|${^fH|l<eo1E+RR1g2_oHr;uDYQOZ1j@zt{@O3uRBOQ%Zi!s`ns$|uXG
zN|_fgUOcl@vKP;sE!k%m-z-_Lo-5_fy?nZS?&V7*>)e@A=G^NGFP|yd=U=>3axT1x
zmYJTE6m4I)_$rdu&mp;VF0|ix{X&&vj{j_Ap2OuogQO-@1Bx*{3v;wR+jDStfPGK|
zpqn98pd?Gmz&%Imz}@wx0FCL;xm2s3syb+jf4p0`7I68yk@U=-Q8s!OQnP0x1#RLx
zb7|fV&GpdS2+i)i6FPpaxvX;dK)FovNPg8&6S#eR>d|ZM)!L&KRo_qz|4~(2u3T%B
zYeA)1K6(7)@kgue)zx+@zWKHKvCc;5mdlM+BPf>-qX|EY#4xk??@n^O$KtnD4wiqs
zXK=~DpFk!swlMS+t7ooQd%<423_RI*vh~v*K0A1J;^%FWhqZKzP0eRQtJT4@uB%{V
zTJx47SC_0CCuDv)DWWKJyoMh<h+H&a$2?$m^D<z*`PiHr8ZT!h<2{5-&)hNs8S$nm
zcRRW}n`YgXu>t5AMGS?uAE@!e!mC<mbX<j?{hF#*S`B~o5sprPW_EYT$OiAKkVNvw
z_q=3qdyxUCj6MgasevhEm8Jtr4}=&`K(ii<4k7EmTj`W8A4jbOo37cNkRj-IN%tH^
zf=d!%f=gl$SWClW2i}L7ic*!0QHYp=sL_$+g7)*Q{WymbL82HzLS77wBLM@+x@T+|
z+tIX5br(wJ$M*s1RX{_z{A8+=m~!<SNFX)C7V@O^R%NwTE{BD3dA04WHJLA#%h%T`
zP5nkqqN>`-gxxAaMG-TK>qu&f<TyoQRHUv$xO_gjrkimy1ska?Z>lIv{%qu)!{z@K
zB#A^h=vkf(2?B}YWkjY>q8OhbQ4Vp<!54Y1JE&QxO>p&j&)76eMdYyxNq&-R5#CRE
zhq)r*iyd5*P%`b^>m9&-r+1$>hx?4k>?5JGP-`}qs-z13@t$Dj9z5JGrg{#D)Q*YN
z3GHgb3++zZ5A7T6W|*n1ca#r)A}^~0OzvYc$K)Urf#d+3M8H$Hd=i3|MU+My*LZ0}
zpb7&`Awvd&JTg~|n3FBtA5j{yO=wj|C5mADG^)genwS14OsZ_3e-sG3q_306tk3nV
z7mT;}_H77kNR@5lot(;g=)Gq@Wn9m`p`m4pP}kzzT3UoWciyRO_%iu0SFg2dORN68
zqX8rkIfBMRtKJ#`P3TrU??r<1MN|-SGt7cnG>aA_wiUrBu9HYWf`v57dHCN!5*V9C
z-&((M6Jln|+BPtUYj0V7yYFxw?_^bzGuUVJGri1PnSQpP>%0AYztGF}a(j&a#QO%6
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
ZDB=M8w3~M)-2JYL&9WWXEVFRW{2y7x03`qb

literal 0
HcmV?d00001

diff --git a/common/common/edict.py b/common/common/edict.py
new file mode 100644
index 0000000..8df5941
--- /dev/null
+++ b/common/common/edict.py
@@ -0,0 +1,58 @@
+def unionWith(m1, m2, f):
+    combined = dict()
+
+    combKeys = set.union(set(m1.keys()), set(m2.keys()))
+
+    for k in combKeys:
+        if k in m1 and k in m2:
+            combined[k] = f(m1[k], m2[k])
+        elif k in m1 and k not in m2:
+            combined[k] = m1[k]
+        elif k not in m1 and k in m2:
+            combined[k] = m2[k]
+
+    return combined
+
+def unionsWith(ms, f, df):
+    combined = dict()
+
+    combKeys = set.union(*[set(m.keys()) for m in ms])
+
+    for k in combKeys:
+        combined[k] = f([m.get(k, df) for m in ms])
+
+    return combined
+
+def union(m1, m2):
+    combined = dict()
+
+    if set(m1.keys()).intersection(m2.keys()):
+        raise ValueError("non distinct keys")
+
+    combKeys = set.union(set(m1.keys()), set(m2.keys()))
+
+    for k in combKeys:
+        if k in m1:
+            combined[k] = m1[k]
+        elif k in m2:
+            combined[k] = m2[k]
+
+    return combined
+    
+
+def map(m, f):
+    return dict([(k, f(v)) for k, v in m.items()])
+
+def mapWithKey(m, f):
+    return dict([(k, f(k, v)) for k, v in m.items()])
+
+def relabel(m, kms):
+    m1 = dict()
+    for k, v in m:
+        for km in kms.get(k, []):
+            m1[km] = v
+
+    return m1
+
+def filter(m, f):
+    return dict([(k, v) for k, v in m.items() if f(v)])
diff --git a/common/common/lin.py b/common/common/lin.py
new file mode 100644
index 0000000..b607cca
--- /dev/null
+++ b/common/common/lin.py
@@ -0,0 +1,498 @@
+from collections import defaultdict
+from os.path import join
+import os
+import _pickle as cPickle
+import common.seg as seg
+from itertools import repeat
+import common.L1L2_cells_ids as layers
+
+def getSurvivingBetween(tss, linss, t1, t2):
+    linsL = filterLinssBetween(linss, (t1, t2))
+
+    cids = list()
+    
+    for c in tss[t1]:
+        if tSearchN(linsL, c.cid, len(linsL), 0):
+            cids.append(c.cid)
+
+    return cids
+
+def filterSurvivingUntil(tss, linss, t2):
+    for t, ts in tss.items():
+        cids = getSurvivingBetween(tss, linss, t, t2)
+        filterT(ts, cids)
+
+    return
+
+def fst(x): return x[0]
+
+def snd(x): return x[1]
+
+def filterT(ts, cids):
+    scids = set(cids)
+    ts.cells = dict([(c.cid, c) for c in ts if c.cid in scids])
+
+    neighsL1 = dict()
+    for cid, ds in ts.neighs.items():
+        if cid in scids:
+            neighsL1[cid] = dict([(n, d) for n, d in ds.items()
+                                  if n in scids])
+
+    ts.neighs = neighsL1
+        
+def filterL1(tss):
+    L1_cids = {10: layers.L1_10h,
+               40: layers.L1_40h,
+               96: layers.L1_96h,
+               120: layers.L1_120h,
+               132: layers.L1_132h}
+    
+    for t, ts in tss.items():
+        filterT(ts, L1_cids[t])
+
+    return
+
+
+def filterL1L2(tss):
+    L1_cids = {10: layers.L1_10h,
+               40: layers.L1_40h,
+               96: layers.L1_96h,
+               120: layers.L1_120h,
+               132: layers.L1_132h}
+
+    L2_cids = {10: layers.L2_10h,
+               40: layers.L2_40h,
+               96: layers.L2_96h,
+               120: layers.L2_120h,
+               132: layers.L2_132h}
+
+    for t, ts in tss.items():
+        filterT(ts, L1_cids[t] + L2_cids[t])
+
+    return
+
+
+def getTs(linFn):
+    fn, _ = os.path.splitext(linFn)
+    (_, t1, _, t2) = fn.split("_")
+
+    return (int(t1[:-1]), int(t2[:-1]))
+
+
+def readLin(linFn):
+    with open(linFn, 'rb') as linF:
+        lin = cPickle.load(linF, encoding='latin1')
+
+    return lin, getTs(linFn)
+
+
+def readLins(linDataLoc):
+    lins = [readLin(join(linDataLoc, f)) for f in os.listdir(linDataLoc)
+            if os.path.isfile(join(linDataLoc, f))]
+
+    return lins
+
+
+def getLinMap(lin):
+    cMap = defaultdict(list)
+    for c1, c2 in lin[0]:
+        cMap[c2].append(c1)
+        
+    return cMap
+
+
+def mkLinsSeries(lins):
+    return [(ts, getLinMap(lin))
+            for lin, ts in sorted(lins, key=lambda lt: lt[1][0])]
+
+
+def after(t, lt):
+    ts, _ = lt
+    (t1, t2) = ts
+    
+    return t >= t1
+
+
+def before(t, lt):
+    ts, _ = lt
+    (t1, t2) = ts
+    
+    return t <= t2
+
+
+def between(linSeries, t1, t2):
+    afters = [i for i, lt in enumerate(linSeries) if after(t1, lt)]
+    befores = [i for i, lt in enumerate(linSeries) if before(t2, lt)]
+
+    s = afters[-1]
+    e = befores[0]
+
+    return [(ts, lin) for ts, lin in linSeries[s:(e+1)]]
+
+
+def mergeLins(lin1, lin2):
+    mLin = dict()
+    
+    for m, ds in lin1.items():
+        mLin[m] = sum([lin2[d] for d in ds], [])
+
+    return mLin
+
+
+def mergeLinss1(lins, acc):
+    if not lins: return acc
+
+    return mergeLinss1(lins[1:], mergeLins(acc, lins[0]))
+
+
+def mergeLinss(lins):
+    if len(lins) > 2: return mergeLinss1(lins[2:], mergeLins(lins[0], lins[1]))
+    elif len(lins) == 2: return mergeLins(lins[0], lins[1])
+    elif len(lins) == 1: return lins[0]
+    else: return []
+
+    
+######################################################
+def concat(xss):
+    return sum(xss, [])
+
+
+def tSearchN(mss, r, n, c):
+    if c == n: return [r]
+    else:
+        return concat([tSearchN(mss, d, n, c+1) for d in mss[c].get(r, [])])
+
+    
+def tSearch1(mss, r):
+    try:
+        return mss[0][r]
+    except KeyError:
+        return []
+
+    
+def tSearch2(mss, r):
+    try:
+        return sum([mss[1][d] for d in mss[0][r]], [])
+    except KeyError:
+        print(r)
+        return []
+
+    
+def cvol(c):
+    if c: return c.vol
+    else: return 0.0
+
+    
+def sumVol(cs, f=cvol):
+    return sum([cvol(c) for c in cs])
+
+
+def mergeCellVolsRefN(tss, mss):
+    volss = []
+
+    for i, ts in enumerate(tss):
+        volss.append(dict())
+        for c in tss[0]:
+            volss[i][c.cid] = sum(cvol(ts.cells.get(ci, None))
+                                  for ci in tSearchN(mss, c.cid, i, 0))
+
+    return volss
+
+
+def const1(c):
+    if c: return 1
+    else: return 0
+
+
+def mergeCellNsRefN(tss, linss):
+    attrss = []
+
+    for i, ts in enumerate(tss):
+        attrss.append(dict())
+        for c in tss[0]:
+            attrss[i][c.cid] = sum(const1(ts.cells.get(ci, None))
+                                   for ci in tSearchN(linss, c.cid, i, 0))
+
+    return  attrss
+
+
+def mergeCellVolsRef3(tss, mss):
+    (ts1, ts2, ts3) = tss
+    
+    vols1 = dict()
+    vols2 = dict()
+    vols3 = dict()
+    
+    for c in ts1:
+        vols1[c.cid] = c.vol
+        vols2[c.cid] = sumVol([ts2.cells[i] for i in tSearch1(mss, c.cid)])
+        vols3[c.cid] = sumVol([ts3.cells[i] for i in tSearch2(mss, c.cid)])
+
+    return vols1, vols2, vols3
+
+
+def mergeCellVolsRef2(tss, mss):
+    (ts1, ts2) = tss
+    
+    vols1 = dict()
+    vols2 = dict()
+    
+    for c in ts1:
+        print(c.cid)
+        vols1[c.cid] = c.vol
+        vols2[c.cid] = sumVol([ts2.cells[i] for i in tSearch1(mss, c.cid)])
+
+    return vols1, vols2
+
+
+def divOr0(n1, n2):
+    if n2 == 0: return 0
+    else: return n1 / n2
+
+    
+def growthRates3(volss, m12):
+    vols1, vols2, vols3 = volss
+    gr2 = dict()
+    for i, vol in vols1.items():
+        gr12 = divOr0((vols2[i] - vols1[i]), vols1[i])
+        gr23 = divOr0((vols3[i] - vols2[i]), vols2[i])
+        gr2[i] = 0.5 * (gr12 + gr23)
+        
+    gr22 = [zip(m12.get(i, []), repeat(gr, len(m12.get(i, []))))
+            for i, gr in gr2.items()]
+    
+    return dict(sum(gr22, []))
+
+
+def growthRatesL2(volss):
+    vols1, vols2 = volss
+    gr1 = dict()
+    for i, vol in vols1.items():
+        gr1[i] = (vols2[i] - vols1[i]) / vols1[i]
+
+    return gr1
+
+
+def growthRatesR2(volss, m12):
+    vols1, vols2 = volss
+    gr2 = dict()
+    for i, vol in vols1.items():
+        gr2[i] = (vols2[i] - vols1[i]) / vols1[i]
+
+    gr22 = [zip(m12.get(i, []), repeat(gr, len(m12.get(i, []))))
+            for i, gr in gr2.items()]
+    
+    return dict(sum(gr22, []))
+
+
+def mkSeries1(dataDir):
+    d = "organism"                                                                                 
+    dExprs = "geneExpression/new_patterns"
+    linDataLoc = "tracking"
+    
+
+    timepoints = [10, 40, 96, 120, 132]
+    lins = mkLinsSeries(readLins(join(dataDir, linDataLoc)))
+     
+    tss = dict()
+    linss = dict()
+
+    for t1, t2 in zip(timepoints, timepoints[1:]):
+        tss[t1] = readDataT1(join(dataDir, d), join(dataDir, dExprs), t1)
+        tss[t2] = readDataT1(join(dataDir, d), join(dataDir, dExprs), t2)
+
+        linss[(t1, t2)] = mergeLinss(list(map(lambda x: x[1],
+                                              between(lins, t1, t2))))
+
+    return tss, linss
+
+def mkSeriesIm0(dataDir):
+    d = "yr01"
+    linDataLoc = "yr01/tracking"
+     
+    timepoints = [0, 10, 40, 96, 120, 132]
+    lins = mkLinsSeries(readLins(join(dataDir, linDataLoc)))
+     
+    tss = dict()
+    linss = dict()
+
+    for t in timepoints:
+        tss[t] = readDataT1Im(join(dataDir, d), t)
+         
+    for t1, t2 in zip(timepoints, timepoints[1:]):
+        linss[(t1, t2)] = mergeLinss(map(lambda x: x[1],
+                                          between(lins, t1, t2)))
+
+    return tss, linss
+
+
+def mkGrowthRates():
+    tss, linss = mkSeries()
+    grs = dict()
+
+    grs[10] = growthRatesL2(mergeCellVolsRef2((tss[10], tss[40]),
+                                              [linss[(10, 40)]]))
+    grs[40] = growthRates3(mergeCellVolsRef3((tss[10], tss[40], tss[96]),
+                                             [linss[(10, 40)], linss[(40, 96)]]),
+                           linss[(10, 40)])
+    grs[96] = growthRates3(mergeCellVolsRef3((tss[40], tss[96], tss[120]),
+                                             [linss[(40, 96)], linss[(96, 120)]]),
+                           linss[(40, 96)])
+    grs[120] = growthRates3(mergeCellVolsRef3((tss[96], tss[120], tss[132]),
+                                              [linss[(96, 120)], linss[(120, 132)]]),
+                            linss[(96, 120)])
+    grs[132] = growthRatesR2(mergeCellVolsRef2((tss[120], tss[132]),
+                                               [linss[(120, 132)]]),
+                             linss[(120, 132)])
+
+    return grs
+
+def readGeomImT(dataDir, fid, t):
+    ressFn = "yr" + fid + "/resolutions.txt"
+    segFn = ("yr" +
+             fid +
+             "/segmentations/YR_" +
+             fid + "_" + str(t) +
+             "h_segmented.tif")
+    
+    ress = readRess(join(dataDir, ressFn))
+    img = readImage(join(dataDir, segFn))
+    res = ress[t]
+    
+    ts = Tissue.fromImage(data=img, res=res)
+    for c in ts:
+        c.swapZX()
+        
+    return ts
+
+def mkSeriesGeomIm(dataDir, fid):
+    ressFn = "yr" + fid + "/resolutions.txt"
+    linDataLoc = "yr" + fid + "/trackingFiles/"
+    ress = readRess(join(dataDir, ressFn))
+    tpoints = sorted(ress.keys())
+    
+    lins = mkLinsSeries(readLins(join(dataDir, linDataLoc)))
+    tss = dict()
+    linss = dict()
+    
+    for t in tpoints:
+        tss[t] = readGeomImT(dataDir, fid, t)
+        
+    for t1, t2 in zip(tpoints, tpoints[1:]):
+        linss[(t1, t2)] = mergeLinss(map(lambda x:
+                                         x[1], between(lins, t1, t2)))
+        
+    return tss, linss
+
+
+###################################
+def invertMap(ln):
+    iLin = [list(zip(ds, repeat(m, len(ds)))) for m, ds in ln.items()]
+
+    return dict(sum(iLin, []))
+
+def updateCells(ts, ts1, iLn):
+    for c1 in ts1:
+        try:
+            c = ts.cells[iLn[c1.cid]]
+        except KeyError:
+            print(c1.cid)
+            c = Cell(0, Vec3(0, 0, 0), 0, dict([(g, False) for g in geneNms]))
+        c1.exprs = dict([(g, c.exprs[g]) for g, v in c1.exprs.items()])
+
+    return
+
+def prev(t):
+    if t == 40: return 10
+    elif t == 96: return 40
+    elif t == 120: return 96
+    elif t == 132: return 120
+    else: return None
+
+def succ(t):
+    if t==10: return 40
+    elif t==40: return 96
+    elif t==96: return 120
+    elif t==120: return 132
+    else: return None
+
+def updateTs(tss, linss, tpoints):
+    #evolve patterns based on lineage
+    tssLin = {}
+    for t in tpoints[1:]:
+        tssLin[(prev(t), t)] = tss[t].updateExprsTs(tss[prev(t)],
+                                                    invertMap(linss[(prev(t), t)]))
+
+    return tssLin
+
+def updateTsBF(tss, fs):
+    return dict((t, tss[t].updateExprsBF(fs[t])) for t in tss.keys())
+
+def toNewmanFn(fn):
+    (fn, ext) = os.path.splitext(fn)
+    return fn + "000" + ".tif"
+
+
+def tFn(t, ref=""):
+    return "ts_t" + str(t) + ref + ".txt"
+
+
+def snd(x):
+    return x[1]
+
+def betweenTs(t, bounds):
+    ts, te = bounds
+    return t >= ts and t <= te
+
+def filterLinssBetween(linss, bounds):
+    t1, t2 = bounds
+    linssL = sorted([(ts, ln) for ts, ln in linss.items() 
+                     if betweenTs(ts[0], (t1, t2)) and
+                        betweenTs(ts[1], (t1, t2))], key=lambda p: p[0][0])
+    
+    return list(map(snd, linssL))
+
+def filterTssBetween(tss, tbounds):
+    t1, t2 = tbounds
+        
+    tssL = sorted([(t, ts) for t, ts in tss.items() if betweenTs(t, (t1, t2))], key=fst)
+    
+    return list(map(snd, tssL))
+
+def readDataT1(d, dExprs, t):
+    from os.path import join
+    
+    geomF = "_segmented_tvformat_0_volume_position.txt"
+    neighF = "_segmented_tvformat_0_neighbors_py.txt"
+    exprF = "h.txt"
+
+    fnGeom = join(d, "t" + str(t) + geomF)
+    fnNeigh = join(d, "t" + str(t) + neighF)
+    fnExpr = join(dExprs, "t_" + str(t) + exprF)
+    
+    gexprs = seg.readExprs(fnExpr)
+    ts = seg.STissue.fromTV(fnGeom, fnNeigh, gexprs, seg.geneNms)
+
+    return ts
+
+def readDataT1Im(d, dExprs, t):
+    from os.path import join
+
+    exprF = "h.txt"
+    fnRes = join(d, "resolutions.txt")
+    fnSeg = join(d, "segmentations/t"+str(t)+"_segmented.tif")
+    fnExpr = join(dExprs, "t_" + str(t) + exprF)
+    
+    
+    data, _ = seg.readImage(fnSeg)
+    ress = seg.readRess(fnRes)
+    res = ress[t]
+
+    gexprs = seg.readExprs(fnExpr)
+    ts = seg.STissue.fromImage(data, res, gexprs, seg.geneNms)
+
+    for c in ts:
+        c.swapZX()
+
+    return ts
+
diff --git a/common/common/lin.py~ b/common/common/lin.py~
new file mode 100644
index 0000000..3cd910b
--- /dev/null
+++ b/common/common/lin.py~
@@ -0,0 +1,546 @@
+from __future__ import print_function
+from __future__ import division
+from collections import defaultdict
+from os.path import join
+import os
+import _pickle as cPickle
+from seg import *
+import analyseExprs as a
+from itertools import repeat
+import boolFs as b
+import L1L2_cells_ids as layers
+
+linDataLoc = "../data/tracking/"
+
+def getSurvivingBetween(tss, linss, t1, t2):
+    linsL = filterLinssBetween(linss, (t1, t2))
+
+    cids = list()
+    
+    
+    for c in tss[t1]:
+        if tSearchN(linsL, c.cid, len(linsL), 0):
+            cids.append(c.cid)
+
+    return cids
+
+def filterSurvivingUntil(tss, linss, t2):
+    for t, ts in tss.items():
+        cids = getSurvivingBetween(tss, linss, t, t2)
+        filterT(ts, cids)
+
+    return
+
+def fst(x): return x[0]
+
+def snd(x): return x[1]
+
+def filterT(ts, cids):
+    scids = set(cids)
+    ts.cells = dict([(c.cid, c) for c in ts if c.cid in scids])
+
+    neighsL1 = dict()
+    for cid, ds in ts.neighs.items():
+        if cid in scids:
+            neighsL1[cid] = dict([(n, d) for n, d in ds.items() if n in scids])
+
+    ts.neighs = neighsL1
+        
+def filterL1(tss):
+    L1_cids = {10: layers.L1_10h,
+               40: layers.L1_40h,
+               96: layers.L1_96h,
+               120: layers.L1_120h,
+               132: layers.L1_132h}
+    
+    for t, ts in tss.items():
+        filterT(ts, L1_cids[t])
+
+    return
+
+
+def filterL1L2(tss):
+    L1_cids = {10: layers.L1_10h,
+               40: layers.L1_40h,
+               96: layers.L1_96h,
+               120: layers.L1_120h,
+               132: layers.L1_132h}
+
+    L2_cids = {10: layers.L2_10h,
+               40: layers.L2_40h,
+               96: layers.L2_96h,
+               120: layers.L2_120h,
+               132: layers.L2_132h}
+
+    for t, ts in tss.items():
+        #scids1 = set(L1_cids[t])
+        #scids2 = set(L2_cids[t])
+
+        filterT(ts, L1_cids[t] + L2_cids[t])
+
+#        ts.cells = dict([(c.cid, c) for c in ts
+#                         if c.cid in scids1 or c.cid in scids2])
+
+    return
+
+
+def getTs(linFn):
+    fn, _ = os.path.splitext(linFn)
+    (_, t1, _, t2) = fn.split("_")
+
+    return (int(t1[:-1]), int(t2[:-1]))
+
+
+def readLin(linFn):
+    with open(linFn, 'rb') as linF:
+        lin = cPickle.load(linF, encoding='latin1')
+
+    return lin, getTs(linFn)
+
+
+def readLins(linDataLoc):
+    lins = [readLin(join(linDataLoc, f)) for f in os.listdir(linDataLoc)
+            if os.path.isfile(join(linDataLoc, f))]
+
+    return lins
+
+
+def getLinMap(lin):
+    cMap = defaultdict(list)
+    for c1, c2 in lin[0]:
+        cMap[c2].append(c1)
+        
+    return cMap
+
+
+def mkLinsSeries(lins):
+    return [(ts, getLinMap(lin))
+            for lin, ts in sorted(lins, key=lambda lt: lt[1][0])]
+
+
+def after(t, lt):
+    ts, _ = lt
+    (t1, t2) = ts
+    
+    return t >= t1
+
+
+def before(t, lt):
+    ts, _ = lt
+    (t1, t2) = ts
+    
+    return t <= t2
+
+
+def between(linSeries, t1, t2):
+    afters = [i for i, lt in enumerate(linSeries) if after(t1, lt)]
+    befores = [i for i, lt in enumerate(linSeries) if before(t2, lt)]
+
+    s = afters[-1]
+    e = befores[0]
+
+    return [(ts, lin) for ts, lin in linSeries[s:(e+1)]]
+
+
+def mergeLins(lin1, lin2):
+    mLin = dict()
+    
+    for m, ds in lin1.items():
+        mLin[m] = sum([lin2[d] for d in ds], [])
+
+    return mLin
+
+
+def mergeLinss1(lins, acc):
+    if not lins: return acc
+
+    return mergeLinss1(lins[1:], mergeLins(acc, lins[0]))
+
+
+def mergeLinss(lins):
+    if len(lins) > 2: return mergeLinss1(lins[2:], mergeLins(lins[0], lins[1]))
+    elif len(lins) == 2: return mergeLins(lins[0], lins[1])
+    elif len(lins) == 1: return lins[0]
+    else: return []
+
+    
+######################################################
+def concat(xss):
+    return sum(xss, [])
+
+
+def tSearchN(mss, r, n, c):
+    if c == n: return [r]
+    else:
+        return concat([tSearchN(mss, d, n, c+1) for d in mss[c].get(r, [])])
+
+    
+def tSearch1(mss, r):
+    try:
+        return mss[0][r]
+    except KeyError:
+        return []
+
+    
+def tSearch2(mss, r):
+    try:
+        return sum([mss[1][d] for d in mss[0][r]], [])
+    except KeyError:
+        print(r)
+        return []
+
+    
+def cvol(c):
+    if c: return c.vol
+    else: return 0.0
+
+    
+def sumVol(cs, f=cvol):
+    return sum([cvol(c) for c in cs])
+
+
+def mergeCellVolsRefN(tss, mss):
+    volss = []
+
+    for i, ts in enumerate(tss):
+        volss.append(dict())
+        for c in tss[0]:
+            volss[i][c.cid] = sum(cvol(ts.cells.get(ci, None)) for ci in tSearchN(mss, c.cid, i, 0))
+
+    return volss
+
+
+def const1(c):
+    if c: return 1
+    else: return 0
+
+
+def mergeCellNsRefN(tss, linss):
+    attrss = []
+
+    for i, ts in enumerate(tss):
+        attrss.append(dict())
+        for c in tss[0]:
+            attrss[i][c.cid] = sum(const1(ts.cells.get(ci, None)) for ci in tSearchN(linss, c.cid, i, 0))
+
+    return  attrss
+
+
+def mergeCellVolsRef3(tss, mss):
+    (ts1, ts2, ts3) = tss
+    
+    vols1 = dict()
+    vols2 = dict()
+    vols3 = dict()
+    
+    for c in ts1:
+        vols1[c.cid] = c.vol
+        vols2[c.cid] = sumVol([ts2.cells[i] for i in tSearch1(mss, c.cid)])
+        vols3[c.cid] = sumVol([ts3.cells[i] for i in tSearch2(mss, c.cid)])
+
+    return vols1, vols2, vols3
+
+
+def mergeCellVolsRef2(tss, mss):
+    (ts1, ts2) = tss
+    
+    vols1 = dict()
+    vols2 = dict()
+    
+    for c in ts1:
+        print(c.cid)
+        vols1[c.cid] = c.vol
+        vols2[c.cid] = sumVol([ts2.cells[i] for i in tSearch1(mss, c.cid)])
+
+    return vols1, vols2
+
+
+def divOr0(n1, n2):
+    if n2 == 0: return 0
+    else: return n1 / n2
+
+    
+def growthRates3(volss, m12):
+    vols1, vols2, vols3 = volss
+    gr2 = dict()
+    for i, vol in vols1.items():
+        gr12 = divOr0((vols2[i] - vols1[i]), vols1[i])
+        gr23 = divOr0((vols3[i] - vols2[i]), vols2[i])
+        gr2[i] = 0.5 * (gr12 + gr23)
+        
+    gr22 = [zip(m12.get(i, []), repeat(gr, len(m12.get(i, []))))
+            for i, gr in gr2.items()]
+    
+    return dict(sum(gr22, []))
+
+
+def growthRatesL2(volss):
+    vols1, vols2 = volss
+    gr1 = dict()
+    for i, vol in vols1.items():
+        gr1[i] = (vols2[i] - vols1[i]) / vols1[i]
+
+    return gr1
+
+
+def growthRatesR2(volss, m12):
+    vols1, vols2 = volss
+    gr2 = dict()
+    for i, vol in vols1.items():
+        gr2[i] = (vols2[i] - vols1[i]) / vols1[i]
+
+    gr22 = [zip(m12.get(i, []), repeat(gr, len(m12.get(i, []))))
+            for i, gr in gr2.items()]
+    
+    return dict(sum(gr22, []))
+
+
+def mkSeries():
+    d = "../data/organism"                                                                                 
+    dExprs = "../data/geneExpression/new_patterns"
+
+    timepoints = [10, 40, 96, 120, 132]
+    lins = mkLinsSeries(readLins(linDataLoc))
+     
+    tss = dict()
+    linss = dict()
+
+    for t1, t2 in zip(timepoints, timepoints[1:]):
+        tss[t1] = a.readDataT1(d, dExprs, t1)
+        tss[t2] = a.readDataT1(d, dExprs, t2)
+
+        linss[(t1, t2)] = mergeLinss(list(map(lambda x: x[1], between(lins, t1, t2))))
+
+    return tss, linss
+
+def mkSeriesIm0():
+    d = "../data/yr01"
+    linDataLoc = "../data/yr01/tracking"
+     
+    timepoints = [0, 10, 40, 96, 120, 132]
+    lins = mkLinsSeries(readLins(linDataLoc))
+     
+    tss = dict()
+    linss = dict()
+
+    for t in timepoints:
+        tss[t] = a.readDataT1Im(d, t)
+         
+    for t1, t2 in zip(timepoints, timepoints[1:]):
+        linss[(t1, t2)] = mergeLinss(map(lambda x: x[1],
+                                          between(lins, t1, t2)))
+
+    return tss, linss
+
+
+def mkGrowthRates():
+    tss, linss = mkSeries()
+    grs = dict()
+
+    grs[10] = growthRatesL2(mergeCellVolsRef2((tss[10], tss[40]),
+                                              [linss[(10, 40)]]))
+    grs[40] = growthRates3(mergeCellVolsRef3((tss[10], tss[40], tss[96]),
+                                             [linss[(10, 40)], linss[(40, 96)]]),
+                           linss[(10, 40)])
+    grs[96] = growthRates3(mergeCellVolsRef3((tss[40], tss[96], tss[120]),
+                                             [linss[(40, 96)], linss[(96, 120)]]),
+                           linss[(40, 96)])
+    grs[120] = growthRates3(mergeCellVolsRef3((tss[96], tss[120], tss[132]),
+                                              [linss[(96, 120)], linss[(120, 132)]]),
+                            linss[(96, 120)])
+    grs[132] = growthRatesR2(mergeCellVolsRef2((tss[120], tss[132]),
+                                               [linss[(120, 132)]]),
+                             linss[(120, 132)])
+
+    return grs
+
+def readGeomImT(fid, t):
+    ressFn = "../data/yr" + fid + "/resolutions.txt"
+    segFn = ("../data/yr" +
+             fid +
+             "/segmentations/YR_" +
+             fid + "_" + str(t) +
+             "h_segmented.tif")
+    
+    ress = readRess(ressFn)
+    img = readImage(segFn)
+    res = ress[t]
+    
+    ts = Tissue.fromImage(data=img, res=res)
+    for c in ts:
+        c.swapZX()
+        
+    return ts
+
+def mkSeriesGeomIm(fid):
+    ressFn = "../data/yr" + fid + "/resolutions.txt"
+    linDataLoc = "../data/yr" + fid + "/trackingFiles/"
+    ress = readRess(ressFn)
+    tpoints = sorted(ress.keys())
+    
+    lins = mkLinsSeries(readLins(linDataLoc))
+    tss = dict()
+    linss = dict()
+    
+    for t in tpoints:
+        tss[t] = readGeomImT(fid, t)
+        
+    for t1, t2 in zip(tpoints, tpoints[1:]):
+        linss[(t1, t2)] = mergeLinss(map(lambda x:
+                                         x[1], between(lins, t1, t2)))
+        
+    return tss, linss
+
+
+###################################
+def invertMap(ln):
+    iLin = [list(zip(ds, repeat(m, len(ds)))) for m, ds in ln.items()]
+
+    return dict(sum(iLin, []))
+
+def updateCells(ts, ts1, iLn):
+    for c1 in ts1:
+        try:
+            c = ts.cells[iLn[c1.cid]]
+        except KeyError:
+            print(c1.cid)
+            c = Cell(0, Vec3(0, 0, 0), 0, dict([(g, False) for g in geneNms]))
+        c1.exprs = dict([(g, c.exprs[g]) for g, v in c1.exprs.items()])
+
+    return
+
+def prev(t):
+    if t == 40: return 10
+    elif t == 96: return 40
+    elif t == 120: return 96
+    elif t == 132: return 120
+    else: return None
+
+def succ(t):
+    if t==10: return 40
+    elif t==40: return 96
+    elif t==96: return 120
+    elif t==120: return 132
+    else: return None
+
+def updateTs(tss, linss, tpoints):
+    #evolve patterns based on lineage
+    tssLin = {}
+    for t in tpoints[1:]:
+        tssLin[(prev(t), t)] = tss[t].updateExprsTs(tss[prev(t)],
+                                                    invertMap(linss[(prev(t), t)]))
+
+    return tssLin
+
+def updateTsBF(tss, fs):
+    return dict((t, tss[t].updateExprsBF(fs[t])) for t in tss.keys())
+
+def toNewmanFn(fn):
+    (fn, ext) = os.path.splitext(fn)
+    return fn + "000" + ".tif"
+
+def plotNewman1(tss, i, geneNm, outDir="."):
+    from subprocess import call
+    import os
+
+    confFile = "newman.conf"
+    visCmd = "/home2/Organism/tools/plot/bin/newman"
+    mergeCmd = "convert"
+
+    b.cellsToDat("ts1.dat", list(tss))
+
+    call([visCmd,
+          "-shape", "sphereVolume",
+          "-d", "3",
+          "ts1.dat",
+          "-column", str(i+1),
+          "-output", "tiff",
+          geneNm,
+          "-camera", confFile,
+          "-min", str(0),
+          "-max", str(1)])
+
+    os.remove("ts1.dat")
+
+    return
+
+def plotNewman2(tss, tss1, i, geneNm, outDir="."):
+    from os.path import join
+    from subprocess import call
+    import os
+
+    confFile = "newman.conf"
+    visCmd = "/home2/Organism/tools/plot/bin/newman"
+    mergeCmd = "convert"
+    
+    b.cellsToDat("ts1.dat", list(tss))
+    b.cellsToDat("ts2.dat", list(tss1))
+
+    call([visCmd,
+          "-shape", "sphereVolume",
+          "-d", "3",
+          "ts1.dat",
+          "-column", str(i+1),
+          "-output", "tiff",
+          "ts1",
+          "-camera", confFile,
+          "-min", str(0),
+          "-max", str(1)])
+
+    call([visCmd,
+          "-shape", "sphereVolume",
+          "-d", "3",
+          "ts2.dat",
+          "-column", str(i+1),
+          "-output", "tiff",
+          "ts2",
+          "-camera", confFile,
+          "-min", str(0),
+          "-max", str(1)])
+
+    call([mergeCmd,
+          toNewmanFn("ts1.tif"),
+          toNewmanFn("ts2.tif"),
+          "+append",
+          "-pointsize", "20",
+          "-fill", "white",
+          "-annotate", "+10+40", geneNm,
+          join(outDir, geneNm+".tif")])
+
+    os.remove("ts1.dat")
+    os.remove("ts2.dat")
+    os.remove(toNewmanFn("ts1.tif"))
+    os.remove(toNewmanFn("ts2.tif"))
+
+
+def tFn(t, ref=""):
+    return "ts_t" + str(t) + ref + ".txt"
+
+
+def toOrgs(tss, ref="", outDir="."):
+    for t, ts in tss.items():
+        b.cellsToOrg(join(outDir, tFn(t, ref)), list(ts))
+
+    return
+
+def snd(x):
+    return x[1]
+
+def betweenTs(t, bounds):
+    ts, te = bounds
+    return t >= ts and t <= te
+
+def filterLinssBetween(linss, bounds):
+    t1, t2 = bounds
+    linssL = sorted([(ts, ln) for ts, ln in linss.items() 
+                     if betweenTs(ts[0], (t1, t2)) and betweenTs(ts[1], (t1, t2))], key=lambda p: p[0][0])
+    
+    return list(map(snd, linssL))
+
+def filterTssBetween(tss, tbounds):
+    t1, t2 = tbounds
+        
+    tssL = sorted([(t, ts) for t, ts in tss.items() if betweenTs(t, (t1, t2))], key=fst)
+    
+    return list(map(snd, tssL))
+
diff --git a/common/common/seg.py b/common/common/seg.py
new file mode 100644
index 0000000..b4b9e65
--- /dev/null
+++ b/common/common/seg.py
@@ -0,0 +1,594 @@
+import numpy as np
+import ast
+from tifffile import TiffFile
+import matplotlib.pyplot as plt
+from copy import deepcopy
+from os.path import join
+
+geneNms = ['AG',
+           'AHP6',
+           'ANT',
+           'AP1',
+           'AP2',
+           'AP3',
+           'AS1',
+           'ATML1',
+           'CLV3',
+           'CUC1_2_3',
+           'ETTIN',
+           'FIL',
+           'LFY',
+           'MP',
+           'PHB_PHV',
+           'PI',
+           'PUCHI',
+           'REV',
+           'SEP1',
+           'SEP2',
+           'SEP3',
+           'STM',
+           'SUP',
+           'SVP',
+           'WUS']
+
+class Vec3(object):
+    def __init__(self, x, y, z):
+        self.x = x
+        self.y = y
+        self.z = z
+
+    def dist(self, v1):
+        return np.sqrt((self.x - v1.x)**2 +
+                       (self.y - v1.y)**2 +
+                       (self.z - v1.z)**2)
+
+    def toOrganism(self, sep=' '):
+        return sep.join([str(self.x), str(self.y), str(self.z)])
+
+    def swapZX(self):
+        xt = self.x
+        self.x = self.z
+        self.z = xt
+
+    def toArray(self):
+        return np.array([self.x, self.y, self.z])
+
+    def __repr__(self):
+        return self.toOrganism()
+
+class Cell(object):
+    def __init__(self, cid, pos, vol, exprs=None):
+        self.cid = cid        #Int
+        self.pos = pos        #Vec3
+        self.vol = vol        #Real
+        self.exprs = exprs    #Map String Bool
+
+    def dist(self, c1):
+        return self.pos.dist(c1.pos)
+
+    def addExprs(self, exprs, geneNms):
+        for gn in geneNms:
+            if not gn in exprs.keys():
+                exprs[gn] = False
+
+        self.exprs = exprs
+        self.geneNms = geneNms
+        
+        return
+
+    def updateExprs(self, gfs):
+        gexprsUpd = dict()
+        
+        for g, _ in self.exprs.items():
+            if g in gfs:
+                gf = gfs[g]
+                (acts, reprs, out, fsAct, fsRepr) = gf
+                inputs = acts + reprs
+                vals = [self.exprs[i] for i in inputs]
+                gexprsUpd[g] = evalI((acts, reprs, out), vals, fsAct, fsRepr)
+            else:
+                gexprsUpd[g] = self.exprs[g]
+            
+        ncell = Cell(self.cid, self.pos, self.vol)
+        ncell.addExprs(gexprsUpd, deepcopy(self.geneNms))
+
+        return ncell
+
+    def updateExprsC(self, c):
+        exprsUpd = dict([(g, c.exprs[g]) for g, v in self.exprs.items()])
+        nc = Cell(self.cid, self.pos, self.vol, exprsUpd)
+        nc.geneNms = self.geneNms
+        return nc
+
+    def _boolToInt(self, b):
+        if b: return 1
+ 
+        return 0
+    
+    def _exprsToOrg(self, sep=' '):
+        exprs = [str(self._boolToInt(self.exprs[gn])) for gn in self.geneNms]
+        
+        return sep.join(exprs)
+
+    def swapZX(self):
+        self.pos.swapZX()
+
+    @classmethod
+    def fromTV(cls, nelems):
+        def parsePos(spos):
+            pos = list(np.fromstring(spos.replace('[', '').replace(']', ''),
+                                     sep=' '))
+            return pos
+        
+        cid = int(nelems['cid'])
+        vol = float(nelems['volume'])
+        [xc, yc, zc] = parsePos(nelems['center'])
+        pos = Vec3(xc, yc, zc)
+
+        return cls(cid, pos, vol)
+
+    @classmethod
+    def fromImage(cls, cd, res):
+        volVoxel = np.prod(res)
+        xc, yc, zc = cd.centroid
+        nVoxels = cd.area
+
+        xc, yc, zc = np.multiply(np.array([xc, yc, zc]), res)
+        
+        vol = nVoxels * volVoxel
+        pos = Vec3(xc, yc, zc)
+        cid = cd.label
+
+        return cls(cid, pos, vol)
+
+    def toOrganism(self):
+        if self.exprs:
+            return (' '.join([self.pos.toOrganism(), str(self.vol),
+                          str(self.cid), self._exprsToOrg()]))
+        else:
+            return (' '.join([self.pos.toOrganism(), str(self.vol),
+                              str(self.cid)]))
+
+    def toText(self, sep=" "):
+        if self.exprs:
+            return (sep.join([str(self.cid),
+                              self.pos.toOrganism(sep=sep),
+                              str(self.vol),
+                              self._exprsToOrg(sep=sep)]))
+        else:
+            return sep.join([str(self.cid), self.pos.toOrganism(sep=sep)])
+
+    def centreToArray(self):
+        return self.pos.toArray()
+
+    def getOnGenes(self):
+        return frozenset([g for g, st in self.exprs.items() if st]) - frozenset(['WUS'])
+
+    def __repr__(self):
+        return self.toOrganism()
+
+class Tissue(object):
+    def __init__(self, cells, neighs, ecellIds = None):
+        self.cells = cells            #Map Int Cell
+        self.neighs = neighs          #Map Int (Map Int Dist)
+        self.L1_cells = ecellIds      #Set Int
+
+    def __iter__(self):
+        #iterate over a list instead of map
+        return iter([v for _, v  in self.cells.items()])
+
+    @classmethod
+    def _extractCells(cls, data, res):
+        from skimage.measure import regionprops
+        cellsSeg = regionprops(data)
+
+        cells = dict()
+        for cd in cellsSeg:
+            cells[int(cd.label)] = Cell.fromImage(cd, res)
+
+        return cells
+
+    @classmethod
+    def _getConn(cls, cells, data):
+        from skimage.future.graph import RAG
+
+        connG = RAG(data)
+        neigh = dict()
+        
+        for n in connG.nodes:
+            nbrs = connG.adj[n].keys()
+            ds = [cells[n].dist(cells[nb]) for nb in nbrs]
+            
+            neigh[n] = dict(zip(nbrs, ds))
+
+        return neigh
+
+    @classmethod
+    def fromTV(cls, fnGeom, fnNeigh):
+        def parseLn(ln):
+            ln = str.strip(ln)
+            nelems = dict()
+            elems = str.split(ln, ',')
+            for elm in elems:
+                [name, val] = str.split(elm, ':')
+                name = str.strip(name)
+                val = str.strip(val)
+                nelems[name] = val
+                
+            return nelems
+        
+        cells = dict() 
+        neighs = dict()
+        ecellIds = []
+        
+        with open(fnGeom, 'r') as f:
+            for ln in f:
+                nelems = parseLn(ln)
+                c = Cell.fromTV(nelems)
+                cells[c.cid] = c
+
+        with open(fnNeigh, 'r') as f:
+            for ln in f:
+                nelems = ast.literal_eval(ln)
+                cid = nelems['cid']
+                ns = nelems['neighbors ids']
+
+                if 1 in ns:
+                    ecellIds.append(cid)
+                    ns.remove(1)
+                    
+                neighs[cid] = dict((n, cells[cid].dist(cells[n])) for n in ns)
+
+        return cls(cells, neighs, set(ecellIds))
+    
+    @classmethod
+    def fromImage(cls, data, res):
+        cells = cls._extractCells(data, res)
+        conn = cls._getConn(cells, data)
+
+        return cls(cells, conn)
+
+    def adjView(self):
+        return dict([(cid, ds.keys()) for cid, ds in self.neighs.items()])
+
+    def relabelFromMap(self, relabelM):
+        neighsR = []
+        
+        for c in self:
+            c.cid = relabelM[c.cid]
+
+        for c, dists in self.neighs.items():
+            reNs = dict([(relabelM[n], d) for n, d in dists.items()])
+            neighsR.append((relabelM[c], reNs))
+
+        self.neighs = dict(neighsR)
+
+        return
+            
+    def relabel(self):
+        relabelM = dict([(c.cid, i) for i, c in enumerate(self)])
+
+        self.relabelFromMap(relabelM)
+
+        return
+
+    def filterL1(self):
+        if not self.neighs:
+            return
+        
+        L1_cell_ids = self.neighs[1]
+
+        L1_cells = dict([(c.cid, c) for c in self if c.cid in L1_cell_ids])
+        L1_neighs = dict([(cid, nbrs) for cid, nbrs in deepcopy(self.neighs.items())
+                           if cid in L1_cells_ids])
+
+        return Tissue(L1_cells, L1_neighs)
+
+    def toNeigh(self):
+        
+        def cellToNeigh(cid, nbs):
+            nbsIds = nbs.keys()
+            nNbs = len(nbsIds)
+            nbsDists = [nbs[nid] for nid in nbsIds]
+            
+            return " ".join([str(cid), str(nNbs)]
+                           + map(str, nbsIds)
+                           + map(str, nbsDists))
+
+        ncells = sum(1 for _ in self)
+        header = str(ncells) + " " + "1"
+        
+        cellReprs = ([cellToNeigh(cid, nbs)
+                      for cid, nbs in self.neighs.items()])
+
+        return "\n".join([header] + cellReprs)
+        
+    def toOrganism(self):
+        headerComment = "#x y z vol id"
+        ns = str(len(self.cells)) + " 5"
+        content = '\n'.join([cell.toOrganism() for cell in self])
+
+        return "\n".join([headerComment, ns, content])
+
+    def centresToArray(self):
+        return np.array([c.centreToArray() for c in self])
+
+    
+class STissue(Tissue):
+    def __init__(self, cells, neighs, gexprs=None, geneNms=None):
+        super(STissue, self).__init__(cells, neighs)
+        if gexprs and geneNms:
+            self.addExprs(gexprs, geneNms)
+
+    def _defGeneExprs(self):
+        return dict([(gn, False) for gn in self.geneNms])
+    
+    def addExprs(self, gexprs, geneNms):
+        self.geneNms = geneNms
+        for cell in self:
+            try:
+                cell.addExprs(gexprs[cell.cid], geneNms)
+            except KeyError:
+                cell.addExprs(self._defGeneExprs(), geneNms)
+                
+        return
+
+    def relabel(self):
+        super(STissue, self).relabel()
+
+    @classmethod
+    def fromImage(cls, data, res, gexprs, geneNms):
+        ts = Tissue.fromImage(data, res)
+        return cls(ts.cells, ts.neighs, gexprs, geneNms)
+
+    @classmethod
+    def fromTV(cls, fnGeom, fnNeigh, gexprs, geneNms):
+        ts = Tissue.fromTV(fnGeom, fnNeigh)
+        return cls(ts.cells, ts.neighs, gexprs, geneNms)
+
+    def toOrganism(self):
+        headerComment = "#x y z vol id " + ' '.join(self.geneNms)
+        ns = str(len(self.cells)) + " " + str(len(self.geneNms)+5)
+        content = '\n'.join([cell.toOrganism() for cell in self])
+
+        return "\n".join([headerComment, ns, content])
+
+    def updateExprsBF(self, gfs):
+        ncells = dict([(c.cid, c.updateExprs(gfs)) for c in self])
+        return STissue(ncells, deepcopy(self.neighs))
+
+    def updateExprsTs(self, ts, iLn):
+        ncells = {}
+        for c1 in self:
+            try:
+                c = ts.cells[iLn[c1.cid]]
+            except KeyError:
+                c = Cell(0, Vec3(0, 0, 0), 0, dict([(g, False) for g in geneNms]))
+
+            ncells[c1.cid] = c1.updateExprsC(c)
+                
+        return STissue(ncells, deepcopy(self.neighs))
+
+    def _boolToInt(b):
+        if b: return 1
+        else: return 0
+
+    def toDict(self):
+        tsDict = {}
+
+        for c in self:
+            tsDict[c.cid] = dict(((g, self._boolToInt(v)) for g, v in c.exprs))
+        
+        return tsDict
+
+    def toCSV(self):
+        headerComment = "id,x,y,z,vol," + ','.join(self.geneNms)
+
+        content = '\n'.join([cell.toText(sep=",") for cell in self])
+
+        return "\n".join([headerComment, content])
+
+
+############### reading
+def getResolution(f):
+    try:
+        x1, x2 = f.pages.pages[0].tags['XResolution']
+        y1, y2 = f.pages.pages[0].tags['YResolution']
+        xres = x2 / x1
+        yres = y2 / y1
+        zres = 1.0
+    except:
+        xres = 1.0
+        yres = 1.0
+        zres = 1.0
+
+    return np.array([xres, yres, zres])
+
+def readImage(fseg):
+    f = TiffFile(fseg)
+    seg = f.asarray().astype(int)
+
+    return seg
+
+def readImageRegionPoints(fseg, res=[1, 1, 1], d=2):
+    from skimage.measure import regionprops
+    
+    cell_regions = dict()
+    
+    seg = readImage(fseg)
+    cellsSeg = regionprops(seg)
+
+    for cregion in cellsSeg:
+        cell_regions[cregion.label] = np.multiply(cregion.coords[:, :d], res[:d])
+
+    return cell_regions
+
+def readRegionVolume(fseg, res=[1, 1, 1]):
+    from skimage.measure import regionprops
+    
+    cell_regions = dict()
+    
+    seg = readImage(fseg)
+    cellsSeg = regionprops(seg)
+
+    for cregion in cellsSeg:
+        cell_regions[cregion.label] = cregion.area*np.product(res)
+
+    return cell_regions
+    
+
+def mergePoints(cell_regions, cids):
+    return np.vstack(tuple([cell_regions[cid] for cid in cids]))
+
+def getCellRegions(dataDir, fid="01", d=2):
+    segFn = "yr{fid}/segmentations/YR_{fid}_{t}h_segmented.tif"
+    ressFn = "yr" + fid + "/resolutions.txt"
+    
+    ress = readRess(join(dataDir, ressFn))
+    tpoints = sorted(ress.keys())
+
+    fsegs = dict([(t, join(dataDir, segFn.format(fid=fid, t=str(t)))) for t in tpoints])
+
+    return dict([(t, readImageRegionPoints(fn, res=ress[t], d=d))
+                   for t, fn in fsegs.items()])
+
+def getCellRegionVolumesF1(dataDir, ress):
+    fsegs = {10: "yr01/segmentations/YR_01_10h_segmented.tif",
+             40: "yr01/segmentations/YR_01_40h_segmented.tif",
+             96: "yr01/segmentations/YR_01_96h_segmented.tif",
+             120: "yr01/segmentations/YR_01_120h_segmented.tif",
+             132: "yr01/segmentations/YR_01_132h_segmented.tif"}
+
+    return dict([(t, readRegionVolume(join(dataDir, fn), res=ress[t]))
+                   for t, fn in fsegs.items()])
+
+def readExprs(fn):
+    #returns: Map Int (Map String Bool)  Cid -> (GeneName -> {On/Off})
+    gexprs = dict() 
+    
+    with open(fn) as f:
+        geneNms = f.readline().rstrip().split(' ')[1:]
+
+        for line in f:
+            els = line.rstrip().split(' ')
+            cid = els[0]
+            exprs = els[1:]
+            gexprs[int(cid)] = dict(zip(geneNms, [bool(int(exp))
+                                                  for exp in exprs]))
+        
+    return gexprs
+
+def writeOrg(fnGeom, fnNeigh, ts):
+    with open(fnGeom, 'w+') as f:
+        f.write(ts.toOrganism())
+
+    with open(fnNeigh, 'w+') as f:
+        f.write(ts.toNeigh())
+
+    return
+
+def readRess(fn):
+    import ast
+    
+    with open(fn, 'r') as f:
+        sress = ("{" + f.read().replace("=", ":").replace("h", "").
+                 replace("\n", "").replace("t", "") + "}")
+        ress = ast.literal_eval(sress)
+
+    return ress
+
+#functions for common tasks
+def mkOrgs(d, dExprs, dOut):
+    from os.path import join
+    
+    timepoints = [10, 40, 96, 120, 132]
+    geomF = "_segmented_tvformat_0_volume_position.txt"
+    neighF = "_segmented_tvformat_0_neighbors_py.txt"
+    exprF = "h.txt"
+
+    initF = ".init"
+    orgNeighF = ".neigh"
+
+    for t in timepoints:
+        print(t)
+        fnGeom = join(d, "t" + str(t) + geomF)
+        fnNeigh = join(d, "t" + str(t) + neighF)
+        fnExpr = join(dExprs, "t_" + str(t) + exprF)
+        fnGeomOut = join(dOut, "t" + str(t) + initF)
+        fnNeighOut = join(dOut, "t" + str(t) + orgNeighF)
+
+        gexprs = readExprs(fnExpr)
+        ts = STissue.fromTV(fnGeom, fnNeigh, gexprs, geneNms)
+
+        writeOrg(fnGeomOut, fnNeighOut, ts)
+
+    return
+
+def mkOrgGeomState(fim, fseg, fexpr, fout):
+    (data, res) = readImage(fim, fseg)
+    gexprs = readExprs(fexpr)
+
+    ts = STissue.fromImage(data, res, gexprs, geneNms)
+
+    writeOrg(fout, ts)
+
+def mkOrgGeom(fim, fseg, fout):
+    (data, res) = readImage(fim, fseg)
+    ts = Tissue.fromImage(data, res)
+
+    writeOrg(fout, ts)
+
+
+def plotTissue(ts, hl):
+    xs = [c.pos.x for c in ts]
+    ys = [c.pos.y for c in ts]
+    zs = [c.pos.z for c in ts]
+
+    cs = ['red' if c.cid in hl else 'blue' for c in ts]
+
+    fig = plt.figure()                                          
+    ax = fig.add_subplot(211, projection='3d')
+    ax.view_init(elev=95, azim=270)
+    ax.scatter(xs, ys, zs, c=cs, alpha=0.9, s=200,
+               edgecolors='black', linewidths=0.5)
+    
+    plt.show()
+
+def filterL1(ts):
+    if not ts.neighs:
+        return
+        
+    L1_cell_ids = ts.neighs[1]
+
+    L1_cells = dict([(c.cid, c) for c in ts if c.cid in L1_cell_ids])
+    L1_neighs = dict([(cid, nbrs) for cid, nbrs in deepcopy(list(ts.neighs.items()))
+                       if cid in L1_cell_ids])
+
+    return Tissue(L1_cells, L1_neighs)
+
+def const2(a, b): return b
+
+def folds1(vals, fs, iVal):
+    acc = iVal
+    for i, v in enumerate(vals):
+        acc = fs[i](acc, v)
+        
+    return acc
+
+def folds(vals, fs):
+    fs = (const2, ) + fs
+    
+    return folds1(vals, fs, False)
+
+def evalI(intr, vals, fsAct, fsRepr):
+    acts = intr[0]
+    reprs = intr[1]
+    
+    nActs = len(acts)
+    nReprs = len(reprs)
+    
+    if vals[nActs:]:
+        return (folds(vals[:nActs], fsAct) and
+                not folds(vals[nActs:], fsRepr))
+    else:
+        return folds(vals[:nActs], fsAct)
diff --git a/common/common/seg.py~ b/common/common/seg.py~
new file mode 100644
index 0000000..8fe4854
--- /dev/null
+++ b/common/common/seg.py~
@@ -0,0 +1,601 @@
+from __future__ import division
+from __future__ import print_function
+import numpy as np
+import ast
+from tifffile import TiffFile
+import matplotlib.pyplot as plt
+import boolFs as b
+from copy import deepcopy
+from mpl_toolkits.mplot3d import axes3d
+
+
+geneNms = ['AG',
+           'AHP6',
+           'ANT',
+           'AP1',
+           'AP2',
+           'AP3',
+           'AS1',
+           'ATML1',
+           'CLV3',
+           'CUC1_2_3',
+           'ETTIN',
+           'FIL',
+           'LFY',
+           'MP',
+           'PHB_PHV',
+           'PI',
+           'PUCHI',
+           'REV',
+           'SEP1',
+           'SEP2',
+           'SEP3',
+           'STM',
+           'SUP',
+           'SVP',
+           'WUS']
+
+class Vec3(object):
+    def __init__(self, x, y, z):
+        self.x = x
+        self.y = y
+        self.z = z
+
+    def dist(self, v1):
+        return np.sqrt((self.x - v1.x)**2 +
+                       (self.y - v1.y)**2 +
+                       (self.z - v1.z)**2)
+
+    def toOrganism(self, sep=' '):
+        return sep.join([str(self.x), str(self.y), str(self.z)])
+
+    def swapZX(self):
+        xt = self.x
+        self.x = self.z
+        self.z = xt
+
+    def toArray(self):
+        return np.array([self.x, self.y, self.z])
+
+    def __repr__(self):
+        return self.toOrganism()
+
+class Cell(object):
+    def __init__(self, cid, pos, vol, exprs=None):
+        self.cid = cid        #Int
+        self.pos = pos        #Vec3
+        self.vol = vol        #Real
+        self.exprs = exprs    #Map String Bool
+
+    def dist(self, c1):
+        return self.pos.dist(c1.pos)
+
+    def addExprs(self, exprs, geneNms):
+        for gn in geneNms:
+            if not gn in exprs.keys():
+                exprs[gn] = False
+
+        self.exprs = exprs
+        self.geneNms = geneNms
+        
+        return
+
+    def updateExprs(self, gfs):
+        gexprsUpd = dict()
+        
+        for g, _ in self.exprs.items():
+            if g in gfs:
+                gf = gfs[g]
+                (acts, reprs, out, fsAct, fsRepr) = gf
+                inputs = acts + reprs
+                vals = [self.exprs[i] for i in inputs]
+                gexprsUpd[g] = b.evalI((acts, reprs, out), vals, fsAct, fsRepr)
+            else:
+                gexprsUpd[g] = self.exprs[g]
+            
+        ncell = Cell(self.cid, self.pos, self.vol)
+        ncell.addExprs(gexprsUpd, deepcopy(self.geneNms))
+
+        return ncell
+
+    def updateExprsC(self, c):
+        exprsUpd = dict([(g, c.exprs[g]) for g, v in self.exprs.items()])
+        nc = Cell(self.cid, self.pos, self.vol, exprsUpd)
+        nc.geneNms = self.geneNms
+        return nc
+
+    def _boolToInt(self, b):
+        if b: return 1
+ 
+        return 0
+    
+    def _exprsToOrg(self, sep=' '):
+        exprs = [str(self._boolToInt(self.exprs[gn])) for gn in self.geneNms]
+        
+        return sep.join(exprs)
+
+    def swapZX(self):
+        self.pos.swapZX()
+
+    @classmethod
+    def fromTV(cls, nelems):
+        def parsePos(spos):
+            pos = list(np.fromstring(spos.replace('[', '').replace(']', ''),
+                                     sep=' '))
+            return pos
+        
+        cid = int(nelems['cid'])
+        vol = float(nelems['volume'])
+        [xc, yc, zc] = parsePos(nelems['center'])
+        pos = Vec3(xc, yc, zc)
+
+        return cls(cid, pos, vol)
+
+    @classmethod
+    def fromImage(cls, cd, res):
+        volVoxel = np.prod(res)
+        xc, yc, zc = cd.centroid
+        nVoxels = cd.area
+
+        xc, yc, zc = np.multiply(np.array([xc, yc, zc]), res)
+        
+        vol = nVoxels * volVoxel
+        pos = Vec3(xc, yc, zc)
+        cid = cd.label
+
+        return cls(cid, pos, vol)
+
+    def toOrganism(self):
+        if self.exprs:
+            return (' '.join([self.pos.toOrganism(), str(self.vol),
+                          str(self.cid), self._exprsToOrg()]))
+        else:
+            return (' '.join([self.pos.toOrganism(), str(self.vol),
+                              str(self.cid)]))
+
+    def toText(self, sep=" "):
+        if self.exprs:
+            return (sep.join([str(self.cid),
+                              self.pos.toOrganism(sep=sep),
+                              str(self.vol),
+                              self._exprsToOrg(sep=sep)]))
+        else:
+            return sep.join([str(self.cid), self.pos.toOrganism(sep=sep)])
+
+    def centreToArray(self):
+        return self.pos.toArray()
+
+    def getOnGenes(self):
+        return frozenset([g for g, st in self.exprs.items() if st]) - frozenset(['WUS'])
+
+    def __repr__(self):
+        return self.toOrganism()
+
+class Tissue(object):
+    def __init__(self, cells, neighs, ecellIds = None):
+        self.cells = cells            #Map Int Cell
+        self.neighs = neighs          #Map Int (Map Int Dist)
+        self.L1_cells = ecellIds      #Set Int
+
+    def __iter__(self):
+        #iterate over a list instead of map
+        return iter([v for _, v  in self.cells.items()])
+
+    @classmethod
+    def _extractCells(cls, data, res):
+        from skimage.measure import regionprops
+        cellsSeg = regionprops(data)
+
+        cells = dict()
+        for cd in cellsSeg:
+            cells[int(cd.label)] = Cell.fromImage(cd, res)
+
+        return cells
+
+    @classmethod
+    def _getConn(cls, cells, data):
+        from skimage.future.graph import RAG
+
+        connG = RAG(data)
+        neigh = dict()
+        
+        for n in connG.nodes:
+            nbrs = connG.adj[n].keys()
+            ds = [cells[n].dist(cells[nb]) for nb in nbrs]
+            
+            neigh[n] = dict(zip(nbrs, ds))
+
+        return neigh
+
+    @classmethod
+    def fromTV(cls, fnGeom, fnNeigh):
+        def parseLn(ln):
+            ln = str.strip(ln)
+            nelems = dict()
+            elems = str.split(ln, ',')
+            for elm in elems:
+                [name, val] = str.split(elm, ':')
+                name = str.strip(name)
+                val = str.strip(val)
+                nelems[name] = val
+                
+            return nelems
+        
+        cells = dict() 
+        neighs = dict()
+        ecellIds = []
+        
+        with open(fnGeom, 'r') as f:
+            for ln in f:
+                nelems = parseLn(ln)
+                c = Cell.fromTV(nelems)
+                cells[c.cid] = c
+
+        with open(fnNeigh, 'r') as f:
+            for ln in f:
+                nelems = ast.literal_eval(ln)
+                cid = nelems['cid']
+                ns = nelems['neighbors ids']
+
+                if 1 in ns:
+                    ecellIds.append(cid)
+                    ns.remove(1)
+                    
+                neighs[cid] = dict((n, cells[cid].dist(cells[n])) for n in ns)
+
+        return cls(cells, neighs, set(ecellIds))
+    
+    @classmethod
+    def fromImage(cls, data, res):
+        cells = cls._extractCells(data, res)
+        conn = cls._getConn(cells, data)
+
+        return cls(cells, conn)
+
+    def adjView(self):
+        return dict([(cid, ds.keys()) for cid, ds in self.neighs.items()])
+
+    def relabelFromMap(self, relabelM):
+        neighsR = []
+        
+        for c in self:
+            c.cid = relabelM[c.cid]
+
+        for c, dists in self.neighs.items():
+            reNs = dict([(relabelM[n], d) for n, d in dists.items()])
+            neighsR.append((relabelM[c], reNs))
+
+        self.neighs = dict(neighsR)
+
+        return
+            
+    def relabel(self):
+        relabelM = dict([(c.cid, i) for i, c in enumerate(self)])
+
+        self.relabelFromMap(relabelM)
+
+        return
+
+    def filterL1(self):
+        if not self.neighs:
+            return
+        
+        L1_cell_ids = self.neighs[1]
+
+        L1_cells = dict([(c.cid, c) for c in self if c.cid in L1_cell_ids])
+        L1_neighs = dict([(cid, nbrs) for cid, nbrs in deepcopy(self.neighs.items())
+                           if cid in L1_cells_ids])
+
+        return Tissue(L1_cells, L1_neighs)
+
+    def toNeigh(self):
+        
+        def cellToNeigh(cid, nbs):
+            nbsIds = nbs.keys()
+            nNbs = len(nbsIds)
+            nbsDists = [nbs[nid] for nid in nbsIds]
+            
+            return " ".join([str(cid), str(nNbs)]
+                           + map(str, nbsIds)
+                           + map(str, nbsDists))
+
+        ncells = sum(1 for _ in self)
+        header = str(ncells) + " " + "1"
+        
+        cellReprs = ([cellToNeigh(cid, nbs)
+                      for cid, nbs in self.neighs.items()])
+
+        return "\n".join([header] + cellReprs)
+        
+    def toOrganism(self):
+        headerComment = "#x y z vol id"
+        ns = str(len(self.cells)) + " 5"
+        content = '\n'.join([cell.toOrganism() for cell in self])
+
+        return "\n".join([headerComment, ns, content])
+
+    def centresToArray(self):
+        return np.array([c.centreToArray() for c in self])
+
+    
+class STissue(Tissue):
+    def __init__(self, cells, neighs, gexprs=None, geneNms=None):
+        super(STissue, self).__init__(cells, neighs)
+        if gexprs and geneNms:
+            self.addExprs(gexprs, geneNms)
+
+    def _defGeneExprs(self):
+        return dict([(gn, False) for gn in self.geneNms])
+    
+    def addExprs(self, gexprs, geneNms):
+        self.geneNms = geneNms
+        for cell in self:
+            try:
+                cell.addExprs(gexprs[cell.cid], geneNms)
+            except KeyError:
+                cell.addExprs(self._defGeneExprs(), geneNms)
+                
+        return
+
+    def relabel(self):
+        super(STissue, self).relabel()
+
+    @classmethod
+    def fromImage(cls, data, res, gexprs, geneNms):
+        ts = Tissue.fromImage(data, res)
+        return cls(ts.cells, ts.neighs, gexprs, geneNms)
+
+    @classmethod
+    def fromTV(cls, fnGeom, fnNeigh, gexprs, geneNms):
+        ts = Tissue.fromTV(fnGeom, fnNeigh)
+        return cls(ts.cells, ts.neighs, gexprs, geneNms)
+
+    def toOrganism(self):
+        headerComment = "#x y z vol id " + ' '.join(self.geneNms)
+        ns = str(len(self.cells)) + " " + str(len(self.geneNms)+5)
+        content = '\n'.join([cell.toOrganism() for cell in self])
+
+        return "\n".join([headerComment, ns, content])
+
+    def updateExprsBF(self, gfs):
+        ncells = dict([(c.cid, c.updateExprs(gfs)) for c in self])
+        return STissue(ncells, deepcopy(self.neighs))
+
+    def updateExprsTs(self, ts, iLn):
+        ncells = {}
+        for c1 in self:
+            try:
+                c = ts.cells[iLn[c1.cid]]
+            except KeyError:
+                c = Cell(0, Vec3(0, 0, 0), 0, dict([(g, False) for g in geneNms]))
+
+            ncells[c1.cid] = c1.updateExprsC(c)
+                
+        return STissue(ncells, deepcopy(self.neighs))
+
+    def toDict(self):
+        tsDict = {}
+
+        for c in self:
+            tsDict[c.cid] = dict(((g, b.boolToInt(v)) for g, v in c.exprs))
+        
+        return tsDict
+
+    def toCSV(self):
+        headerComment = "id,x,y,z,vol," + ','.join(self.geneNms)
+
+        content = '\n'.join([cell.toText(sep=",") for cell in self])
+
+        return "\n".join([headerComment, content])
+
+        
+
+
+#plotting
+class IndexTracker(object):
+    def __init__(self, ax, X):
+        self.ax = ax
+        ax.set_title('use scroll wheel to navigate images')
+
+        self.X = X
+        self.slices, rows, cols = X.shape
+        self.ind = self.slices//2
+
+        self.im = ax.imshow(self.X[self.ind, :, :])
+        self.update()
+
+    def onscroll(self, event):
+        if event.button == 'up':
+            self.ind = (self.ind + 1) % self.slices
+        else:
+            self.ind = (self.ind - 1) % self.slices
+        self.update()
+
+    def update(self):
+        self.im.set_data(self.X[self.ind, :, :])
+        self.ax.set_ylabel('slice %s' % self.ind)
+        self.im.axes.figure.canvas.draw()
+
+def plot3d(data):
+    fig, ax = plt.subplots(1, 1)
+    tracker = IndexTracker(ax, data)
+    fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
+    plt.show()    
+
+
+############### reading
+def getResolution(f):
+    try:
+        x1, x2 = f.pages.pages[0].tags['XResolution']
+        y1, y2 = f.pages.pages[0].tags['YResolution']
+        xres = x2 / x1
+        yres = y2 / y1
+        zres = 1.0
+    except:
+        xres = 1.0
+        yres = 1.0
+        zres = 1.0
+
+    return np.array([xres, yres, zres])
+
+def readImage(fseg):
+    f = TiffFile(fseg)
+    seg = f.asarray().astype(int)
+
+    return seg
+
+def readImageRegionPoints(fseg, res=[1, 1, 1], d=2):
+    from skimage.measure import regionprops
+    
+    cell_regions = dict()
+    
+    seg = readImage(fseg)
+    cellsSeg = regionprops(seg)
+
+    for cregion in cellsSeg:
+        cell_regions[cregion.label] = np.multiply(cregion.coords[:, :d], res[:d])
+
+    return cell_regions
+
+def readRegionVolume(fseg, res=[1, 1, 1]):
+    from skimage.measure import regionprops
+    
+    cell_regions = dict()
+    
+    seg = readImage(fseg)
+    cellsSeg = regionprops(seg)
+
+    for cregion in cellsSeg:
+        cell_regions[cregion.label] = cregion.area*np.product(res)
+
+    return cell_regions
+
+    
+
+def mergePoints(cell_regions, cids):
+    return np.vstack(tuple([cell_regions[cid] for cid in cids]))
+
+def getCellRegions(fid="01", d=2):
+    segFn = "../data/yr{fid}/segmentations/YR_{fid}_{t}h_segmented.tif"
+    ressFn = "../data/yr" + fid + "/resolutions.txt"
+    ress = readRess(ressFn)
+    tpoints = sorted(ress.keys())
+
+    fsegs = dict([(t, segFn.format(fid=fid, t=str(t))) for t in tpoints])
+
+    return dict([(t, readImageRegionPoints(fn, res=ress[t], d=d))
+                   for t, fn in fsegs.items()])
+
+def getCellRegionVolumes(fid="01"):
+    fsegs = {10: "../data/yr01/segmentations/YR_01_10h_segmented.tif",
+             40: "../data/yr01/segmentations/YR_01_40h_segmented.tif",
+             96: "../data/yr01/segmentations/YR_01_96h_segmented.tif",
+             120: "../data/yr01/segmentations/YR_01_120h_segmented.tif",
+             132: "../data/yr01/segmentations/YR_01_132h_segmented.tif"}
+
+    return dict([(t, readRegionVolume(fn, res=ress[t]))
+                   for t, fn in fsegs.items()])
+
+def readExprs(fn):
+    #returns: Map Int (Map String Bool)  Cid -> (GeneName -> {On/Off})
+    gexprs = dict() 
+    
+    with open(fn) as f:
+        geneNms = f.readline().rstrip().split(' ')[1:]
+
+        for line in f:
+            els = line.rstrip().split(' ')
+            cid = els[0]
+            exprs = els[1:]
+            gexprs[int(cid)] = dict(zip(geneNms, [bool(int(exp))
+                                                  for exp in exprs]))
+        
+    return gexprs
+
+def writeOrg(fnGeom, fnNeigh, ts):
+    with open(fnGeom, 'w+') as f:
+        f.write(ts.toOrganism())
+
+    with open(fnNeigh, 'w+') as f:
+        f.write(ts.toNeigh())
+
+    return
+
+def readRess(fn):
+    import ast
+    
+    with open(fn, 'r') as f:
+        sress = ("{" + f.read().replace("=", ":").replace("h", "").
+                 replace("\n", "").replace("t", "") + "}")
+        ress = ast.literal_eval(sress)
+
+    return ress
+
+#functions for common tasks
+def mkOrgs(d, dExprs, dOut):
+    from os.path import join
+    
+    timepoints = [10, 40, 96, 120, 132]
+    geomF = "_segmented_tvformat_0_volume_position.txt"
+    neighF = "_segmented_tvformat_0_neighbors_py.txt"
+    exprF = "h.txt"
+
+    initF = ".init"
+    orgNeighF = ".neigh"
+
+    for t in timepoints:
+        print(t)
+        fnGeom = join(d, "t" + str(t) + geomF)
+        fnNeigh = join(d, "t" + str(t) + neighF)
+        fnExpr = join(dExprs, "t_" + str(t) + exprF)
+        fnGeomOut = join(dOut, "t" + str(t) + initF)
+        fnNeighOut = join(dOut, "t" + str(t) + orgNeighF)
+
+        gexprs = readExprs(fnExpr)
+        ts = STissue.fromTV(fnGeom, fnNeigh, gexprs, geneNms)
+
+        writeOrg(fnGeomOut, fnNeighOut, ts)
+
+    return
+
+def mkOrgGeomState(fim, fseg, fexpr, fout):
+    (data, res) = readImage(fim, fseg)
+    gexprs = readExprs(fexpr)
+
+    ts = STissue.fromImage(data, res, gexprs, geneNms)
+
+    writeOrg(fout, ts)
+
+def mkOrgGeom(fim, fseg, fout):
+    (data, res) = readImage(fim, fseg)
+    ts = Tissue.fromImage(data, res)
+
+    writeOrg(fout, ts)
+
+
+def plotTissue(ts, hl):
+    xs = [c.pos.x for c in ts]
+    ys = [c.pos.y for c in ts]
+    zs = [c.pos.z for c in ts]
+
+    cs = ['red' if c.cid in hl else 'blue' for c in ts]
+
+    fig = plt.figure()                                          
+    ax = fig.add_subplot(211, projection='3d')
+    ax.view_init(elev=95, azim=270)
+    ax.scatter(xs, ys, zs, c=cs, alpha=0.9, s=200,
+               edgecolors='black', linewidths=0.5)
+    
+    plt.show()
+
+def filterL1(ts):
+    if not ts.neighs:
+        return
+        
+    L1_cell_ids = ts.neighs[1]
+
+    L1_cells = dict([(c.cid, c) for c in ts if c.cid in L1_cell_ids])
+    L1_neighs = dict([(cid, nbrs) for cid, nbrs in deepcopy(list(ts.neighs.items()))
+                       if cid in L1_cell_ids])
+
+    return Tissue(L1_cells, L1_neighs)
diff --git a/common/setup.py b/common/setup.py
new file mode 100644
index 0000000..f75eef4
--- /dev/null
+++ b/common/setup.py
@@ -0,0 +1,18 @@
+import setuptools
+
+with open("README.md", "r") as fh:
+    long_description = fh.read()
+
+setuptools.setup(
+    name="common", # Replace with your own username
+    version="0.0.1",
+    author="Argyris Zardilis",
+    author_email="argyris.zardilis@slcu.cam.ac.uk",
+    packages=setuptools.find_packages(),
+    classifiers=[
+        "Programming Language :: Python :: 3",
+        "License :: OSI Approved :: MIT License",
+        "Operating System :: OS Independent",
+    ],
+    python_requires='>=3.6',
+)
diff --git a/common/setup.py~ b/common/setup.py~
new file mode 100644
index 0000000..e69de29
-- 
GitLab