1 """
2 components/tools/OmeroPy/src/omero/util/OmeroPopo.py
3
4 -----------------------------------------------------------------------------
5 Copyright (C) 2006-2010 University of Dundee. All rights reserved.
6
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 ------------------------------------------------------------------------------
22
23 @author Donald MacDonald
24 <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
25 @version 3.0
26 <small>
27 (<b>Internal version:</b> $Revision: $Date: $)
28 </small>
29 @since 3.0-Beta4.2
30
31 """
32 import math;
33 import numpy;
34 import omero.clients
35 from omero.model import ImageI
36 from omero.model import RoiI
37 from omero.model import EllipseI
38 from omero.model import LineI
39 from omero.model import RectI
40 from omero.model import PointI
41 from omero.model import LabelI
42 from omero.model import PolylineI
43 from omero.model import PolygonI
44 from omero.model import PathI
45 from omero.model import MaskI
46 from omero.model import NamespaceI
47 from omero.rtypes import rdouble
48 from omero.rtypes import rstring
49 from omero.rtypes import rint
50 from omero.rtypes import rfloat
51 from omero.rtypes import rlist
52 from omero.rtypes import rlong
53
54
55
57 """
58 Convert a list to a Comma Separated Value string.
59 @param list The list to convert.
60 @return See above.
61 """
62 lenList = len(list);
63 cnt = 0;
64 str = "";
65 for item in list:
66 str = str + item;
67 if(cnt < lenList-1):
68 str = str + ",";
69 cnt = cnt +1;
70 return str;
71
73 """
74 Convert a csv string to a list of strings
75 @param csvString The CSV string to convert.
76 @return See above.
77 """
78 list = csvString.split(',');
79 for index in range(len(list)):
80 list[index] = list[index].strip();
81 return list;
82
83
84
85
87
88
89
90
92 self.value = None;
93 self.dirty = False;
94
95
96
97
98
99
101 if(value==None):
102 raise Exception("IObject delegate for DataObject cannot be null.");
103 self.value = value;
104
105
106
107
108
110 if(self.value.getId()==None):
111 return -1;
112 return self.value.getId().getValue();
113
114
115
116
120
121
122
123
124
127
128
129
130
131
133 self.dirty = boolean;
134
135
136
137
138
141
142
143
144
147
148
149
150
153
155
156
157
158
165
166
167
168
169
170
171
178
179
180
181
182
183
192
193
194
195
196
197
198
205
206
207
208
209
210
219
220
221
222
224
225
226
227
228
230 self.theZ = z;
231 self.theT = t;
232 self.ZBITSPLIT = 18;
233
234
235
236
238 if(self.theZ == obj.theZ and self.theT == obj.theT):
239 return True;
240 return False;
241
242
243
244
246 if(self.theZ != obj.theZ or self.theT != obj.theT):
247 return True;
248 return False;
249
250
251
252
254 if(self.theT >= obj.theT):
255 return False;
256 if(self.theZ >= obj.theZ):
257 return False;
258 return True;
259
260
261
262
264 if(self.theT < obj.theT):
265 return False;
266 if(self.theZ < obj.theZ):
267 return False;
268 return True;
269
270
271
272
274 if(self.theT <= obj.theT):
275 return False;
276 if(self.theZ <= obj.theZ):
277 return False;
278 return True;
279
280
281
282
284 if(self.theT < obj.theT):
285 return False;
286 if(self.theZ < obj.theZ):
287 return False;
288 return True;
289
290
291
292
294 return self.theZ<<self.ZBITSPLIT+self.theT;
295
296
297
298
299
300
303
304
305
306
307
308
311
312
313
314
315
318
319
320
321
322
325
326
327
328
329
331 """
332 Wrap the serverSide shape as the appropriate OmeroPopos
333 @param serverSideShape The shape object to wrap.
334 @return See above.
335 """
336 print "ServerSideShape"
337 print serverSideShape.__class__.__name__
338 if serverSideShape.__class__.__name__=='EllipseI':
339 return EllipseData(serverSideShape);
340 if serverSideShape.__class__.__name__=='RectI':
341 return RectData(serverSideShape);
342 if serverSideShape.__class__.__name__=='MaskI':
343 return MaskData(serverSideShape);
344 if serverSideShape.__class__.__name__=='PolygonI':
345 return PolygonData(serverSideShape);
346 return None;
347
348
349
350
352
353
354
355
365
366
367
381
382
383
384
385
392
393
394
395
396
398 roi = self.asIObject();
399 if(roi==None):
400 raise Exception("No Roi specified.");
401 return roi.getImage();
402
403
404
405
406
408 roi = self.asIObject();
409 if(roi==None):
410 raise Exception("No Roi specified.");
411 coord = shape.getROICoordinate();
412 shapeList = None;
413 if(self.roiShapes.has_key(coord) == False):
414 shapeList = list();
415 self.roiShapes[coord] = shapeList;
416 else:
417 shapeList = self.roiShapes[coord];
418 shapeList.append(shape);
419 roi.addShape(shape.asIObject());
420 self.setDirty(True);
421
422
423
424
425
427 roi = self.asIObject();
428 if(roi==None):
429 raise Exception("No Roi specified.");
430 coord = shape.getROICoordinate();
431 shapeList = self.roiShapes[coord];
432 shapeList.remove(shape);
433 roi.removeShape(shape.asIObject());
434 self.setDirty(True);
435
436
437
438
439
441 return len(self.roiShapes)
442
443
444
445
446
453
454
455
456
457
458
459
460
463
464
465
466
467
468
470 return self.roiShapes.iteritems();
471
472
473
474
475
476
477
478
480 coordList = self.roiShapes.keys();
481 coordList.sort();
482 keyList = [];
483 for coord in coordList:
484 if(coord>=start and coord <= end):
485 keyList.append(coord);
486 return self.roiShapes.from_keys(keyList);
487
488
489
490
491
492
504
505
506
507
508
518
519
520
521
522
523
525 roi = self.asIObject();
526 if(roi==None):
527 raise Exception("No Roi specified.");
528 roi.setNamespaces(map.keys);
529 keywords = [];
530 for namespace in map.keys:
531 keywords.append(map[namespace]);
532 roi.setKeywords(keywords);
533 self.setDirty(True);
534
535
536
537
538
547
548
549
550
551
553 roi = self.asIObject();
554 if (roi == None):
555 raise Exception("No Roi specified.");
556 namespaces = self.getNamespaces();
557 namespaceKeywords = roi.getKeywords();
558 if(len(namespaces) != len(namespaceKeywords)):
559 raise Exception("Namespaces length does not match keywords namespace length.");
560 map = {};
561 for i in range(len(namespaces)):
562 map[namespaces[i]] = namespaceKeywords[i];
563 return map;
564
566
571
572
573
574
575
576
578 shape = self.asIObject();
579 if(shape==None):
580 raise Exception("No Shape specified.");
581 z = shape.getTheZ();
582 if(z==None):
583 return 0;
584 else:
585 return z.getValue();
586
587
588
589
590
591 - def setZ(self, theZ):
592 shape = self.asIObject();
593 if(shape==None):
594 raise Exception("No Shape specified.");
595 shape.setTheZ(rint(theZ));
596 self.coord.setZSection(theZ);
597 self.setDirty(True);
598
599
600
601
602
603
605 shape = self.asIObject();
606 if(shape==None):
607 raise Exception("No Shape specified.");
608 t = shape.getTheT();
609 if(t==None):
610 return 0;
611 else:
612 return t.getValue();
613
614
615
616
617
618 - def setT(self, theT):
619 shape = self.asIObject();
620 if(shape==None):
621 raise Exception("No Shape specified.");
622 shape.setTheT(rint(theT));
623 self.coord.setTimePoint(theT);
624 self.setDirty(True);
625
626
627
628
629
631 shape = self.asIObject();
632 if(shape==None):
633 raise Exception("No Shape specified.");
634 self.setZ(coord.getZSection());
635 self.setT(coord.getTimePoint());
636 self.coord.setZSection(coord.getZSection());
637 self.coord.setTimePoint(coord.getTimePoint());
638 self.setDirty(True);
639
640
641
642
643
645 shape = self.asIObject();
646 if(shape==None):
647 raise Exception("No Shape specified.");
648 return self.coord;
649
650
651
652
654 shape = self.asIObject();
655 if(shape==None):
656 raise Exception("No Shape specified.");
657 text = shape.getTextValue();
658 if(text==None):
659 return "";
660 else:
661 return text.getValue();
662
663
664
665
666 - def setText(self, text):
667 shape = self.asIObject();
668 if(shape==None):
669 raise Exception("No Shape specified.");
670 shape.setTextValue(rstring(text));
671 self.setDirty(True)
672
673
674
675
676
677
690
697
698
699
700
701
717
718
719
720
721
724
725
726
727
730
731
732
733
735
736
737
738
749
750
751
752
754 shape = self.asIObject();
755 if(shape==None):
756 raise Exception("No Shape specified.");
757 shape.setCx(rdouble(cx));
758
759
760
761
763 shape = self.asIObject();
764 if(shape==None):
765 raise Exception("No Shape specified.");
766 cx = shape.getCx();
767 if(cx==None):
768 return 0;
769 return cx.getValue();
770
771
772
773
775 shape = self.asIObject();
776 if(shape==None):
777 raise Exception("No Shape specified.");
778 shape.setCy(rdouble(cy));
779
780
781
782
784 shape = self.asIObject();
785 if(shape==None):
786 raise Exception("No Shape specified.");
787 cy = shape.getCy();
788 if(cy==None):
789 return 0;
790 return cy.getValue();
791
792
793
794
796 shape = self.asIObject();
797 if(shape==None):
798 raise Exception("No Shape specified.");
799 shape.setRx(rdouble(rx));
800
801
802
803
805 shape = self.asIObject();
806 if(shape==None):
807 raise Exception("No Shape specified.");
808 rx = shape.getRx();
809 if(rx==None):
810 return 0;
811 return rx.getValue();
812
813
814
815
817 shape = self.asIObject();
818 if(shape==None):
819 raise Exception("No Shape specified.");
820 shape.setRy(rdouble(ry));
821
822
823
824
826 shape = self.asIObject();
827 if(shape==None):
828 raise Exception("No Shape specified.");
829 ry = shape.getRy();
830 if(ry==None):
831 return 0;
832 return ry.getValue();
833
834
835
836
837
838
839
843
844
845
846
847
849 cx = self.getCx();
850 cy = self.getCy();
851 rx = self.getRx();
852 ry = self.getRy();
853 transform = self.transformToMatrix(self.getTransform());
854 point = numpy.matrix((cx, cy, 1)).transpose();
855 centre = transform*point;
856 BL = numpy.matrix((cx-rx, cy+ry, 1)).transpose();
857 BR = numpy.matrix((cx+rx, cy+ry, 1)).transpose();
858 TL = numpy.matrix((cx-rx, cy-ry, 1)).transpose();
859 TR = numpy.matrix((cx+rx, cy-ry, 1)).transpose();
860 MajorAxisLeft = numpy.matrix((cx-rx, cy, 1)).transpose();
861 MajorAxisRight = numpy.matrix((cx+rx, cy, 1)).transpose();
862 MinorAxisTop = numpy.matrix((cx, cy-ry, 1)).transpose();
863 MinorAxisBottom = numpy.matrix((cx, cy+ry, 1)).transpose();
864 lb = transform*BL;
865 rb = transform*BR;
866 lt = transform*TL;
867 rt = transform*TR;
868 majl = transform*MajorAxisLeft;
869 majr = transform*MajorAxisRight;
870 mint = transform*MinorAxisTop;
871 minb = transform*MinorAxisBottom;
872 o = (majr[1]-majl[1]);
873 a = (majr[0]-majl[0]);
874 h = math.sqrt(o*o+a*a);
875 majorAxisAngle = math.asin(o/h);
876 boundingBoxMinX = min(lt[0], rt[0],lb[0], rb[0]);
877 boundingBoxMaxX = max(lt[0], rt[0], lb[0], rb[0]);
878 boundingBoxMinY = min(lt[1], rt[1], lb[1], rb[1]);
879 boundingBoxMaxY = max(lt[1], rt[1], lb[1], rb[1]);
880 boundingBox = ((boundingBoxMinX, boundingBoxMinY), (boundingBoxMaxX, boundingBoxMaxY));
881 centredBoundingBox = ((boundingBox[0][0]-centre[0],boundingBox[0][1]-centre[1]),(boundingBox[1][0]-centre[0],boundingBox[1][1]-centre[1]))
882 points = {};
883 cx = float(centre[0]);
884 cy = float(centre[1]);
885 xrange = range(centredBoundingBox[0][0], centredBoundingBox[1][0])
886 yrange = range(centredBoundingBox[0][1], centredBoundingBox[1][1])
887 for x in xrange:
888 for y in yrange:
889 newX = x*math.cos(majorAxisAngle)+y*math.sin(majorAxisAngle);
890 newY = -x*math.sin(majorAxisAngle)+y*math.cos(majorAxisAngle);
891 val = (newX*newX)/(rx*rx)+ (newY*newY)/(ry*ry);
892 if(val <= 1):
893 points[(int(x+cx), int(y+cy))]=1;
894 return points;
895
896
897
898
900
901
902
903
916
917
918
919
920
924
925
926
927
928
932
933
934
935
936
940
941
942
943
944
948
949
950
951
952
960
961
962
963
964
965
966
968 pts = self.toString(points);
969 pts1 = self.toString(points);
970 pts2 = self.toString(points);
971 mask = self.toString(points);
972 str = "points["+pts+"] ";
973 str = str + "points1["+pts1+"] ";
974 str = str + "points2["+pts2+"] ";
975 str = str + "mask["+mask+"]";
976 self.setPointsString(str);
977
978
979
980
982 shape = self.asIObject();
983 if(shape==None):
984 raise Exception("No Shape specified.");
985 pts = shape.getPoints();
986 if(pts==None):
987 return "";
988 else:
989 return pts.getValue();
990
991
992
993
994
995
998
999
1000
1001
1002
1003
1004
1005
1006 - def getContents(self, string, start, end):
1007 lIndex = string.find(start);
1008 if(lIndex == -1):
1009 return "";
1010 strFragment = string[lIndex:];
1011 rIndex = strFragment.find(']');
1012 if(rIndex == -1):
1013 return "";
1014 return string[lIndex+len(start):rIndex];
1015
1016
1017
1018
1019
1021 numberList = pts.split(',');
1022 return numberList;
1023
1024
1025
1026
1027
1029 str = "";
1030 for index, pt in enumerate(pointsList):
1031 str = str + pt;
1032 if(index<len(pointsList)-1):
1033 str = str + ",";
1034 return str;
1035
1036
1037
1038
1044
1045
1046
1047
1048
1050 pts = self.toCoords(self.getPoints());
1051 minx = pts[0][0];
1052 maxx = minx;
1053 miny = pts[0][1];
1054 maxy = miny;
1055
1056 for pt in pts:
1057 minx = min(pt[0],minx);
1058 miny = min(pt[1],miny);
1059 maxx = max(pt[0],maxx);
1060 maxy = max(pt[1],maxy);
1061 return [(minx,miny), (maxx, maxy)];
1062
1063
1064
1065
1066
1068 coords = [];
1069 for index in range(len(ptsList)/2):
1070 coords.append((int(ptsList[index*2]), int(ptsList[index*2+1])));
1071 return coords;
1072
1073
1074
1075
1076
1077
1079 points = {};
1080 boundingRectangle = self.getBoundingRectangle();
1081 xrange = range(boundingRectangle[0][0], boundingRectangle[1][0])
1082 yrange = range(boundingRectangle[0][1], boundingRectangle[1][1])
1083 for xx in xrange:
1084 for yy in yrange:
1085 if(self.inPolygon((xx,yy))):
1086 points[(xx,yy)]=1;
1087 return points;
1088
1089
1090
1091
1092
1093
1095 angle = 0.0
1096 polypoints = self.getPoints();
1097 cnt = 0;
1098 polygon = [];
1099 for index in range(0,len(polypoints)/2):
1100 polygon.append((int(polypoints[index*2]), int(polypoints[index*2+1])));
1101
1102 n = len(polygon)
1103
1104 for i, (h, v) in enumerate(polygon):
1105 p1 = (h - p[0], v - p[1])
1106 h, v = polygon[(i + 1) % n]
1107 p2 = (h - p[0], v - p[1])
1108 angle += self.Angle2D(p1[0], p1[1], p2[0], p2[1]);
1109
1110 if abs(angle) < math.pi:
1111 return False
1112 return True
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122 - def Angle2D(self, x1, y1, x2, y2):
1123 theta1 = math.atan2(y1, x1)
1124 theta2 = math.atan2(y2, x2)
1125 dtheta = theta2 - theta1
1126 while dtheta > math.pi:
1127 dtheta -= 2.0 * math.pi
1128 while dtheta < -math.pi:
1129 dtheta += 2.0 * math.pi
1130 return dtheta
1131
1132
1133
1134
1136
1137
1138
1139
1151
1152
1153
1154
1155 - def setX(self, x):
1156 shape = self.asIObject();
1157 if(shape==None):
1158 raise Exception("No Shape specified.");
1159 shape.setX(rdouble(x));
1160
1161
1162
1163
1165 shape = self.asIObject();
1166 if(shape==None):
1167 raise Exception("No Shape specified.");
1168 x = shape.getX();
1169 if(x==None):
1170 return 0;
1171 return x.getValue();
1172
1173
1174
1175
1176 - def setY(self, y):
1177 shape = self.asIObject();
1178 if(shape==None):
1179 raise Exception("No Shape specified.");
1180 shape.setY(rdouble(y));
1181
1182
1183
1184
1186 shape = self.asIObject();
1187 if(shape==None):
1188 raise Exception("No Shape specified.");
1189 y = shape.getY();
1190 if(y==None):
1191 return 0;
1192 return y.getValue();
1193
1194
1195
1197 shape = self.asIObject();
1198 if(shape==None):
1199 raise Exception("No Shape specified.");
1200 shape.setWidth(rdouble(width));
1201
1202
1203
1204
1206 shape = self.asIObject();
1207 if(shape==None):
1208 raise Exception("No Shape specified.");
1209 width = shape.getWidth();
1210 if(width==None):
1211 return 0;
1212 return width.getValue();
1213
1214
1215
1217 shape = self.asIObject();
1218 if(shape==None):
1219 raise Exception("No Shape specified.");
1220 shape.setHeight(rdouble(height));
1221
1222
1223
1224
1226 shape = self.asIObject();
1227 if(shape==None):
1228 raise Exception("No Shape specified.");
1229 height = shape.getHeight();
1230 if(height==None):
1231 return 0;
1232 return height.getValue();
1233
1234
1235
1237 shape = self.asIObject();
1238 if(shape==None):
1239 raise Exception("No Shape specified.");
1240 shape.setBytes(mask);
1241
1242
1243
1244
1246 shape = self.asIObject();
1247 if(shape==None):
1248 raise Exception("No Shape specified.");
1249 mask = shape.getBytes();
1250 if(mask==None):
1251 return 0;
1252 return mask.getValue();
1253
1254
1255
1256
1257
1259
1260
1261
1262
1273
1274
1275
1276
1277 - def setX(self, x):
1278 shape = self.asIObject();
1279 if (shape == None):
1280 raise Exception("No Shape specified.");
1281 shape.setX(rdouble(x));
1282
1283
1284
1285
1287 shape = self.asIObject();
1288 if (shape == None):
1289 raise Exception("No Shape specified.");
1290 x = shape.getX();
1291 if (x == None):
1292 return 0;
1293 return x.getValue();
1294
1295
1296
1297
1298 - def setY(self, y):
1299 shape = self.asIObject();
1300 if(shape==None):
1301 raise Exception("No Shape specified.");
1302 shape.setY(rdouble(y));
1303
1304
1305
1306
1308 shape = self.asIObject();
1309 if(shape==None):
1310 raise Exception("No Shape specified.");
1311 y = shape.getY();
1312 if(y==None):
1313 return 0;
1314 return y.getValue();
1315
1316
1317
1319 shape = self.asIObject();
1320 if(shape==None):
1321 raise Exception("No Shape specified.");
1322 shape.setWidth(rdouble(width));
1323
1324
1325
1326
1328 shape = self.asIObject();
1329 if(shape==None):
1330 raise Exception("No Shape specified.");
1331 width = shape.getWidth();
1332 if(width==None):
1333 return 0;
1334 return width.getValue();
1335
1336
1337
1339 shape = self.asIObject();
1340 if(shape==None):
1341 raise Exception("No Shape specified.");
1342 shape.setHeight(rdouble(height));
1343
1344
1345
1346
1348 shape = self.asIObject();
1349 if(shape==None):
1350 raise Exception("No Shape specified.");
1351 height = shape.getHeight();
1352 if(height==None):
1353 return 0;
1354 return height.getValue();
1355
1356
1357
1358
1359
1360
1361
1365
1366
1367
1368
1369
1371 transform = self.transformToMatrix(self.getTransform());
1372 x = self.getX();
1373 y = self.getY();
1374 width = self.getWidth();
1375 height = self.getHeight();
1376 point = numpy.matrix((x, y, 1)).transpose();
1377 centre = transform*point;
1378 BL = numpy.matrix((x, y+height, 1)).transpose();
1379 BR = numpy.matrix((x+width, y+height, 1)).transpose();
1380 TL = numpy.matrix((x, y, 1)).transpose();
1381 TR = numpy.matrix((x+width, y, 1)).transpose();
1382 lb = transform*BL;
1383 rb = transform*BR;
1384 lt = transform*TL;
1385 rt = transform*TR;
1386 majl = lb
1387 majr = rb
1388 o = (majr[1]-majl[1]);
1389 a = (majr[0]-majl[0]);
1390 h = math.sqrt(o*o+a*a);
1391 angle = math.asin(o/h);
1392 boundingBoxMinX = min(lt[0], rt[0], lb[0], rb[0]);
1393 boundingBoxMaxX = max(lt[0], rt[0], lb[0], rb[0]);
1394 boundingBoxMinY = min(lt[1], rt[1], lb[1], rb[1]);
1395 boundingBoxMaxY = max(lt[1], rt[1], lb[1], rb[1]);
1396 boundingBox = ((boundingBoxMinX, boundingBoxMinY), (boundingBoxMaxX, boundingBoxMaxY));
1397 points = {};
1398 xrange = range(boundingBox[0][0], boundingBox[1][0])
1399 yrange = range(boundingBox[0][1], boundingBox[1][1])
1400 transformedX = float(centre[0]);
1401 transformedY = float(centre[1]);
1402 cx = float(centre[0]);
1403 cy = float(centre[1]);
1404 for xx in xrange:
1405 for yy in yrange:
1406 newX = xx*math.cos(angle)+yy*math.sin(angle);
1407 newY = -xx*math.sin(angle)+yy*math.cos(angle);
1408
1409 if (newX-transformedX < width and newY-transformedY < height and newX-transformedX > 0 and newY-transformedY > 0):
1410 points[(int(x+cx), int(y+cy))]=1;
1411 return points;
1412
1413
1414
1415
1426
1427
1428
1429
1431 workflow = self.asIObject();
1432 if(workflow==None):
1433 raise Exception("No workflow specified.");
1434 workflow.setName(rstring(namespace));
1435 self.setDirty(True);
1436
1437
1438
1439
1441 workflow = self.asIObject();
1442 if(workflow==None):
1443 raise Exception("No Workflow specified.");
1444 namespace = workflow.getName();
1445 if(namespace==None):
1446 return "";
1447 return namespace.getValue();
1448
1449
1450
1451
1453 workflow = self.asIObject();
1454 if(workflow==None):
1455 raise Exception("No workflow specified.");
1456 workflow.setKeywords(keywords);
1457 self.setDirty(True);
1458
1459
1460
1461
1463 workflow = self.asIObject();
1464 if(workflow==None):
1465 raise Exception("No workflow specified.");
1466 workflow.setKeywords(toList(keywords));
1467 self.setDirty(True);
1468
1469
1470
1471
1473 workflow = self.asIObject();
1474 if(workflow==None):
1475 raise Exception("No Workflow specified.");
1476 keywords = workflow.getKeywords();
1477 if(keywords==None):
1478 return [];
1479 return keywords;
1480
1481
1482
1483
1490
1491
1492
1493
1495 keywords = self.getKeywords();
1496 return (keyword in keywords);
1497
1498
1499
1500
1507