A LOWER JURASSIC AMMONITE IMAGE DATABASE AND ITS APPLICATIONS by BO LIANG B.Eng., Xiangtan Mining Institute, 1984 M.Eng., China University of Geosciences, 1987 A THESIS SUBMITTED IN PARTIAL FULFILMENT OF THE REQUIREMENTS FOR THE DEGREE OF DOCTOR OF PHILOSOPHY in THE FACULTY OF GRADUATE STUDIES GEOLOGICAL SCIENCES We accept this thesis as conforming to the required standard THE UNIVERSITY OF BRITISH COLUMBIA May 1994 © B o Liang, 1994 In presentin g thi s thesi s i n partia l fulfilmen t o f th e requirement s fo r a n advance d degree a t th e Universit y o f Britis h Columbia , I agre e tha t th e Librar y shal l mak e i t freely availabl e fo r referenc e an d study . I furthe r agre e tha t permissio n fo r extensiv e copying o f thi s thesi s fo r scholarl y purpose s ma y b e grante d b y th e head . o f m y department o r b y hi s o r he r representatives . I t i s understoo d tha t copyin g o r publication o f thi s thesi s fo r financia l gai n shal l no t b e allowe d withou t m y writte n permission. (Signature) Department o f fodlojifftil fatWA The Universit y o f Britis h Columbi a Vancouver, Canad a Date fldb.iV r99 f DE-6 (2/88 ) ii -Abstract Amnion is the first computerized image database for ammonites that allows automated measurement o f morphologica l parameter s from images . Th e databas e contain s 779 0 specimens representing 1 5 families, 17 9 genera an d 131 9 species . Each specime n ha s 10 2 descriptors coverin g taxonomy , quantitativ e morphology , qualitativ e morphology , stratigraphy, locality information and general comments. Species density diagrams are plotted with respec t to basi c shel l geometry. Th e data show stron g correlation s amon g basi c geometri c parameter s whic h ma y b e relate d t o restrictions imposed by whorl shape and size. Buckman's Law of Covariation is shown to be applicable to Lower Jurassic ammonite stocks and new covariations are demonstrated among tuberculation, ribbing , whor l shap e an d ventra l features , al l o f whic h hav e functiona l implications. Morphological an d stratigraphica l dat a from Amnion sugges t a possibl e correlatio n between basi c shel l geometry , morphologica l variabilit y an d tax a duration . Lo w within -population morphological variabilities and short durations are associated with taxa that inhabit the most densely populated geometric region. Away from this peak, there is a steady increase in both morphological variability and taxa longevity implying a decrease in selective pressure. The taxonomic diversity of Lower Jurassic ammonites peaks first at the family level in the Ibex Zone, followed by generic data one zone later, and finally species in the Margaritatus Zone implying a delay in radiation for lower levels of ammonite taxa. The Late Sinemuria n and Earl y Pliensbachia n hav e hig h famil y originatio n rate s an d relativel y lo w specie s diversities; species reach their highest diversity level in the Late Pliensbachian which also has the highest family extinction rate and an almost zero origination rate. Two morphologica l diversit y indexe s ar e used t o stud y change s throug h time . Th e range index describes the range of the morphospace occupied . The Shannon index measures both the range and the evenness of the occupation. Both indexes indicate a simila r pattern . There i s a rapi d ris e t o a n Earl y Sinemuria n maximu m throug h morphologica l radiation , ill especially in terms of the basic shell geometry, followed b y a pronounced fal l i n the middle Sinemurian with diversity remaining relatively high and stable thereafter. It i s eviden t b y comparing taxonomic an d morphologica l diversit y change s throug h time tha t initia l morphologica l diversificatio n i n Lowe r Jurassi c ammonite s exceede d th e proliferation o f lower-level taxa. For example, th e morphological diversit y of the Bucklandi Zone with 46 species is slightly higher than that of the Margaritatus Zone with 177 species. It demonstrates that morphological diversity and taxonomic diversity are not simpl y correlated but that taxa initially occupy discrete positions within a broad morphospace followed b y the occupation of intervening areas. It i s observe d tha t al l Lowe r Jurassi c ammonit e familie s radiatin g int o numerou s species in the firs t zon e o f their occurrenc e hav e durations o f les s than 4 zones ; i n othe r words, rapid origination is associated with short duration. Table of Contents Abstract i i Table of Contents i v Acknowledgments vi i Chapter 1 Introductio n 1 1.1 Introductor y Statement 1 1.2 Previou s Work 2 1.3 Purpos e and Scope 3 Chapter 2 Th e Lower Jurassic Ammonite Image Database ~ Ammon 5 2.1 Introductio n 5 2.2 Th e Database Structure 6 2.3 SQ L -- The Query Language 1 8 2.3.1 Dat a entry 1 9 2.3.2 Updatin g the database 1 9 2.3.3 Queryin g the database 2 0 2.3.4 Changin g the structure of the database 2 3 2.4 Dat a Sources 2 4 Chapter 3 Imag e Analytical Techniques 2 7 3.1 Introductio n 2 7 3.2 Digitizatio n 2 7 3.3 Interactiv e Image Measurement Module 2 8 3.4 Automati c Image Measurement 3 3 3.4.1 Preprocessin g 3 4 3.4.2 Edg e detection 3 4 3.4.3 Thinnin g and line tracing 3 5 3.4.4 Locatin g coiling axis 3 5 3.4.5 Classificatio n o f coiling curves and ribs 3 6 t V 3.4.6 Derivin g morphological parameters 3 8 3.5 Fourie r Analysis of Whorl Shape 3 8 Chapter 4 Morphologica l Variation and Covariation 4 5 4.1 Introductio n 4 5 4.2 Lowe r Jurassic Ammonite Shell Morphology 4 5 4.2.1 Backgroun d 4 5 4.2.2 Th e Sample of Observations 4 6 4.2.3 Basi c Shell Geometry 4 7 4.2.4 A n interpretation of Buckman's Law of Covariation 5 1 4.2.5 Morphologica l Variability and Taxon Longevity 5 4 4.2.6 Correlatio n between Basic Shell Geometry and Other Morphological Features 6 0 4.3 Covariatio n 6 9 4.3.1 Introductio n 6 9 4.3.2 Buckman' s Law 7 1 4.3.3 Volutio n 7 4 4.3.4 Whor l Shape 7 7 4.3.5 Rib s 8 0 4.3.6 Tuberculatio n 8 2 4.3.7 Vente r 8 4 4.3.8 Summar y & Speculations 8 6 4.4 Ontogeneti c Variation 8 9 4.4.1 Umbilical Ratio (U) 8 9 4.4.2 Shel l Expansion Rate (W) 9 1 4.4.3 Rati o of Whorl Width to Whorl Height (WWWH) 9 2 4.4.4 Primar y Rib Density (PRHW) 9 4 4.4.5 Superfamil y 9 5 Chapter 5 Change s through Time 9 6 5.1 Introductio n 9 6 5.2 Stratigraphi c Division 9 7 5.3 Choic e of Characters 9 7 5.4 Geometr y through Time 9 8 5.5 Taxonomi c Diversity 10 1 5.6 Morphologica l Diversity 10 4 5.6.1 Morphologica l Range Diversity Index (MRDI) 10 4 5.6.2 Shanno n Diversity Index (SDI) 10 8 5.7 Discrepancie s between Morphological and Taxonomic Diversities 11 3 5.8 Othe r Interesting Observations 11 4 Chapter 6 A n Aid to Identification 11 9 6.1 Introductio n 11 9 6.2 Use r Interface 12 1 6.3 Example s 12 8 Chapter 7 Summar y and Conclusions 15 1 References 15 4 Appendix 1 Variou s Morphological Parameter Value Combinations and their Abundance in the Database Ammon 16 4 Appendix 2 Sourc e Code for the Graphics Interface of Ammon 20 0 Appendix 3 Sourc e Code for the Program—imageEdit 25 9 Appendix 4 Sourc e Code for the Interactive Image Measurement Module.. 276 Appendix 5 Sourc e Code for the Automated Image Measurement Module. 321 (without the Canny edge detector and the Pavlidis thinning algorithm) Appendix 6 Sourc e Code for Fourier Analysis 40 7 Appendix 7 Sourc e Code for the Animation of Whorl Shape Changes 42 2 vii Acknowledgments The completio n o f thi s thesi s i s mad e possible , i n larg e part , t o th e guidance , encouragement an d financial suppor t of my thesis advisor Dr. P. L. Smit h whose help ofte n extended beyond research. His comments and suggestions on the earlier drafts hav e greatl y improved th e manuscript . I n addition , hi s researc h librar y i s th e majo r sourc e o f dat a making up the database Ammon. Special thank s ar e du e t o Dr . R . J . Woodha m (Compute r Scienc e Department , UBC) who kindly provided the program implementation of the Canny edge detector i n the initial stage of this project an d made valuable suggestion s a s a member o f my supervisor y committee. I wish to thank Dr. T . H. Brown fo r hi s critical comment s on Chapter 4 which le d to a majo r improvement . I woul d als o lik e t o than k Dr . W . C . Barne s fo r hi s encouragement an d detailed review of the manuscript. This study was supported by a University Graduate Fellowship from th e Universit y of British Columbi a an d grant s t o P . L . Smit h fro m th e Natural Scienc e an d Engineerin g Research Council, which are gratefully acknowledged . I owe a great deal to my fellow graduate students at the Paleontology Lab o f UBC. Giselle Jakobs helped updating the information fo r Toarcian ammonites in the database and provided som e reference material . Geng a Nadaraju an d Jozse f Palfy wer e alway s ther e t o help wit h m y word-processin g relate d questions . Jozse f Palf y als o provide d advic e wit h Sinemurian ammonite s an d th e thesi s layout . I benefite d fro m discussion s wit h Gar y Johannson. A grea t dea l o f thank s mus t g o t o Toma s Clem o an d Joan n Bessle r fro m Hydrology Lab of UBC for their help. Dr. H. W. Tipper of the Geological Surve y of Canada at Vancouver kindly sen t m e a well preserved specime n of Fanninoceras fannini fo r study . He als o helped updatin g th e information fo r Hettangian ammonites from North America . I am indebted to Mr. Stewar t Kingdon (Computer Scienc e Department, UBC ) wh o provided th e progra m implementatio n o f th e Pavlidi s thinnin g algorith m an d helpe d digitizing a fe w ammonit e images . I than k Dr . Andre-Pierr e Benguerre l (UBC ) fo r hi s encouragement, suppor t and valuable advice. My sinceres t thanks go to P . L. Smit h and K. Gordanier-Smit h fo r makin g m e fee l at home as I adapted to a different environment . Finally I woul d lik e t o than k m y wif e Cind y an d m y parent s fo r thei r dedicate d support that I can always count on. Introduction 1 Chapter 1 Introductio n 1.1 Introductor y Statemen t Jurassic ammonite s ar e commonl y regarde d a s excellen t inde x fossils , evolvin g rapidly an d bein g geographicall y widespread . Th e Earl y Jurassi c i s a 3 0 M a interva l an d rocks of this age are widespread in Western North America both in allochthonous sequence s and o n the craton . "Th e hig h resolvin g powe r o f ammonit e biochronolog y offer s th e bes t method of correlating between the suspect terranes an d comparing thei r disparat e geologica l histories" (Smit h 1988) . Obtainin g biochronologi c informatio n require s th e recognitio n o f associations o f ammonit e shel l morphologie s (species) , association s whic h ca n b e demonstrated t o maintai n thei r superpositiona l relationship s throughou t thei r entir e geographic distribution . Eac h species show s variation within the population an d als o durin g ontogeny, variatio n whic h mus t b e documente d an d understoo d befor e a specie s ca n b e identified wit h confidence . Th e descriptio n o f morpholog y an d th e documentatio n o f variation can be approached in three ways: (a) The use of geometric models to describe morphology quantitativel y (theoretically capable of producing a universal set of all possible morphologies) . (b) The use of images of specimens to obtain quantitative data and qualitative descriptors (determining which parts of the universal set are actually occupied) ; a computerized image database is best suited for this task . (c) The use of a database management system to manipulate the data from (b ) to recognize species. In addition, the data from (b ) can be used to test hypotheses on evolution such as the claim fo r greate r earl y disparit y (Whittingto n 1985 ; Goul d 1989) , t o explor e possibl e correlations betwee n taxo n longevit y an d morphologica l variability , t o detec t subtl e link s between morphological features , to more rigorously document extinction events and so on. Introduction 2 Continuing advance s i n compute r hardwar e an d softwar e technologie s hav e made i t feasible to store and manipulate fossi l image s digitally. Access speeds and storage capacitie s are progressively increasin g whil e cost s decrease . A n imag e scanne r wit h 25 6 gra y shade s that cos t $5000 when thi s project starte d i n 1990 , now cost s les s than $100 0 (1994) . Imag e databases fo r othe r fossi l group s ar e likel y t o emerg e which , whe n networke d b y th e "Information Superhighway" , will make a huge impact on the way that paleontologists work. 1.2 Previou s Wor k The first attemp t to mathematically describ e coiled shell s was made in the nineteenth century b y Moseley (1838 ) who establishe d a geometric model fo r mollus k shell s based o n the logarithmic spiral. Raup (1966, 1967) reexamined and modified Moseley' s model and was able to express the basic forms of most mollusc shells using four geometric parameters. Raup (1967) showed that ammonoids occupy only a portion of the theoretical range of possibilities for shel l geometry , an d tha t som e geometri c combination s hav e bee n utilize d mor e tha n others. Raup' s approac h wa s subsequentl y use d b y War d (1980 ) t o compar e th e shel l geometry o f Jurassi c an d Cretaceou s ammonoid s t o Mesozoi c an d Cenozoi c nautiloids . Chamberlain (1981 ) wen t furthe r an d relate d ammonoi d an d nautiloi d shel l geometr y t o hydrodynamic efficiency b y showing that species with coiled shells cluster on adaptive peaks that optimize streamlining and stability. More recently, Saunders and Swan (1984,1987) have used Raup' s parameter s t o analyz e th e morphologi c diversit y o f mid-Carboniferou s ammonoids. These studies demonstrated the usefulness o f Raup's approach in evaluating an d graphically portraying the distribution of ammonoid shell geometry. During th e pas t twent y year s progres s ha s bee n mad e toward s storin g fossi l information o n compute r databases . Pric e (1984 ) describe d ho w a hierarchica l databas e management syste m wa s designed fo r materia l i n the Sedgewic k Museum , Cambridge . Th e prototype Amnio n was initiate d t o systematicall y handl e dat a accruin g fro m stratigraphi c studies o f Jurassi c sedimentar y basin s i n Nevada , Orego n an d Britis h Columbi a (Smit h Introduction 3 1986). GONIAT , a compute r databas e fo r Paleozoi c ammonoid s wa s develope d b y Kullmann, Korn, Kullmann and Petersen (1991). Images ar e o f grea t importanc e i n paleontology . Fo r example , th e Paleontologica l Cataloging Syste m Developmen t Committe e o f th e America n Associatio n o f Stratigraphi c Palynologists an d Micropaleontology Pres s have been working togethe r t o desig n a n imag e database (Huber 1990) . Similarly a major oi l company has been developing a textual database with an image library (Rich 1989) . Fossil images in these systems are for visual comparison s only, a big step forward would be to derive morphologcal parameters directly from image s in the database. Numerous attempt s hav e bee n mad e t o interpret image s sinc e th e adven t o f digita l computers. Mos t progres s ha s bee n mad e i n system s tha t perfor m a particula r tas k i n a controlled environment which provides strong constraints on the recognition process . On the other hand, less progress has been made in the areas where computers have been called upon to extrac t ill-define d informatio n fro m image s (Hor n 1985) . Th e majo r element s i n a n ammonite imag e ar e lin e features , suc h a s rib s an d th e coilin g curve . Severa l attempt s t o extract lin e wor k fro m natura l image s hav e bee n published . Cleynenbreuge l e t a l (1988 ) described initia l experienc e wit h a syste m tha t extract s road network s fro m SPO T satellit e images for example , and a knowledge-based syste m was used fo r automati c segmentatio n o f coronary vessels from digita l angiograms (Stansfield 1986) . 1.3 Purpos e and Scop e This thesis focuses on Lower Jurassic ammonites and the primary objectives are : 1. To incorporate images into the textual Ammon database and expand the database to give a comprehensive coverage of Lower Jurassic ammonites. Introduction 2. To design a computer system for measuring morphological parameters fro m images in the Amnion database and to assess the feasibility o f a fully automate d approach. 3. To quantify th e description of whorl shape so that intraspecific variations can be documented objectively and comparisons can be made among different taxa . 4. To quantify an d document intra-taxon variation in morphology which serves to define taxa more objectively . 5. To map the distribution of Lower Jurassic ammonites in terms of basic shell geometry so that relative densities of occurrence in different geometri c regions can be evaluated and functional factor s governing the distribution can be explored. 6. To detect covariations among morphological features and give interpretations whenever possible. 7. To explore possible correlation between taxon longevity and morphological variability. 8. To quantitatively document taxonomic diversity changes and morphological diversity changes through geological time, and study the relation between the two. 9. To design a computer system to aid in the identification o f Lower Jurassic ammonites which may also serve as an education tool. The Ammon Image Database 5 Chapter 2 Th e Lower Jurassic Ammonite Imag e Database - Ammo n 2.1 Introductio n Ammonite specie s normall y sho w variatio n withi n th e populatio n whic h mus t b e determined befor e a species ca n be identified wit h confidence . Th e retrieva l o f informatio n for an y specie s require s searchin g a large literatur e whic h limit s the spee d o f identificatio n and makes direct comparison of specimens difficult . During the last two decades there is increasing need to evaluate global biotic patterns in time. Plat e tectonic and paleobiogeographic research require paleontological input , and yet our established practices are hardly appropriate for integrating and evaluating fossi l dat a on a global scale , particularl y fo r narro w tim e interval s (Spice r 1986) . Maintainin g u p t o dat e revisions of taxa based o n specimens an d literature from differen t geographica l area s i s als o time consuming. Computerized databases have the potential to solve these problems. Durin g the past twenty years progress has been made towards storing fossil catalogue information o n computer databases. Pric e (1984) described how a hierarchical database management syste m was designed for material in the Sedgewick Museum, Cambridge. GONIAT, a computer database for Paleozoic ammonoids was introduced at the International Cephalopo d Symposium in 1990. GONIA T utilizes Dbase software supplemented with additional programming which provides a simplified user interface (Kullmann , Korn, Kullmann and Petersen 1991) . Image s are of great importance in paleontology. For example, the Paleontological Cataloging System Development Committee of the American Association of The Amnion Image Database (• Stratigraphic Palynologists and Micropaleotology Press have been working together to design a paleontological catalog database where, according to Huber (1990): "Palynologist s are evaluating systems that can capture images of fossils as digital data directly from a microscope, and then store, manipulate and retrieve them from an image database stored on optical disk". Similarl y a major oi l company has been developing a textual database and an image library in a system that allows one or more images of a particular fossil type to be combined with textual information (Rich 1989) . Klapper and Foster (1993) described a shape analysis system that identifies conodont species with its digitized outline. The research that leads to this thesis is a continuation of Ammon, a Lower Jurassic ammonite database which was initiated to systematically handle data accruing from stratigraphic studies of Jurassic sedimentary basins in Nevada, Oregon, and British Columbia (Smith 1986) . The computerization o f paleontological dat a is not without difficulty. Conventionall y descriptions ar e prepare d i n a forma t whic h ha s evolve d ove r man y year s o f taxonomi c practice. Within this framework presentation ma y vary and , fo r eac h individua l description , authors ar e free within limit s t o choos e whateve r phraseolog y seem s mos t appropriate . Fo r information-retrieval purpose s al l elements o f description s shoul d b e strictl y comparabl e requiring tha t terminolog y b e use d consistently . Othe r area s o f difficult y includ e characte r selection, standardization of data and amount of data that needs to be entered into database. 2.2 Th e Database Structur e The Ammo n was originall y designe d b y Smit h (1986 ) o n a mainfram e compute r using TAXIR as the database management program. Subsequently it was transferred to a The Ammon Image Database Item\Descriptor Iteml Item 2 Item 3 Descriptor 1 State 1 State 3 State 2 Descriptor 2 State 3 State 2 State 4 Descriptor 3 State 2 State 1 State 5 Figure 2-1 A table in the relational model workstation (SparcStationl ) an d converte d t o wor k unde r Oracl e Relationa l Databas e Management System . In the relationa l model , data are represented i n tabular for m (Fig . 2-1) . Eac h row o f the table i s referred t o a s an item and eac h colum n i s called a descriptor . Th e row s o f the table link together related values, and different table s may be linked implicitly i f they include values of a common item, e.g. specimen number. "The firs t ste p i n designin g a databas e i s t o establis h a lis t o f descriptor s tha t wil l describe the items in every possible way that might be useful no w and in the future but with a minimum of information redundancy. I n the database Ammon described below, an item is an ammonoid an d th e descriptor s ar e categorie s o f informatio n describin g thos e ammonoids " (Smith 1986) . Ther e were 96 descriptors proposed by Smith (1986) and the author has added another 1 1 descriptors which include relative location o f image file and scal e o f illustration . These descriptor s ar e divide d int o si x categories , viz. , taxonomy , quantitativ e morphology , qualitative morphology , stratigraphy , localit y (includin g catalogu e information ) an d genera l comments (Fig. 2-2). The following notes describing the states of these descriptors are taken from Smith' s original paper (1986) with a few modifications . The Ammon Image Database 8 Taxonomy Quantitative Morphology Qualitative Morphology Stratigraphy Locality and Catalogue Information Others 1 SUBORDER 4 SUBFAMILY 7 QUALIFIER 10TAXAUTHYEAR 13SYNSPECIES 14DMAX 20 WH 26 PRHW 32 UNITUBPOS0 38 VOLUTION 44 USHOULD 50 PRIBD 56 SRIBD 62 CONSTRD 68 STAGE 74 HORIZON 80 SITU 82 AREA 88 SECTNAME 94 REPOSITORY 99 IMAGE 15DPHRAG 21 WHMAX 27 RIBWIDTH 33 CHW 2 SUPERFAMILY 5 GENUS 8 SPECIES 11 REFAUTHYEAR 16 D 22WHD 28 SRHW 34 SF 39 WHORL SHAPE 4 0 EXPANSION 45 FLANKS 51 PTREND 57 STREND 63 CTREND 69 SUBSTAGE 75 FORMATION 81 ASSOCSPEC 83 COUNTRY 89 SECTNO 95 TYPE 100 SCALE 101 SPECFEATURE 46 VENTER 52 PFORM 58 SFORM 64 CFORM 70 EURZONE 76 MEMBER 84 PROVINCE 90 LOCNO 96 COLLECTORYR 102 REMARKS 17 UD 23 WW 29THW 35 VOLUTION0 41 UWALL 47 VENTPROF 53 PPROF 59 SPROF 65 APERTURE 71 EURSUBZONE 77 LITHOLOGY 85 LONG 91 OTHERNO 3 FAMILY 6 SUBGENUS 9 SUBSPECIES 12 SYNONYMY 18U 24WWD 30 BISPACE 36 AH 42 UWALLHT 48 KEEL 54 FURC 60 TUBERC 66 SUTURE 72 ZONE 78 DATUM 86LAT 92 SUBLOCNO 97 GENERALOC 19W 25WWWH 31 FURCPOSO 37 APPROX 43 UWALLANG 49 SULCI 55 FURCPOS 61 UNITUBPOS 67 ONTOGENY 73 SUBZONE 79 RELDATUM 87 Q 93 SUPERLOCNO 98 SPECNO Figure 2-2 Th e descriptors of the database Ammon (modified fro m Smit h 1986 ) Taxonomic descriptors. ~ Ammonoi d taxonom y ha s bee n th e subjec t o f a prolifi c literature culminatin g i n th e Treatis e o n Invertebrat e Paleontolog y (Arkell , Kumme l an d Wright, 1957 ) an d subsequen t attempt s t o updat e thi s informatio n (fo r th e Jurassi c se e Donovan and Forsey, 1973 , and Donovan, Callomon and Howarth, 1981) . Descriptors 1- 4 (SUBORDERS , SUPERFAMILIES , FAMILIE S AN D SUBFAMILIES) are self explanatory. Sinc e this database concerns only the Ammonoidea i t is not necessary to go above the sub-ordinal level. Descriptors 5 , 6, 8 and 9 should be the names used by the author of the publication i f the information i s derived from the literature. Descriptor 7 (QUALIFIER) : 1 . CF (confer) ; 2 . AFF (affinis) ; 3. ? (uncertai n generi c assignment); 4. EX GR (ex grupo); 5. SS (sensu stricto); 6. SL (sensu lato); 7. SP? (uncertain species assignment). The Amnion Image Database 9 Descriptor 1 0 (TAXAUTHYEAR) i s the author of the taxon together with the year of publication (all in parentheses if the species has been transferred from the original genus). Descriptor 1 1 (REFAUTHYEAR ) i s th e referenc e (autho r an d year ) i n whic h th e figure of the specimen appears (if applicable). Descriptor 1 2 (SYNONYMY) an d descripto r 1 3 (SYNSPECIES) are , o f course , th e valid genus and species name as judged by the person designing the database. Quantitative morphology. - Quantitative approache s t o morpholog y wer e ignore d i n the Treatise (Arkeli, Kummel and Wright, 1957 ) and it has been left to individual workers to define thei r ow n variable s wit h eac h publication s o that a lack o f consistenc y ha s resulted . The primary variable s used i n Amnion ar e descriptor s 14-17 , 19-21 , 23 , 26-33, 35-36 . Th e variables derive d from the m coul d b e calculate d bu t th e advantag e o f improve d storag e efficiency woul d be offset b y slower retrieval. Descriptor 1 4 (DM AX) is the maximum diameter measurable for that specimen. If the specimen i s matur e thi s wil l b e indicate d b y informatio n recorde d i n REMARK S (e.g. , approximated sutures ) o r i t wil l b e reflecte d i n th e informatio n fo r th e APERTUR E (descriptor 65). Descriptor 1 5 (DPHRAG) is the shell diameter at the adoral end of the phragmocone. Descriptor 16-18 , 20, 22-29 and 33 are illustrated and explained in Fig. 2-3. The Amnion Image Database 10 Descriptor 19 : W = (LR/L) 27t/r wher e LR an d L ar e th e sam e linea r featur e separate d by an angular distance about the coiling axis of r radians (a version of the expansion rate of Raup, 1966, 1967) . Thi s variabl e ca n b e use d t o extrapolate linea r measurement s (D , UD , etc. ) that th e expansio n rat e remain s constan t durin g growth. maximum whor l heigh t measurabl e fo r th e backwards o r forward s i n ontogeny , assumin g Figur e 2-3 Th e quantitative descriptor s used in Ammon (from Smit h 1986) . D (Descriptor 16 ) = the diameter at which all measurements and qualitative observations are recorded. UD (Descriptor 17 ) = the Descriptor 2 1 (WHMAX ) i s th e umbilica l diameter. U (Descriptor 18 ) = UD/D. WH (Descriptor 20) = whorl height. WHD (Descriptor 22) = WH/D. WW specimen. Thi s descripto r wa s not include d i n (Descripto r 23) = whorl width. WWD (Descriptor 24) = WW/D. WWWH the origina l Ammo n but adde d b y the autho r t o ,-. . _ ' „ .„ 7 m r T T _ . , , , (Descriptor 25) = WW/WH. The shaded deal with fragmentary specimens . half-whor l represents the interval at diameter D over which counts of primary Descriptor 3 0 : BISPACE = Y/D , where r i b S j secondar y ribs, tubercles and , , . A l , . x , A , , . constriction s are made (Descriptors PRHW Y i s th e distanc e betwee n tubercle s i n (26), SRHW (28), THW (29) and CHW bituberculate ammonoids. (33 ) respectively). Descriptor 3 1 : FURCPOSO = FD/WH, where FD i s the distanc e betwee n furcatio n point an d umbilica l seam . FURCPOS O i s th e quantitativ e equivalen t o f FURCPO S an d i s added by the author. The Ammon Image Database 11 Descriptor 3 2 : UNITUBPOS O = TD/WH , wher e TD is the distance between tubercles and umbilical seam in unituberculate ammonoids. UNITUBPOSO is the quantitat--ive equivalen t o f UNITUBPO S an d i s adde d b y th e author. Descriptor 3 4 (SF ) i s th e sutura l formul a fo r th e specimen at that diameter. A specimen may be entered into the compute r severa l time s a t differen t shel l diameter s s o that the ontogenetic development of a sutural pattern may be recorded. Descriptor 35 : VOLUTIONO = LP/wh where LP i s the whor l overla p an d w h i s the inner whorl heigh t (Fig . 2-4) . This descripto r i s the quantitativ e equivalen t o f VOLUTIO N WH 1 w h 1 -' o •> LP , i Figure 2-4 Descriptor s 35, 36 VOLU1 AH = LJ 1ON0 = LP/wh. P/WH. 1 ADVOLUT E 3 MIDVOLUT E 0 5 OCCLUDE D 7 HETEROMORP H 2 EVOLUT E Q 4 INVOLUT E 6 ELLIPTICA L 8 HELICOSPIRA L WHORL SHAP E 2 ELLIPSOI D 5 LANCEOLAT E 8 W RECTANGULA R 11 W TRIANGULA R C^> 3 W ELLIPSOI D 9 QUADRAT E R 12 TRAPEZOI D 1 ROUNDE D o 7 RECTANGULAR 10 TRIANGULAR ^=7 13 CORONAT E Figure 2-5 Th e states for the descriptor VOLUTION (38) (from Smit h 1986) Figure 2-6 Th e states for the descriptor WHORL_SHAPE (39) (from Smit h 1986 ) The Amnion Image Database 1 2 and is not included in the original Amnion. Descriptor 36: AH = LP/WH where LP i s th e whor l overla p an d W H i s th e outer whor l heigh t (Fig . 2-4) . Thi s descriptor seem s importan t i n interpretin g the covariatio n betwee n W an d U (se e section 4.2.4). Figure 2-7 State s used for describing profiles Descripto r 3 7 (APPROX) : Thos e of the UWALL, the FLANKS, the primar y variable s tha t ar e approximat e ar e VENTPROF, the PPROF, the SPROF. l i s t e d i n descripto r 3 0 s o tha t the y ca n b e (from Smit h 1986) eliminate d fro m subsequen t analyse s whe n necessary. Qualitative morphology. — Descriptor 3 8 (VOLUTION ) : I n th e descriptiv e term s illustrated i n Fig . 2-5 , the umbilical sea m o f the whorl progresse s fro m barel y touchin g th e preceding whorl (advolute) to overlapping the upper (evolute) , middle (midvolute) and lower (involute) thir d o f th e flan k o f th e precedin g whorl , whe n th e shel l i s occluded , th e oute r whorl completel y cover s the inne r whorls . State s 6 to 8 describe th e situatio n whe n growt h deviates from a regular , logarithmicall y accretin g planispire . Som e ammonoids , particularl y in the Paleozoic, show an elliptical growth pattern throughout ontogeny. More commonly the mature whor l wil l egres s t o th e elliptica l patter n o r eve n los e contac t wit h th e precedin g regular whorl s altogethe r an d becom e heteromorphi c (stat e 7) . Som e ammonoid s hav e a iilllllll fr—1 1 2 3 4 5 CONCAVE FLAT CONVEX INFLATED ANGULAR The Amnion Image Database 1 3 n n n ri n A n A 1 2 3 4 5 6 7 8 PLAIN CARINATE SULCATE CARINATE-SULCATE BICARINATE BICARINATE-SULCATE TRICARINATE TRICARINATE-SULCATE 3 \ 2 ^ T 1 / \ | 20 ° 4 / _ _ _ / 5 1 RURSIRADIAT E 2 GRURSIRADIAT E 3 RECTIRADIAT E 4 GPRORSIRADIAT E 5 PRORSIRADIAT E Figure 2-9 State s for the descriptors PTREND and CTREND (from Smit h 1986 ) translational componen t t o thei r growt h an d appear gastropod-lik e (stat e 8) . State s 7 an d 8 Figure 2-8 State s for the descriptor n e v e r o c c u r i n L o w e r Jurassi c ammonites. VENTER (from Smit h 1986) ~ . . ~ n OTTA™- \ v ' Descripto r 3 9 (WHORL_SHAPE) : se e Fig. 2-6. Descriptor 4 0 (EXPANSION ) describe s ho w fas t th e shel l expand s i n th e followin g terms: slow, moderate and rapid. Descriptor 4 1 (UWALL ) describe s th e profil e o f the umbilica l wal l usin g th e term s shown in Fig. 2-7. Descriptor 42 (UWALLHT) is the height of the umbilical wall (low; high). Descriptor 4 3 (UWALLANG ) describe s th e slop e o f a fla t umbilica l wal l i n th e following terms: undercut, vertical, steep and shallow. Descriptor 4 4 (USHOULD ) i s th e profil e o f th e umbilica l shoulde r (rounded ; angular). The Amnion Image Database 14 Descriptor 4 5 (FLANKS ) describe s the profil e o f th e whor l flanks i n th e terminology of Fig. 2-7. Descriptor 4 6 (VENTER ) describe s the appearance of the venter as shown in Fig. Figur e 2-10 State s for describing position 2-8. o n the profile of a whorl. Used in PFORM, Descriptor 4 7 (VENTPROF ) i s th e FURCPOS , UNITUBPOS and CFORM profile of the venter in cross-section as shown in Fig. 2-7. Descriptor 4 8 (KEEL ) refer s t o carinat e form s an d describe s th e prominenc e (high , low) and profile (flat-topped , rounded , angula r or crenulate) of the keel as well as noting the presence of a floor . Descriptor 4 9 (SULCI ) describe s sulc i (descripto r 47 , state s 3 , 4 , 6 , 8 ) b y th e term s deep or shallow. Descriptor 50 (PRIBD) describes the ribbing density by the terms distant or dense. Descriptor 5 1 (PTREND ) describe s th e averag e tren d o f th e primar y rib s acros s th e flank of the whorl (Fig . 2-9). Descriptor 5 2 (PFORM) : The form o f the primary ribbin g ha s been describe d b y a number o f terms (e.g. , Schlegelmilch , 1976 , fig. 7 , Arkell , Kumme l an d Wright , 1957 , fig. 132, Smith , 1986 , fig. 11) . Th e term s use d i n th e Treatis e (Arkell , Kumme l an d Wright , 1957, fig. 132) are adopted here for simplicity > II • 5 - 4 N 1 1 UWAL L (umbilica l wall ) 2 USHOULDE R 3 LOWFLAN K 4 MIDFLAN K 5 UPPERFLAN K 6 VLSHOULDE R (vent ro- la tera l shoulder) 7 VENTE R The Ammon Image Database 15 ^P^ X T X 6 VIRGATOTOM E VENTRAL VIE W 'Si > APERTURE 1 RURSIRADIAT E 2 GRURSIRADIAT E 3 RECTIRADIAT E 4 GPRORSIRADIAT E 5 PRORSIRADIAT E Figure 2-12 State s for the descriptor STREND showing the trend of secondary ribs across the venter of a coronate Figure 2-11 State s for the descriptor FURC ammonoi d (from Smit h 1986) . Descriptor 5 3 (PPROF) indicates the cross-sectional profile o f the primary rib s in the terms shown in Fig. 2-7. Descriptor 54 (FURC) describes the pattern of rib furcation a s shown in Fig. 2-11. Descriptor 55 (FURCPOS) indicates the position of the furcation (descripto r 54, states 2-6; th e first furcatio n i s indicate d fo r state s 5 and 6 ) using th e terminolog y o f Fig . 2-10 . Fasciculation can be described using a combination of descriptors 54 and 55. Descriptor 56-5 9 describ e character s o f th e secondar y ribbin g i n th e terminolog y applied t o th e primar y rib s (analogou s descriptors 50-53 ) wit h th e followin g modifications: descripto r 5 7 (STREND ) i s shown in Fig. 2-12 and descriptor 58 (SFORM) are prefixe d wit h a n I whe n th e rib s ar e intercalated. Figure 2-13 State s for the descriptor TUBERC (from Smit h 1986 ) 1 UN I 4 MULT I 2 8 1 5 CLAVAT E IT 3 TR I 6 BULLAT E The Ammon Image Database 1 6 Descriptor 6 0 (TUBERC ) an d 6 1 (UNITUBPOS) describ e th e tuberculatio n (Fig. 2-13) and the position of the tubercles i n unituberculate form s i n th e terminolog y o f Fig. 2-10. Descriptors 62-6 4 describe the density , trend an d for m o f constriction s i n th e sam e terminology applie d t o primar y rib s (descriptors 50-52). Descriptor 6 5 (APERTURE ) describe s the aperture using the state s illustrated i n Fig . _ 1 . Figur e 2-14 State s for the descriptor APERTURE (from Smit h 1986 ) Descriptor 6 6 (SUTURE) i s a field fo r comments on features of the suture. Descriptor 6 7 (ONTOGENY ) indicate s whethe r ther e i s a distinc t chang e i n morphology durin g ontogen y (ye s or no). This descripto r i s used to tell the user to sca n the database a t a variet y o f shel l diameter s t o loo k fo r multipl e entrie s o f dat a fo r th e sam e specimen a t different diamete r (eac h entry wil l have the sam e specime n number (descripto r 98) ) and to check the general remarks. Stratigraphy. -- The descriptors for stratigraphy are largely self explanatory. Descriptors 7 0 (EURZONE ) an d 7 1 (EURSUBZONE ) ar e standar d zone s an d subzones of the Northwest European Province (Dean, Donovan and Howarth, 1961) . APERTURE 2 CONSTRICTE D a 4 SINUOU S 6 ROSTRU M i a 1 SIMPL E 3 FLARE D 5 LAPPET S a 7 HOR N The Amnion Image Database 1 7 Descriptors 72-74 record a zonation other than that of northwest Europe. Descriptor 78-79 : Fo r ammonit e localitie s fro m measure d sections , th e poin t o f reference suc h a s th e contac t betwee n tw o formation s i s liste d i n descripto r 7 8 wit h measurements i n meters abov e o r below (negative) tha t datum show n in descriptor 79 . This information permit s th e rapi d compilatio n o f th e stratigraphi c rang e o f a specie s i n an y section. Descriptor 8 1 (ASSOCSPEC ) : Th e numbe r o f specimen s o f thi s specie s a t thi s locality that are not entered separately into the database. Locality and catalogue information. — Descripto r 8 2 (area ) divide s th e worl d int o a few broad geographic regions such as the Western Pacific, Western Tethyan, North America, South America, Northwest Europe . Descriptor 8 4 (PROVINCE): Province , state , or county . Descriptors 85-8 7 giv e th e geographi c locatio n o f th e specime n i n term s o f longitud e an d latitude wit h descripto r 8 7 givin g th e positio n relativ e t o th e equato r ( N o r S ) an d th e Greenwich meridian (E or W). Descriptors 88-91 are the section name, section number, locality number (may include letters) and any other number, e.g. , a field numbe r that is associated with the specime n apar t from it s official catalogu e number (descriptor 98). Descriptor 9 2 (SUBLOCNO ) an d 9 3 (SUPERLOCNO ) recor d th e subjacen t an d superjacent localitie s i n a measure d sectio n s o tha t a worke r ca n retriev e informatio n i n stratigraphic order . Descriptor 95 (TYPE) has the following states : holotype, paratype, syntype, lectotype, paralectotype, neoholotype, newparatype, topotype, hypotype. The Ammon Image Database 1 8 Descriptor 96 (COLLECTORYR) list s the collector and year of collection to facilitat e retrieval of information from field notebooks. Descriptor 9 7 (GENERALOC ) give s non-standardize d localit y information , e.g. , Graham Island, Silvies River, etc. Descriptor 98 (SPECNO) is the unique label that characterizes this specimen. Descriptors 99 (IMAGE) and 100 (SCALE) give the relative path of image files in the file syste m and the scale of the illustration. The absolute path of the image is determined b y combining the relative path with a base directory checked at run time which enables the user to move the image file to the desired location without modifying th e user interface describe d in Chapter 6. Descriptor 10 1 i s adde d b y th e autho r fo r th e followin g reason : Som e taxonomi c groups have unique feature tha t i s important fo r the identification o f the grou p ye t doe s no t justify a separat e descripto r i n th e database , fo r example , Hildoceras an d Hildaites hav e strong media n latera l groove ; Amaltheus, Aegoceras, an d Pleuroceras hav e serrate d keel ; they ar e lumpe d int o SPECFEATUR E whic h ca n b e scanne d fo r a specifi c featur e whe n needed. Descriptor 10 2 (REMARKS) is a free forma t tex t field, remark s that does not fit into any of the descriptors can be put here. 2.3 SQ L — The Query Languag e The Oracl e relationa l databas e managemen t syste m allow s th e operato r t o us e th e industry standar d languag e SQ L to store , retrieve an d manipulat e data . SQ L i s a n English -The Ammon Image Database 1 9 like languag e consistin g o f severa l "layers " o f increasin g complexit y an d capability . En d users with little or no experience with databases can learn SQL's basic features ver y quickly , yet SQL provides information professional s wit h the powerful an d complet e se t o f facilitie s required (Anonymous 1990a) . 2.3.1 Dat a entry The use r add s ne w specimen s t o Ammo n b y issuin g th e INSER T command , fo r example, INSERT INTO Ammon (genus, species, zone, specno, d) VALUES ("Badouxia", "canadensis" , "Bucklandi", "C-201453", 4.2); inserts a new specimen of Badouxia canadensis with a specimen number o f C-201453 fro m Bucklandi zone. I f more than one specimen need to be entered, a more efficient wa y is to use one's favorit e wor d processin g progra m o r tex t edito r an d sav e the dat a int o a n ASCI I file , then use SQL*Loader to load data in external file s int o Ammon (see Anonymous 1990 b fo r detail). In fact, most of the data in Ammon are entered using SQL*Loader . 2.3.2 Updatin g the database The UPDAT E comman d change s value s store d i n Ammon . Descriptor s suc h a s WWWH, U, WWD in Ammon are represented as ratios but some ammonite workers prefer t o present thes e parameter s a s percentages . Thi s ca n b e achieve d b y issuin g a n UPDAT E command: UPDATE Ammo n SET www h = wwwh*100, u = u*100, wwd = wwd*100 The Ammon Image Database 2 0 which convert s WWWH , U , WW D o f all specimen s i n Ammon int o percentag e values . A WHERE claus e ca n b e use d t o specif y specimen s tha t nee d t o b e updated . Th e imag e measurement modul e described i n Chapte r 3 can also be used to update morphologica l dat a in Ammon. The DELETE command removes specimens from Ammon . 2.3.3 Queryin g the database Retrieving dat a fro m th e databas e i s th e mos t commo n SQ L operation . A databas e retrieval is called a query and to issue a query the operator uses the SELECT command. The basic SELECT command has three parts: SELECT som e descriptors FROM a table (such as Ammon) or some tables WHERE searc h condition A question lik e "wha t specie s ar e involute , have a carinate vente r o r more than 3 0 primary ribs per half whorl" is addressed by SELECT synonymy , synspecies FROM Ammo n WHERE volution='involute ' AND (venter='carinate' OR prhw>30); The user can also select items that do not meet search conditions. For example, the followin g query retrieves all species that are not involute: SELECT synonymy , synspecies FROM Ammo n WHERE volutio n != 'involute'; != means not equal. Th e user may combine AND, OR and != in the same query to connect as many search conditions as are necessary to retrieve the data. The Ammon Image Database 2 1 The IN operator let s the user select items that contain a value that matches one of the values in a list. For example, the following quer y lists al l species with a carinate venter , or a carinate-sulcate venter or sulcate venter: SELECT synonymy , synspecies FROM Ammo n WHERE vente r IN ('carinateVcarinate-sulcateVsulcate') ; Because som e specie s ma y hav e many specimen s i n the databas e an d eac h specime n i s a n independent item in the database, there would be lots of duplicate species names in the query result which can be eliminated by specifying DISTINCT in the SELECT clause: SELECT DISTINC T synonymy, synspecies The user can also select items that match a specified pattern o f characters or numbers. For examples, the user may want to find al l species that have "der" in their names: SELECT DISTINC T synonymy, synspecies FROM Ammo n WHERE synspecie s LIK E '%der%' ; the SQ L operato r LIK E mean s tha t specie s nam e contain s th e strin g "der " an d the percen t sign (%) signifie s an y string of zero or more characters. This feature allow s multiple states in the same entry. For example , for a specimen that has both bi-furcate an d tri-furcate ribs , the value of the descriptor FURC can be input as "bi,tri" which will meet the search condition for specimens with bi-furcate ribs as well as specimens with tri-furcate ribs . SQL als o support s the following arithmeti c operators , string manipulation an d grou p functions: The Amnion Image Database 22 Arithmetic + ~ * / POWER ROUND TRUNC ABS Operators Add Subtract Multiply Divide Exponentiation Rounding Truncation Absolute Value String 1 DECODE LENGTH SUBSTR INSTR UPPER LOWER SOUNDEX Function Concatenation Translate String Length Substring Instring Upper Case Lower Case Sound Matching Group AVG SUM MAX MIN STDDEV VARIANCE COUNT Function Average Sum Maximum Minimum Standard Deviation Variance Number of Items This i s onl y a partia l list , mos t relevan t t o Amnion . Th e SQ L Languag e Referenc e Manual (Anonymous 1990c ) has a complete set of the operators and functions . Group function s whic h le t th e use r selec t summar y informatio n fro m group s o f item s demonstrate th e powe r o f SQL . Suppose , fo r instance , tha t th e use r want s t o kno w th e average shell expansion rate (W) and degree of intraspecific variatio n of W for ever y specie s that has at least 6 specimens in the Ammon database, the user can issue the following query : SELECT synonymy,synspecies,AVG(w),STDDEV(w ) FROM Ammo n GROUP by synonymy,synspecie s HAVING COUNT(* ) >= 6; In the example above, every species is a group, average and standard deviation values of W are calculated for each species. Just as specify searc h conditions for individual items using The Ammon Image Database 23 the WHERE clause, the SQL clause HAVING is used to specify search conditions for groups of items. One of the reasons that SQL is so powerful is that complex queries can be built out of several simple queries. A WHERE clause of one query may contain another query called a subquery. Suppose that the user wants to retrieve all specimens (specno) collected from the same zone as specimen X with a specimen number of GSC20122 : SELECT specno FROM Ammon WHERE zone = (SELECT zone FROM Ammon WHERE specno = 'GSC20122'); Subqueries may be just as complex as main queries — they may contain subqueries of their own. 2.3.4 Changing the structure of the database The SQL command ALTER can be used to add new descriptors to Ammon or make columns of existing descriptors wider to accommodate long text strings. ALTER TABLE Ammon ADD (specfeature CHAR (100)); In this command a new descriptor specfeature is added to Ammon with data type (CHAR) and maximum number of characters in the descriptor (100). Oracle will not waste storage by reserving space for the maximum number of characters allowed for each descriptor. For example, even though the maximum length of a value in descriptor specfeature is 100, most specimens do not have any entry for this descriptor therefore occupy no storage space at all. The Ammon Image Database 24 SQL is the industry standard relational database language which assures compatibility across different database systems including IBM's DB2 and SQL/DS. In addition, Oracle runs on an impressive range of computers, from PCs to minis to mainframes. All versions of Oracle are identical which enables the application be moved across hardware and software boundaries with virtually no modifications. More importantly, SQL commands can be embedded in standard programming languages such as C, FORTRAN or Pascal. For example, a graphics user interface has been implemented for Ammon using C, embedded SQL, Sunview and a graphics library called Pixrect. This graphics user interface gives easy access to the database as well as image display and manipulation capabilities (see Chapters 3 and 6 for details). 2.4 Data Sources The following references were used in compiling the Ammon image database: Arkell, Kummel and Wright, 1957 Arthur, 1985, 1987 Blasco, 1978 Blasco, Levy and Nullo, 1978 Crickmay, 1925, 1928 Dagis, 1968, 1974, 1976 Dean, Donovan and Howarth, 1961 Erben, 1956 Frebold, 1951,1958,1959,1960, 1964,1966,1967, 1970,1975 Frebold, Mountjoy et al., 1967 Gabb, 1869 Gabilly, 1976a, 1976b Geczy, 1976 Geyer, 1974, 1979 Guex, 1980,1981,1989 The Ammon Image Database 25 Hall, 1987 Hall and Howarth, 1983 Hall and Westerman, 1980 Hillebrandt, 1973,1981,1982, 1987, 1989, 1990 Hirano, 1971, 1973 Imlay, 1968,1981 Jakobs, 1992 Kalacheva, 1980 Mclearn, 1932 Meister, 1986 Novedades, 1988 Obrien, 1985 Palfy, 1991 Poulton, 1987,1991 Poulton and Tipper, 1991 Quinzio, 1987 Repin 1974,1968 Riccardi and Westermann, 1991a, 1991b Sanborn, 1960 Schlatter, 1991 Schlegelmilch, 1976 Smith, 1976, 1981 Smith and Tipper, 1986, 1988 Stankevich, 1964 Taylor, 1988 Thompson and Smith, 1988, 1992 Tilmann, 1917 Tipper and Richards, 1976 Tipper, Smith et al., 1991 Tozer, 1982 Wang and Smith, 1986 Westermann, 1972 Westermann and Riccardi, 1972, 1979 White, 1889 Whiteaves, 1884 The Ammon Image Database 26 Wiedenmayer, 1977, 1980 Willard, 1963 The prototype Ammon had information on about 1400 specimens; the present greatly expanded version has 7790 specimens from over 25 countries. The number of specimens sampled from each country is not uniform; the vast majority are from the following countries in descreasing order of abundance: Canada, Russia, United States, Switzerland, Argentina, France, Chile, Germany, Britain, Hungary, Austria, Mexico and Japan. Image Analytic Techniques 27 Chapter 3 Image Analytic Techniques 4.1 Introduction A number of interesting hypotheses in paleobiology can only be addressed using quantitative morphological data. Claim for greater early disparity, for example, cannot be confidently established until we develop quantitative techniques for the characterization of morphospace and its differential filling through time (Gould 1991). Subtle links between morphological features can hardly be recognized without the power of the computer to isolate and quantify all aspects of variation and covariation (Smith 1986). Some ammonite morphological parameters such as shell expansion rate and volution show continuous spectra, quantification of which is needed to differentiate intraspecific variations from interspecific variations. Although quantification is highly desired, deriving data from actual specimens is time consuming. Even for qualitative morphological characters, typing numerous character states into the computer is a slow and tedious process. The following computer image analytic techniques are used to alleviate the problem. 4.2 Digitization Illustrations of selected ammonites from published literature are scanned into a Sun SparcStation using a MicroTek image scanner with 256 gray shades. The highest resolution available from the scanner is 400 dpi (dots per inch), but after some experiments, it is found that 300 dpi resolution gives the best results for illustrations on good quality paper and 200 dpi resolution is enough for illustrations on old and poor quality paper. To make images displayed on screen (with 100 dpi resolution) the same size as their original forms on paper, a program was written to shrink scanned image to one half original size (for illustrations scanned with 200 dpi resolution), or one third of original size (for illustrations scanned with 300 dpi resolution) by averaging adjacent pixels. This greatly reduces storage requirements since a half sized image only occupies one fourth of the original disk space. Image Analytic Techniques 28 Fossil plates in journal articles normally have multiple specimens figured in each plate. To speed up the digitization process, a whole plate is scanned into the computer and the program "imageEdit" (Appendix 3) is used to pick up individual specimens, clear irrelevant components and save the selected part of the image as a separate file. An image is saved as a Sun raster file which is named after the author, year and abbreviation of the publication followed by plate and figure number. For example, plate 1, figure 1 of Hall 1987 (Canadian Journal of Earth Science) is named as: hall87cjesl-l.ras (lateral view), hall87cjesl-l.l.ras (ventral view), the corresponding descriptor IMAGE in the Ammon is coded as hall87cjesl-l|l.l. "|" is a separator which indicates the start of another image with the same base name as the preceding one. 3.3 Interactive Image Measurement Module A front-end user interface is built on top of the Ammon database to facilitate measurement of morphological characters from images of specimens. The interface is implemented in C, embedded SQL, Sunview and a graphics library called Pixrect (see Appendix 4). The basic idea of this module is to derive morphological characters by combining the human ability to visually locate features with the computer ability to memorize and compute. When a specimen is entered into the database for the first time, morphological data are often not available and have to be measured from images of the specimen. Suppose a specimen with a SPECNO of 43252a is entered into the Ammon without morphological data. Later it is called to screen (Fig. 3-1, see Chapter 6 for detail of query by user interface) to calculate the shell expansion rate (W) and the umbilical ratio (U), a procedure requiring four control points: the coiling axis (O), two points (P3, P4) on the outer coiling curve and one point on the inner coiling curve (P2), another point (Pi) is given to enable simulation of the inner whorl spiral and to help in locating the coiling axis more precisely since fitting the inner curve relies even more heavily on correct location of the coiling axis. P] and P2 are separated by one whorl. By definition (Fig. 3-1) Arnmon Image Database Display Image Window Figure 3-1 Interactive image measurement program ' Image Analytic Techniques 30 W = (OP3/OP4)27l/r where OP3 and OP4 are separated by an angular distance of r radians which must be less than 7i to make coiling direction unequivocal to the program. U = OP2/OP3 For rare ammonites that have an undercut umbilical wall, the umbilical shoulder rather than the umbilical seam is taken as the edge of the umbilicus (Smith 1986). An equivalent measurement of W for inner whorl is WI - OP2/OP! where OP2 and OPj are separated by one whorl. WI can be used to simulate the inner whorl spiral. The diameter of the shell and the whorl height at point P3 are D = OP3 + OP3/JW, WH = P2P3 The absolute values for D and WH in centimeters is computed by combining the image scale recorded in the Ammon and monitor resolution coded in the program. The whorl overlap ratios (Fig. 2-4) with respect to the inner whorl and the outer whorl are (Fig. 3-1): VOLUTION0 = P2X/P1P2, AH = P2X/P2P3 To calculate the above parameters, all the user needs to do is to mark the five control points with the middle mouse button then press one of the "W(out)-', the "W(in)=" or the "U=" command buttons in the top window, the program will superimpose the simulated inner and outer coiling curves on the image and show the parameter values in the text fields following the command buttons. If a specimen has parts broken or damaged and the control points cannot be located with confidence, the user can proceed with "try and see". If the fitting is not satisfactory the operation can be undone by pressing the "Reset image" button in the left window. After the locations of the control points have been adjusted the user can try fitting again. Once the location of the coiling axis is settled, the primary rib density (PRHW) can be counted by clicking on a number of consecutive ribs with the middle mouse button. Suppose that N ribs are marked then PRHW = N*7t/r Image Analytic Techniques 31 where r is the angular distance between the first and last ribs which must be less than n to avoid ambiguity about coiling direction yet large enough to justify extrapolation of the number of ribs for half whorl (PRHW). This can be a handy tool for exploring primary rib density change during ontogeny; the user simply clicks on a few ribs and the program does the counting and extrapolation. Fig. 3-1 shows that the PRHW for this specimen gradually increases from 10 in the innermost whorl to 12 in the middle whorl to 15 in the last whorl. The secondary rib density (SRHW) if applicable can be determined in a similar way. Another group of parameters which are related to whorl width can be measured from a cross-section (Fig. 3-1, left): WW = AB = 2.5cm, WWWH = AB/DD1 = 0.88, WWD = AB/CD = 0.27 To measure WW the user clicks on points A and B then press the "Distance" button in the left window; to measure WWWH and WWD the user clicks on the four control points A through D and then press the "Ratio" button. For most specimens, cross-sections are not available so the above parameters have to be derived from ventral view images. Since the ventral view image is subject to photographic distortion at both ends, the two control points for whorl width (A' and B' in Fig. 3-1, right) are located in the center of the view and line A'B' is perpendicular to the plane of bilateral symmetry. To determine the shell diameter and whorl height of the specimen at this locality: first, find a point on the lateral view where the shell diameter is equal to CD', suppose that the point is P3; second, find a point Y on the line OP3 so that P3Y is equal to the distance between point D' and line A'B'; finally draw a line from Y which is perpendicular to OP3 and the line intercepts the ventral edge at two points, the point which is closer to P3 along the venter is the projection of A' and B' where the shell diameter and whorl height can be measured appropriate for the whorl width A'B'. The above process is done by the Interactive Image Measurement program, the user only needs to click on the four control points (A1, B', C, D') then press the "WWD=" button in the top window. The text fields show the same results as given by the cross section : WWD = 0.27 and WWWH = 0.88. To Amnion Image Database Display Image Window Retrieve by 9S Returned: 3 Rema Taxonomv => l» lc" Figure 3-2 Coiling curve simulation and shell reconstruction Image Analytic Techniques 33 evaluate the effect of possible photographic distortion on the WWD and the WWWH values, the program has been used to process 46 specimens with both cross-sections and ventral views. The average difference between the two sources is 4.3% of the measurements from cross-sections and the differences are usually well within 10% of the measurements therefore the alternative method to derive the WWD and the WWWH from ventral views are considered reliable. The icon panel in Fig. 3-1 is designed to facilitate the input of qualitative morphological data into Amnion. It is evident from the images of the specimen that it has strong, straight and gently prorsiradiate ribs; a steep umbilical wall; a quadrate to rounded whorl section (the Ammon database allows multiple states for any character of a specimen) and a plain venter. The user clicks on the corresponding icons which the program highlights. Finally press the "Save" button in the left window and all qualitative, as well as quantitative, morphological data are put into the database without the user typing a single word or having to memorize any character states. The interactive measurement module can also be used to detect subtle changes of parameters during growth, or to reconstruct a shell from a fragment. Fig. 3-2 (left) shows that the shell expansion rate from A to B is below the average of the entire whorl since the coiling curve of the actual shell lags behind the hypothetical curve. From B to C, the shell expands rapidly to close the gap and surpass the hypothetical curve followed by a slowing down from C to D to complete the cycle. Fig. 3-2 (right) shows reconstruction of a shell from a fragment with five control points : coiling axis (O), Pj ,P2 , P3 and P4. The vast majority of morphological data of the Ammon are gathered using this interactive image measurement module. 3.4 Automatic Image Measurement To explore the possibility of a fully automatic approach, a program (Appendix 5) was written to measure shell expansion rate and rib density from lateral view images of specimens without human intervention. Other morphological features such as tuberculation and rib Image Analytic Techniques 34 furcation are ignored to make the task tractable. The morphology of ammonites has a high degree of regularity, e.g. the coiling curve usually follows a logarithmic spiral; ribs and other ornamentation occur periodically following the coiling curve. This regularity is the basis of image interpretation. The program involves six steps: 3.4.1 Preprocessing Images are cleared of irrelevant components such as text labels and remnants of other images using the program imageEdit. To focus the subsequent analyses on the ammonite in the image, the average (X) and standard deviation (S) of the background brightness intensity are estimated from a three-pixel wide margin of the image (assuming each image has a background margin around it) and the program reassigns brightness intensity value to each pixel in the 256 gray shades image: CO Z < X+S and X < 128 (black background) Z = | 256 Z > X-S and X > 128 (white background) •^Z Otherwise where Z is the brightness intensity of the pixel. 3.4.2 Edge detection The major elements in an ammonite image are coiling curve and ribs, both are edges where brightness shows significant changes. Edge detection serves to simplify the analysis of images by drastically reducing the amount of data to be processed, while at the same time preserving useful structural information about object boundaries. The Canny (from John Canny) operator was chosen for this purpose. Canny based his design on the following criteria (Canny 1986): 1. Good detection: there should be a low probability of failing to mark real edge points and a low probability of falsely marking non-edge points; 2. Good localization: the points marked as edge points by the operator should be as close as possible to the center of the true edge; 3. Only one response to a single edge; Image Analytic Techniques 35 Figure 3-3 An output from Canny operator U n e s e g m e n t h a s t h r e e p a r t s . Locate coiling axis using possible rib and coiling curve segments. orientation, length in terms of number of edge points in the segment and coordinates of these points. Before line tracing, a thinning algorithm (Pavlidis 1982) is used to skeletonize edge segments potentially wider than one pixel into one-pixel wide segments. 3.4.4 Locating coiling axis The most important feature of ammonite morphology is that ribs distribute around coiling axis radially and coiling curves follow a logarithmic spiral starting from coiling axis. Assume P is the angle made by the radius vector to any tangent to the spiral which describes how rapidly coiling curves move away from coiling axis. Lower Jurassic ammonites have P values between 75° and 90° even when there are changes during ontogeny. A statistical parameter (SC) based on this observation is used to locate the coiling axis : m n SC = ]T CoilingLen[i\ + ]T RibLen[i] i=l i=l where CoilingLenfi] is the length of the ith line segment which has an P value between 75° and 90° with respect to the hypothetical coiling axis O (Fig. 3-3); RibLenfiJ is the length of Image Analytic Techniques 36 the ith line segment with a < 15° so the line segment is in a radial position to the hypothetical coiling axis, a is calculated from the middle point of the segment (Fig. 3-3). The SC value provides a measurement of support that the hypothetical coiling axis gets from all line segments in the image using the underlying geometric pattern. Coiling axis is practically always located within a central region in the image which is half of the image size in terms of width and height. The program samples this region from left to right, top to bottom computing the SC values with an increment of 4 pixels which corresponds to 1 mm if the image scale is 1 and the monitor resolution is 100 dpi. The pixel which has the highest SC value is considered to be the location of the coiling axis. This algorithm gives very robust results. 3.4.5 Classification of coiling curves and ribs This is the most challenging part of the program since coiling curves and ribs often are broken by various kinds of noise and there may be lots of line segments resulting from local brightness changes which are not related to coiling curves and ribs (Fig. 3-3). Again the underlying geometric constraints are used to eliminate non-rib and non-coiling-curve : 1. Ribs distribute radially around coiling axis; 2. Coiling curves are nearly normal to radius vectors (p > 75°); 3. The distance between adjacent ribs should not change abruptly, otherwise there must be missing ribs or false ribs between them; 4. The length of each rib should be consistent with its neighboring ribs; 5. The "white to black" rib edges should be sandwiched by two "black to white" rib edges and vice versa; 6. Empirically, the range of shell expansion rate (W) for Lower Jurassic ammonites is between 1.2 and 5, possible coiling curve segments and geometric relations among them should meet this constraint; Generally speaking, statistical data on geometric features are more robust than individual measurements. The image is therefore divided into 12 equiangular sectors around Figure 3-$iJ- Automatic image measurement Computer classified and simulated ribs and coiling curve on original image -4 Image Analytic Techniques 38 the coiling axis. Rib and coiling curve segments are verified in each sector and then rechecked during the final assembling stage according to the above constraints. 3.4.6 Deriving morphological parameters Once the coiling axis, coiling curves and ribs are determined, shell expansion rate (W), rib density (PRHW), volution (VOLUTIONO), AH and their changes during ontogeny can easily be computed. Nonlinear regression can be used to formulate rib forms. Fig. 3-4 shows ribs and coiling curves simulated by the program superimposed on the original image; ribs were matched using the least squares technique. This program can be a handy tool to explore ontogenetic changes. A user may determine the shell expansion rate between any two points by clicking on them with the mouse. Similarly, a user may determine the rib density between any two points by clicking on them; the program will display how many ribs between the two points and how many ribs there would be for half a whorl. By working from the inner to the outer whorls, the user can get a clear picture of how the shell expansion rate and rib density change during growth. In this example (Fig. 3-4) the rib density gradually increases from 28 -> 30 ->34 -> 36 -> 44 from the visible innermost whorl to the outer whorl then start to decrease to 42->39->34 in the last half whorl. Unfortunately the accuracy demonstrated in this example cannot be achieved in most cases. It is very difficult to classify all ribs and coiling curve segments correctly and locate coiling curve accurately. 3.5 Elliptic Fourier Analysis of Whorl Shape Whorl shape is an important aspect of ammonite shell morphology. A simple descriptor in the Ammon database is the ratio of whorl width to whorl height (WWWH) which does not define the shape uniquely since a circle and a square would give the same ratio. Another descriptor WHORL_SHAPE uses descriptive terminology such as "quadrate", "rounded", "subrounded" etc, but workers do not necessarily agree on the exact meaning of a given descriptive phrase such as "subrounded" and it is difficult to compare variations across different taxonomic groups. These considerations create a need for a method like Fourier analysis which has been successfully used in many paleontological studies for the Image Analytic Techniques 39 characterization of closed curves (Kaesler and Waters, 1972; Anstey and Delmet, 1973; Christopher and Waters, 1974; Younker and Ehrlich, 1977; Canfield and Anstey 1981; Foote 1989). One commonly used Fourier method, polar Fourier analysis (Kaesler and Waters, 1972), is limited to simple curves without multiple reentrants and is therefore not considered here. The more sophisticated elliptic Fourier analysis (Kuhl and Giardina, 1982) and perimeter-based Fourier analysis (Foote 1989) were compared in a preliminary study. Experiments with whorl shape data show that the elliptical Fourier analysis gives better results, and there is also the advantage that there is no need to determine an artificial centroid for the shape. The Elliptical Fourier analysis is therefore used in the following study. Whorl shape outline is approximated by a continuous sequence of digitized points in an X-Y coordinate system. The outline can be considered to be generated by a point moving around the boundary. Suppose / is the arc length along the curve, U is the arc length at point p; L is the total perimeter length and K is the total number of points on the curve. The elliptical Fourier series are (Kuhl and Giardina, 1982): x(/) = ^o + | ] ( ^ c o s ^ + Z>„s in^ ) n=\ n2rat/ , j ^„2rmh y{l) = Co + JT {en c o s ^ + dn s i n ^ / ) where an and bn are the nth harmonic: L ^AxP Irrnlp Irmlp-u On = r~^y > [COS—=-^ - COS — J 2n2%2p?lAlp L L L ^AxP . 2n%lP • 2n%lp-u 6*=^v^ [s l ,^-sm-T-] L v^Aypr 2nnlp 2n%lP-u c"=^v^ [cos-^-cos-^ ] , L ^.Aypp . 2mdp . 2rmlp-u rf"=2^Vp?1^[sm"Ti-sm-~i^] Axp=Xp- Xp.^ Ayp = yp - yp_] p = l,2,.... K The constant components in these Fourier series are as follows: Image Analytic Techniques 40 1 K AJC ^ = - H—riil - /2 ,) + WP - lp - 0 Lp=i2AlP K Co AKP (/2P-/2P-i) + W^-^-0 2AV P where P'1 AXvP'1 7=1 A/i P - 1 Z< 7=1 P j=\ ,P~l p~l AvD P~L A/p y = i and The following normalization procedure results in Fourier descriptors which are invariant with rotation, dilation and translation of the contour and also with the starting point on the contour. The basic idea is to rotate the first harmonic phasor until it is aligned with a semi-major axis of its locus: a? bZ cos yn sin y/\ - sin yn cos yn cosn&i -sinnOi sinn0 cosnOi a„ bn _C/j Cln_ where 0] = 2nXj/L and X] is the displacement of the starting point, V}/^ is the spatial rotation angle: 6U— arctan 2 a* c* _b* d\ 2{a\b\+c\d\) 2. 2 , 2 ,2 _a\+c\-b\-d\ _ cos# sin# - sin 0 co 5 0 d\ C\ b\ di Image Analytic Techniques 41 Figure 3-5 1-, 9-, 12-, and 30- harmonic representations of a geometric shape (from Kuhl and Giardina 1982) The Fourier coefficients can be made independent of size by dividing each of the coefficients by the magnitude of the semimajor axis and independent of translation by ignoring the bias terms Ag and CQ. The first harmonic content of the size-normalized Fourier series is always characterized by af = i-0, bf* = o.o, cf = o.o, df* < 1.0. Elliptic Fourier series can be used to represent very irregular closed contours as demonstrated by Kuhl and Giardina (Fig. 3-5). Whorl shape drawings are scanned into the computer from published work. A thinning algorithm (Pavlidis 1982) is used to skeletonize outline parts potentially wider than one pixel and a contour tracing program (as used in section 3.4) links separate pixels into a continuous outline ready for analysis. Fig. 3-6 shows the ontogenetic variations of Arnioceras ceratitoides. the number of Image Analytic Techniques 42 WHORL SHAPE FOURIER REP ONTOGENY 1 2 3 4 5 Figure 3-6 Ontogenetic change in whorl shape for Arnioceras ceratitoides Image Analytic Techniques 43 -+• ONTOGENY ONTOGENY Figure 3-7 Computer generated hypothe-tical sequence from interpolation of whorl 1 and 9 in Fig. 3-6. Figure 3-8 Computer generated hypo--thetical sequence from extrapolation of whorl 6 and 7 in Fig. 3-6. From top to bottom, numbers of harmonic used in the Fourier series are: 4, 3, 4, 5, 6, 6, 8, 15, 23 (root mean square error < 0.01) harmonics required to reduce root mean square error to 0.01 or less increases with ontogeny. This is consistent with the visual observation of the general increase in whorl shape complexity. The most significant change occurs from whorl 7 to 8 where the number of harmonics increases from 8 to 15 which corresponds to the development of a keel. One of the principal advantages of Fourier analysis is that it allows the construction of intermediate whorl shapes and extensions, or reductions, of morphologic trends beyond the forms available. If the first whorl in Fig. 3-6 is allowed to evenly evolve (in terms of Fourier coefficients) into the last whorl, it produces a hypothetical sequence of whorl shapes which is different from the real sequence (Fig. 3-7). Fig. 3-8 (right) shows an extrapolation sequence of whorl 6 to 7. A program (Appendix 7) has been written to visualize and animate the detail Image Analytic Techniques 44 of how one whorl shape can gradually evolve into another. All shapes in the sequence are normalized and later whorls are superimposed on the earlier whorls so that subtle change in shape can be detected. These examples demonstrate the potential value of elliptic Fourier analysis in morphologic simulation. In addition, Fourier analysis can detect and quantify whorl shape variations within and among taxa. Ontogeny can be directly compared with phylogeny to gain insight into heterochrony. It would be interesting to map the whorl shape distribution of naturally occurring ammonites with respect to their Fourier representations so the relative density of occurrence can be evaluated, perhaps shedding light on functional factors governing whorl shape. Finally, current models of 3-D simulation of ammonites shells all assume a circular or ellipsoid whorl section. Fourier representation of whorl sections make it possible to model real ammonites. All these are open areas for future research. Morphological Variation and Covariation 45 Chapter 4 Morphological Variation and Covariation 4.1 Introduction The diverse shell morphologies of ammonites have promoted much speculation on relationships between shell form and function, shell geometry and taxon duration. In this chapter the Ammon database is used to analyze Lower Jurassic ammonites in terms of shell morphology, possible correlation between taxon longevity and its morphological variability. In addition to documenting the range and diversity of ammonite morphology, I hope to demonstrate the existence of patterns of shell morphology that are independent of taxonomy at the superfamily level. This concerns possible functional relationships between morphological variables. It is well known that the information in paleontological databases is incomplete (Raup 1991): only a fraction of the taxa that ever lived have been sampled, new fossil material is being collected all the time and taxa are subject to revision with new discoveries. Despite many potential sources of error, Sepkoski (1993) demonstrated that errors and changes in paleontological databases are not necessarily impediments to statistical analysis so long as the data are sufficiently numerous. 4.2 Lower Jurassic Ammonite Shell Morphology 4.2.1 Background As is shown in one outstanding paper by Raup (1967), the basic geometry of planispiral ammonites can be described by three parameters: W (whorl expansion rate), U (umbilical ratio), WWWH (shape of the whorl). Plots of W, U and WWWH can be used effectively to map the distribution of basic shell geometry. Raup (1967) showed that ammonoids occupy only a portion of the theoretical range of possibilities for shell geometry, and that some geometric combinations have been utilized more than others. Raup's approach was subsequently used by Ward (1980) to compare the shell geometry of Jurassic and Morphological Variation and Covariation 46 Cretaceous ammonoids to Mesozoic and Cenozoic nautiloids. Chamberlain (1981) went further and related ammonoid and nautiloid shell geometry to hydrodynamic efficiency by showing that species with coiled shells cluster on adaptive peaks that optimize streamlining and stability. More recently, Saunders and Swan (1984,1987) have used this approach to analyze the morphologic diversity of mid-Carboniferous ammonoids. These studies demonstrated the usefulness of Raup's approach in evaluating and graphically portraying the distribution of ammonoid shell geometry. By design, the studies of Raup, Ward, and Chamberlain were generalized in their approach; this was necessary in order to assemble the amount of data required for the types of analyses undertaken. However, geometric analysis at the taxonomic level of genus and stratigraphic level of period, while acceptable for a preliminary survey, is increasingly regarded as being too coarse-grained to resolve many critical questions. Database Ammon makes it possible to work at the species and zonal levels. As a result of more detailed analysis, some of Raup's conclusions, particularly concerning geometric trends through time and ontogenetic variations are now subject to revision. 4.2.2 The Sample of Observations The data used in this study comprise observations made on 6784 specimens, representing 15 families, 179 genera, and 1319 species. This comprises virtually complete coverage for the ammonite genera known to occur in the Lower Jurassic as catalogued by Donovan, Callomon, and Howarth (1981). All species are represented in the sample by averaging the measurements made on specimens with shell diameters (D) larger than 4 cm. This reduces the impact of ontogenetic change on the data since most Lower Jurassic ammonite species that undergo such change do so early in ontogeny. Selected analyses at D > 8 cm show no appreciable differences from analyses conducted at D > 4 cm. Ontogenetic change will be considered as a separate problem with appropriate biometrical data in section 4.5. Variations between each species are also calculated which show that morphological variations between species are much higher than within species, for basic shell geometry even though intraspecific variations are widespread (Table 4-1). Morphological Variation and Covariation Table 4-1 Between species variance and within species variance Parameter U W WWWH Mean 0.4192 2.0231 0.8822 Between Species Variance BSV (Num. of Species) 0.015502(1251) 0.106973 (1248) 0.082893 (1045) Within Species Variance WSV (Num. of Species) 0.000915 (817) 0.015257(670) 0.009702 (639) F-BSV /WSV 16.99 7.01 8.53 Ftest cc=0.01 1.32 4.2.3 Basic Shell Geometry The W, U, and WWWH data for the whole sample have been plotted as scatter diagrams with one point for each species. The density of points in the scatter has been contoured and the results shown in Fig. 4-1, where successively higher contours indicate increase in points per unit area on the plot. The shell geometry of these ammonites is restricted to the low W and high U region of the morphological spectrum with the greater portion clustering in the vicinity of W=1.9, U=0.45, which coincides with one of the two peaks of hydrodynamic efficiency determined by Chamberlain (1981). Fig. 4-2 shows that WWWH is strongly correlated with W; as W increases, WWWH decreases. Figures 4-3, 4-4, 4-5 show the standard deviation contours of W, U, and WWWH with respect to W and U, which serve as "error bars" for Fig. 4-1 and Fig. 4-2, only species with at least 6 occurrences in the database are used, the number is chosen somewhat arbitrarily, any fewer than this seems to me to be too small a number for calculating standard deviation for a species. The curved line shown in these figures follows the equation W=l/U which marks the point of minimal whorl contact. The density contour and WWWH contour are strikingly similar to those for Mesozoic ammonoids in general being largely concentrated on a small portion of the theoretical range of possibilities for shell geometry (Fig. 4-6) and suggesting the same geometrical restraints. For example, high values of U tend to be associated with low W and high WWWH, which forms an important part of Buckman's Law of Covariation. Morphological Variation and Covariation 48 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 " I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I L 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-1 Density diagram with respect to W and U (whole sample) 1.20 1.37 1.54 1.71 1.89 2.06 2.23 2.40 2,57 2.74 2.91 3.09 3.26 3.43 3.60 3.77 3.94 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I |_ 1.20 1.37 1.54 1.71 1.89 2.06 2.23 2.40 2.57 2.74 2.91 3.09 3.26 3.43 3.60 3.77 3.94 W Figure 4-2 WWWH contour with respect to W and U (whole sample) Morphological Variation and Covariation 49 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 0.00 I I I l I I I I I l I I I I I I I I I I I I I I I I I I I 0.00 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 W Figure 4-3 Standard deviation contours of W with respect to W and U (964 species) 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 I I I I I I I I I 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 W Figure 4-4 Standard deviation contour of U with respect to W and U (964 species) Morphological Variation and Covariation 50 1 0.83 0.77 0.70 0.64 0.57 0.51 0.45 Z> 0.38 0.32 0.26 0.19 0.13 0.06 .20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 0.00 .20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 W Figure 4-5 Standard deviation contour of WWWH with respect to W and U (780 species) 0.00 4.00 ^ 3 * } ^ ^ 5 ^ b N V v $N \ ^ s f J Figure 4-6 W and U density topography (whole sample) Morphological Variation and Covariation 51 4.2.4 An interpretation of Buckman's Law of Covariation Swan and Saunders (1987) made the important observation that the covariation among W, U, and WWWH may be related to restrictions imposed by the shape and relative size of the whorl. If AH is the ratio of the internal cross sectional height of the whorl (IH) to the external height of the whorl (EH) and W <= 1/U (Fig. 4-7 , inset) then: AH=(1-1/W)/(1-U) (1) When the family of curves for successive values of AH is superimposed on the W-U scatter plot, there appears to be a relationship (Fig. 4-7). The actually occurring combinations of W and U appear to be concentrated on AH of between 0.7 and 1, whereas the preferred AH for mid-Carboniferous ammonoids is between 0.5 and 0.7. Swan and Saunders (1987) stated 0.1 0.2 0.3 0.4 0.5 O.G 0.7 0.8 0.9 U 1.5 2 .0 2 .5 3 .0 3 .5 4 .0 4.5 W Figure 4-7 Family of curves for AH in terms of W and U Morphological Variation and Covariation 52 "In terms of function, we speculate that the distinctly U-shaped cross sections that result from low AH values might prohibit the deployment of strong propulsive musculature, and might even restrict ingestion. It is not so obvious why high AH values should have been unfavorable". In contrast, high AH values are popular among Lower Jurassic ammonites. From equation (1) above, it is apparent that as expansion rate (W) increases, U has to decrease if AH is to remain relatively constant as is observed in the Carboniferous and Jurassic samples. Furthermore, if AA is the cross sectional area of the whorl, as a first order approximation that does not consider the overlap area between two successive whorls, then for unit shell radius: AA=K*WWWH*(1-U)2 (2) (1 cross section is rectangular or quadrate 7i/4 cross section is circular (Swan and Saunders 1987 equation) rc/4 cross section is elliptic 1/2 cross section is triangular In real world ammonites, both rectangular and triangular whorl sections have some degree of rounding, the actual range for constant K is somewhere between 0.6 and 0.9 instead of 0.5 and 1, and the most common forms have K values around 7t/4. Assuming K=7t/4, the family of curves for equation (2) in terms of WWWH and U again shows a parallelism with the distribution of Lower Jurassic ammonite data. Fig. 4-8 illustrates a preference for AA values between 0.1 and 0.3 whereas the preferred AA for mid-Carboniferous ammonoids is between 0.5 and 0.7 (Swan and Saunders 1987). From equations (1) and (2), one can infer that, as expansion rate (W) increases, U decreases in order to keep AA constant and consequently WWWH decreases. This explains the previously observed pattern that shells with higher expansion rates tend to be more involute and compressed, and involute shells with low expansion rates tend to be depressed. I can demonstrate the negative correlation between U and WWWH holds, even if the overlap area between two successive whorls is considered. Morphological Variation and Covariation 53 0.1 0.2 0.3 0.4 0.5 0.G 0.7 0.8 0.9 U 1.6v WWWH Figure 4-8 Family of curves for AA in terms of WWWH and U 1. If the whorl cross section is rectangular or quadrate, then for unit shell radius: AA=WWWH*(1-U)*(1-U-(1/W-U)/W) (3) Let F(U)=(1-U-(1/W-U)/W) (4) Combining Eqs (1) and (4), we have F(U)=(AH-AH2)*U2+(2*AH2-3*AH)*U+2*AH-AH2 whose derivative is F'(U)=2*(AH-AH2)*U+2*AH2-3*AH Since U<1, F'(U)<-AH Morphological Variation and Covariation 54 I—WW — WH I AA 1 T l wh 1 f U _ _ r=1 I I u I ( 1 h Figure 4-9 Cross section with unit shell radius, so u equals to U of Amnion, WWWH = WW / WH W = WH /wh and AH is always positive, therefore F'(U)<0 The derivative is negative, so the function F(U) decreases as U increases, Finally, because AA=WWWH*(1-U)*F(U) I conclude as U increases , WWWH decreases in order to keep AA constant. 2. If cross section is triangular, then for unit shell radius: AA=0.5*WWWH*((1-U)2-(1/W-U)2) (5) Let F(U)=(1-U)2-(1/W-U)2 (6) Combining Eqs (1) and (6), we have F(U)=(2*AH-AH2)*U2+(2*AH2-4*AH)*U+2*AH-AH2 whose derivative is F'(U)=2*(2*AH-AH2)*U+2*AH2-4*AH Since U<1, F'(U)<0 The derivative is negative, so the function F(U) decreases as U increases, Finally, because AA=0.5*WWWH*F(U) I conclude as U increases , WWWH decreases in order to keep AA constant. 3. Other shapes: since the vast majority of whorl shapes stand between the two extremes, that is between triangular and rectangular shapes, we can reasonably expect the negative correlation between U and WWWH would also hold for them. 4.2.5 Morphological Variability and Taxon Longevity The relative durations of taxa and the possible correlation between morphology and duration are intriguing puzzles of evolution (Ward 1983). The standard deviation contours of W, U, and WWWH (Figs. 4-3, 4-4, 4-5 respectively) not only serve as the "error bars" of Fig. Morphological Variation and Covariation 55 4-1 and Fig. 4-2, but also show the morphological variability of species at the corresponding location in the morph space. The magnitude of the standard deviation is at least in part controlled by the magnitude of the mean value; to facilitate the comparison of morphological variability between different species, the direct influence by the magnitude of the mean value is eliminated by calculating the coefficient of variation (Cy) where Cy = standard deviation * 100% / average It is evident from Figs. 4-10, 4-11, 4-12 that the coefficients of variation for W, U, and WWWH show the same pattern of changes (only species with at least 6 occurrences and stratigraphic information are used); small Cy values are associated with the most densely populated region of low W and high U. Moving away from this adaptive peak to less densely populated regions of high W and low U, the coefficients of variation gradually increase, which may indicate that less selective pressure is being applied in these adaptive "lowlands". Jurassic ammonites are commonly regarded as excellent index fossils that offer fine time resolution. To examine whether there is a correlation between basic shell geometry and taxa duration, the range data of Lower Jurassic ammonite species and genera have been assembled. Table 5-1 presents the well-established northwest European zonation scheme used as the primary standard in this study; the Lower Jurassic is divided into 4 stages and 20 zones. In the discussion that follows concerning the duration of taxa in units of zones, the following points should be borne in mind: (1) In constructing time scales, absolute ages are established for points within sequences and encompassed zones are assumed to be equal in duration for interpolation purpose (Palmer et al 1983; Harland et al 1989). (2) If a taxon is found within a zone, it is assumed to range throughout the zone which may inflate the range of some taxa. (3) Attention is confined to taxa whose range can be resolved to the zonal level and that are well represented in the database (arbitrarily by at least 6 occurrences). Morphological Variation and Covariation 56 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 0.83 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I 0.83 0.77 0.70 0.64 0.57 0.51 0.45. 0.38 0.32 0.26 0.19 0.13 0.06 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 w Figure 4-10 The coefficient of variation contours for W 728 species, contour interval = 0.07 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 0.00 Figure 4-11 The coefficient of variation contours for U 728 species, contour interval = 0.03 Morphological Variation and Covariation 57 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 0.83 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I 0.83 0.77 0.70 0.64 0.57 0.51 0.45 0.38 0.32 0.26 0.19 0.13 0.06 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 W Figure 4-12 The coefficient of variation contours for WWWH 728 species, contour interval = 0.015 0.00 3.78 4.00 The duration contour for the same species as in Fig. 4-10 (Fig. 4-13) shows resemblances to the coefficient of variation contour plots (Figs. 4-10, 4-11, 4-12). Ammonites occupying the adaptive peak have low within-population variability and short duration. Away from this peak in faster expanding regions, there is a steady increase in both morphological variability and taxa longevity implying a decrease selective pressure. Patterns at the generic level need not be identical to those at the species level, since long-lived genera, for example, could include many short-lived species. Fig. 4-14 shows the duration contour for 117 genera to whom the above 964 species belong, which is very similar to the one for the species. This result suggests that generic and species longevities of Lower Jurassic were related to their morphology. One possibility is that the correlation between taxa duration and geometric variability could be the result of unequal taxonomic splitting. The concept that taxonomy and ranges are influenced by complexity of hard-part morphology was advocated Morphological Variation and Covariation 58 by Schopf et al. (1975) who suggested that a fossil with a great deal of describable morphology will normally show a shorter range than a nondescript form because evolutionary change in the nondescript taxon will have less chance of being recognized. Following this reasoning, the least ornamented ammonites should have longer durations. It is interesting to see whether the above observed correlation holds once the influence of ornamentation is eliminated. Subsamples for both species and genera with smooth shells or weak ornamentation were extracted from the whole sample. Figs. 4-15, 4-16 show their duration contours and it is clear that both figures still reflect the trends seen in Figs. 4-13, 4-14. The analysis presented here is primitive, and the conclusion that taxa duration may be related to morphological variability within the population through selective pressure is tentative. To be more confident with this conclusion, a more refined time scale calibration, a better correlation between different ammonite zonation schemes, and more specimens for under-represented species are needed. 1.20 1.43 1.67 1.90 2.13 2.37 2.60 2.83 3.07 3.30 3.53 3.77 4.00 0.83 0.76 0.69 0.62 0.55 0.48 Z) 0.42 0.35 0.28 0.21 0.14 0.07 0.00 1.20 1.43 1.67 1.90 2.13 2.37 2.60 2.83 3.07 3.30 3.53 3.77 4.00 W Figure 4-13 Contours of species duration in units of zones, 728 species, contour interval = 0.04 J I I 1 I I I L I I I J L I I I n nn Morphological Variation and Covariation 59 1.20 1.43 1.67 1.90 2.13 2.37 2.60 2.83 3.07 3.30 3.53 3.77 4.00 , 0 0 I I I I I I I I I I I I I I I I I I I I I I I l_J 0 0 0 1.20 1.43 1.67 1.90 2.13 2.37 2.60 2.83 3.07 3.30 3.53 3.77 4.00 ' W Figure 4-14 Contours of genus duration in units of zones, 117 genera, contour interval = 0.2 1.20 1.39 1.59 1.78 1.97 2.17 2.36 2.55 2.74 2.94 3.13 3.32 3.52 3.71 3.90 1.20 1.39 1.59 1.78 1.97 2.17 2.36 2.55 2.74 2.94 3.13 3.32 3.52 3.71 3.90 W Figure 4-15 Contours of species duration in units of zones for species with weak ornamentation, 258 species, contour interval = 0.06 Morphological Variation and Covariation 60 1.20 1.42 1.63 1.85 2.06 2.28 2.49 2.71 2.92 3.14 3.35 3.57 3.78 4.00 ' w Figure 4-16 Contours of genus duration in units of zones for genera with weak ornamentation, 53 genera, contour interval = 0.15 4.2.6 Correlation between basic shell geometry and other morphological features The analysis thus far has considered only the essentials of overall form and has ignored ornamentation and ventral features. In the following analyses I explore the correlation between basic geometry (W and U) and 10 variables characterizing ornamentation and ventral features. The most significant correlations with shell geometry involve tubercles, rib-furcation, rib strength and the presence of a keel. The first attempt is related to shell ornamentation, and particularly to the development of tubercles. Three subsamples were extracted from the total sample. Fig. 4-17 shows the W-U distribution of ammonites with tubercles on the upper flank, Fig. 4-18 shows the W-U distribution of ammonites with tubercles on the lower flank, neither of which differ substantially from the distribution for the whole sample (Fig. 4-1) except for the general absence of tuberculate forms in the low U region. Fig. 4-19 showing the W-U distribution of Morphological Variation and Covariation 61 ammonites with two rows of tubercles is more or less a combination of Fig. 4-17 and Fig. 4-18. Figs. 4-20, 4-21, 4-22 show the W-U distributions of ammonites with simple ribs, ribs furcated on upper flank, and ribs furcated on lower flank respectively. The W-U distribution of ammonites with simple ribs is similar to the distribution for the whole sample (Fig. 4-1), whereas ammonites with ribs furcated on upper flank concentrate on the low W and high U region, and ammonites with ribs furcated on lower flank tend to be more involute and have higher expansion rates. Similar analysis of subsamples was made in relation to the coarseness of ribs. Three subsamples were extracted from the total sample. Figs. 4-23, 4-24, 4-25 show the W-U distribution of ammonites with weak ribs, average ribs, and strong ribs respectively. Ammonites with weak ribs show more diversity in terms of basic shell morphology, as the rib strength increases, the shells tend to be more and more restricted to Chamberlain's (1981) low Cf3 peak region with high hydrodynamic efficiency. It is difficult to explain, 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 - l 0.80 0.73 0.66 H 0.58 0.51 - 0.44 0.37 0.29 0.22 0.15 0.07 0.00 O.00 • I I I I i i i i i i i i i i i i i i i i i M i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i r 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-17 Density diagram for ammonites with tubercles on upper flank (208 species) Morphological Variation and Covariation 62 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 J I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I l I I l l l I I I I I I I l l l l l l l l -I I l l l l I I l l I I I I I I I I I I I I I I I I I I I I I I I I 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-18 Density diagram for ammonites with tubercles on lower flank (64 species) 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I D 'I l l l I I I l l l I l l I l l l l l l l l I l I I I I l l l l I I I i-1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-19 Density diagram for ammonites with two rows of tubercles (74 species) 0.00 Morphological Variation and Covariation 63 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I 1 I I I I I I I I I I I I I I I I I I I I I I I I I I I M I I I I I I l l 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-20 Density diagram for ammonites with simple ribs (784 species) 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I L ' l l M I I I I I l I I I I l l I I I I I I I I I I I I I I I I I I I I I I I r 0.80 0.73 0.66 0.58 0.51 0.44 0.37 0.29 0.22 0.15 0.07 0.00 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-21 Density diagram for ammonites with ribs furcated on upper flank (150 species) Morphological Variation and Covariation 64 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-22 Density diagram for ammonites with ribs furcated on lower flank (178 species) 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 J I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I ~i i i i M i i i r I T M / 1 I I / T T T I i i i i i i i i i i i i t i i i i i i i i 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-23 Density diagram for ammonites with weak ribs ( 278 species) 0.00 Morphological Variation and Covariation 65 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I i i i i i i t i i M i i i i i i i i i i i i i i i i i i i i i i i r 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-24 Density diagram for ammonites with average ribs (701 species) 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I. 0 0 0 i : 11 i i i i 11 M i i i i i i i i i i i i i i i i r 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 w Figure 4-25 Density diagram for ammonites with strong ribs, X marks low Cj> peak of Chamberlain (1981), 351 species 0.80 0.73 0.66 0.58 0.51 0.44 0.37 0.29 0.22 0.15 0.07 0.00 Morphological Variation and Covariation 66 considering ammonites with strong ornamentation are generally regarded as poor swimmers (Swan and Saunders 1987). One possibility is that if ribs are coarse for reasons not connected with hydrodynamic efficiency, then it makes sense to offset their detrimental impact on the drag coefficient by adopting the most hydrodynamically efficient shell geometry Since Chamberlain's Cj) contour map was based on shells having circular whorl cross sections (WWWH=1), I used a subsample of specimens with 0.89<=WWWH<=1.11. Fig. 4-26 shows the same phenomenon, namely that shell forms with the coarsest ribs are concentrated around the low CQ peak region. A similar analysis of subsample was made in relation to the presence or absence of a well-defined keel on the venter. Fig. 4-27 shows ammonites with a plain venter are most abundant in the low W and low U region. Fig. 4-28 shows ammonites with a keel are more evenly distributed. Morphological Variation and Covariation 67 Rib Width < 0.1 0.1 <= Rib Width < 0.2 u 0.8 0.7 O.G 0.5 0.4 0.3 0.2 i.S 2.0 2.5 3.0 3.5 4.0 4.5 W U 0.8 0.7 O.S 0.5 0.4 0.3 0.2 0.1 1.5 2.0 2.5 3.0 3.5 4.0 4.5 W 0.2 <= Rib Width < 0.3 Rib Width >= 0.3 u **• 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0.3 0.2 0.1 1.5 2.0 2.5 3.0 3.5 4.0 4.5 W 1.5 2.0 2.5 3.0 3.5 4.0 4.5 W Figure 4-26 W and U distribution with respect to rib width X marks low C D peak of Chamberlain (1981) Morphological Variation and Covariation 68 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 ' 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-27 Density diagram for ammonites with plain venter (409 species) 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 0.00 I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I LI •i i i i i i i i i 1 1 ; i M i / 1 1 1 i i i i i i i i i i i i i i i i i i i i i i i i i r 0.07 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 4-28 Density diagram for ammonites with carinate venter (540 species) 0.00 Morphological Variation and Covariation 69 4.3 Covariation 4.3.1 Introduction Westermann (1966) has observed that several ammonite stocks show a persistent intercorrelation of morphological features: more involute and compressed forms are less ornate than more evolute and inflated forms. Such a correlation was probably first recognized by Buckman (1892) and was named 'Buckman's Law of Covariation1 by Westermann (1966). Buckman (1892) identified 69 new species from a single bed of the Sowerbyi Zone in the Bajocian (Middle Jurassic) of Dorset, England. Based on covariation and morphologic intergradation, Westermann was able to group 64 of Buckman's species into a single palaeospecies. Subsequently, similar phenomena have been widely documented, for example, by Bayer and McGhee (1984), and Kennedy and Cobban (1976), who cited examples of intra-specific variation in Cretaceous ammonites. In Jurassic ammonites the superfamily has long been used as the principal high level taxon (Donovan, Callomon, and Howarth 1981). There are three superfamilies in the Lower Jurassic. The oldest is the Psilocerataceae which appears at the base of Jurassic and is of uncertain origin. The Eoderocerataceae appears four zones later than the Psilocerataceae and ranges four zones higher. The Hildocerataceae arises from the Eoderocerataceae in the lowest Pliensbachian and persists into the Middle Jurassic where it gives rise to all other Jurassic ammonites (Fig. 4-29). In the following sections, I will try to demonstrate that Buckman's Law of Covariation applies equally well to the three superfamilies of Lower Jurassic ammonites and in so doing, give a more rigorous demonstration of Buckman's Law than has been previously possible. I will then go on to explore other patterns of covariation. To focus on functional rather than phylogenetic constraints, I will test the patterns for each of the three superfamilies independently. To avoid bias by some frequently represented species in the Morphological Variation and Covariation 70 Lower Jurassic Psilocerataceae 3 Eoderocerataceae Hildocerataceae Middle Jurassic Haplocerataceae Spirocerataceae Stephanocerataceae X Perisphinctaceae Figure 4-29 Ranges and possible phylogenetic relationships of ammonite superfamilies in the Lower-Middle Jurassic (after Donovan, Callomon and Howarth 1981) database, species rather than specimens serve as the basic calculation unit. To incorporate the morphological variation during ontogeny, a species might be represented more than once. For example, the species Haugiajugosa shows strong variation during ontogeny and has four entries in the database: entry 1 2 3 4 W 2.62 2.18 1.87 1.64 V 0.59 0.47 0.43 0.36 Diameter 4.71 15.47 23.60 31.73 When studying how the V values are related to W values, the data are divided into three groups with W <1.8 (group 1), 1.8 <=W< 2.2 (group 2), and W >=2.2 (group 3). Entry 1 falls into group 3 with a V value of 0.59; entries 2 and 3 fall into group 2 with an average V value of 0.45; and entry 4 falls into group 1 with a V value of 0.36 so there are three data points for Haugiajugosa in the covariation analysis. For quantitative morphological parameters, the data are plotted as 3-D bar diagrams. Morphological Variation and Covariation 71 Table 4-2 Abbreviations for statistical and morphological terms M -- Mean Sig. - Significance Level, T Test PRHW — Primary Rib Density per half whorl RW - Ratio of Maximum Rib Width to Whorl Height WWWH -- Ratio of Whorl Width to Whorl Height V — Percentage of Interior Whorl being Overlapped S — Standard Deviation F — Frequency N — Number of Species RF - Rib Form D - Shell Diameter WWD - Ratio of Whorl Width to D difference between two means is relatively small comparing with the standard deviations yet the means are significantly different due to large number of specimens used in the calculation 4.3.2 Buckman's Law (1) Shells with higher expansion rate (W) tend to be more involute (V). Superfamil y w\v <1.8 1.8-2.2 >2.2 Psilocerataceae M 0.173 0.334 0.578 S 0.126 0.220 0.239 N 152 163 95 Sig. 0.001 0.001 Eoderocerataceae M 0.172 0.218 0.436 S 0.105 0.136 0.222 N 145 208 71 Sig. 0.001 0.001 Hildocerataceae M 0.281 0.353 0.449 S 0.134 0.173 0.193 N 77 321 217 Sig. 0.001 0.001 0.6 0.5 0.4 0.3 0.2 0.1 /—7| •—71 y :v::: Psilocerataceae Eoderoceratace ae W Hildoceratacea e • <1.8 D1.8-2.2 • >2.2 This covariation can be explained by equation (1) in section 4.2, that is, the restrictions imposed by the ratio of the interior height of the whorl (IH) to the exterior height of the whorl (EH). (2) Involute shells are more compressed than evolute shells. Morphological Variation and Covariation 72 (2) Involute shells are more compressed than evolute shells. Superfamily VYWWWH <0.3 0.3-0.6 >0.6 Psilocerataceae M 0.975 0.860 0.661 S 0.183 0.218 0.370 N 123 86 53 Sig. 0.001 0.001 Eoderocerataceae M 1.091 1.038 0.967 S 0.293 0.401 0.379 N 217 100 33 Sig. 0.09 0.10 Hildocerataceae M 0.816 0.731 0.649 S 0.154 0.2 0.190 N 183 206 91 Sig. 0.001 0.001 WWWH Psilocerataceae Eoderocerataceae Hildocerataceae V • <0.3 M 0.3-0.6 • >0.6 This covariation can be explained by equation (2) in section 4.2, that is, the restrictions imposed by the relative cross sectional area of the whorl (AA). (3) Compressed shells have finer ribs. Superfamily WWWHXRW <0.8 0.8-1.3 >1.3 Psilocerataceae M 0.144 0.184 0.253 S 0.059 0.057 0.057 N 79 152 13 Sig-0.001 0.001 Eoderocerataceae M 0.171 0.191 0.195 S 0.056 0.067 0.073 N 92 216 104 Sig. 0.005 0.15 Hildocerataceae M 0.133 0.182 0.228 S 0.047 0.048 0.076 N 271 165 7 Sig. 0.001 0.001 0.26,^ 0.24 0.22 0.2 RW 0.18 0.16 0.14 0 . ^ 0.1 • <0.8 H 0.8-1.3 • >1.3 Psilocerataceae Eoderocerataceae Hildocerataceae WWWH Morphological Variation and Covariation 73 w o a* 0 0.4 0.6 I I I Figure 4-30 Variation in the ratio between internal shell volume and volume of shell material, as a function of W and U assuming a shell thickness equal to 0.0772 of the radius of the generating curve(From Raup 1967). Buoyancy control and carbonate efficiency may have played major roles here. Assume (1) a circular generating curve and (2) no variation in relative shell thickness during ontogeny, Fig. 4-30 shows the distribution of the ratio: internal volume/volume of shell material with respect to W and U (Raup 1967). The buoyancy and relative secretion efficiency of the shell as measured by this ratio decrease toward the region of high W and low U. In a real example, Swan and Saunders (1987) measured the shell thickness on 129 whorl sections from 49 Middle Carboniferous ammonoid specimens and showed that there is an inverse relationship between W and shell thickness: forms with higher W tend to have thinner shells. Three possibilities arise: (a) weak ornamentation could minimize the loss of buoyancy due to the rapidly expanding shell. Fig. 4-22 and 24 in the preceding section also support this reasoning, since ammonites with strong ornamentation are restricted to the low W region whereas ammonites with weak ornamentation could have either slow or fast expanding shells; (b) it may be that shells with high W simply could not afford extra shell ornamentation due to the low carbonate efficiency; (c) weak ornamentation gives compressed and fast expanding shells Morphological Variation and Covariation 74 better streamlining which may lessen the role of the shell as a protective device. No matter which of these interpretations is correct, covariations (1) and (2) can lead to (3). (4) Conversely from (3), shells with weak ribs are more compressed. Superfamily Rib\WWWH weak medium strong Psilocerataceae M 0.757 0.854 0.976 S 0.253 0.288 0.219 N 45 139 56 Sig. 0.02 0.002 Eoderocerataceae M 0.843 1.005 1.178 S 0.215 0.311 0.307 N 28 150 188 Sig-0.004 0.001 Hildocerataceae M 0.683 0.739 0.882 S 0.166 0.201 0.160 N 121 215 106 Sig. 0.004 0.001 WWWH • weak • medium • strong Psilocerataceae Eoderocerataceae Hildocerataceae Ribs 4.3.3 Volution (1) Shells with sinuous ribs are more involute than shells with straight ribs. Superfamily Rib FormW straight sinuous Psilocerataceae M 0.277 0.618 S 0.209 0.231 N 176 20 Sig-0.001 Eoderocerataceae M 0.233 0.450 S 0.170 0.117 N 279 15 Sig. 0.001 Hildocerataceae M 0.275 0.373 S 0.161 0.177 N 105 231 Sig. 0.001 0.7 0.6 0.5 0.4 0.3 0.2 0.1 dJ • straight • sinuous Psilocerataceae Eoderocerataceae Hildocerataceae Rib Form Morphological Variation and Covariation 75 From (1) and Buckman's law, we can infer: (2) Shells with sinuous ribs are more compressed than shells with straight ribs. Superfamily Rib\WWWH straight sinuous Psilocerataceae M 0.938 0.606 S 0.253 0.134 N 137 13 Sig. 0.001 Eoderocerataceae M 1.137 0.692 S 0.300 0.095 N 289 17 Sig. 0.001 Hildocerataceae M 0.935 0.754 S 0.246 0.154 N 93 169 Sig. 0.001 WWWH 1.2 1.H 1 0.9 0.8 0.7|. 0.6 0.51*4 _ NO • straight • sinuous Psilocerataceae Eoderocerataceae Hildocerataceae Rib Form From (1) and Buckman's law, we can also infer: (3) Straight ribs tend to be coarser than sinuous ribs. Superfamily RFXRW straight sinuous Psilocerataceae M 0.188 0.1 S 0.061 0.042 N 207 22 Sig. 0.001 Eoderocerataceae M 0.188 0.151 S 0.068 0.056 N 325 19 Sig 0.1 Hildocerataceae M 0.179 0.156 S 0.053 0.047 N 127 240 Sig-0.001 0.19 RW • straight • sinuous Psilocerataceae Eoderocerataceae Hildocerataceae Rib Form (4) Shells with tubercles on the upper flank tend to be more evolute than shells with tubercles on the lower flank. Morphological Variation and Covariation 76 Superfamily TubercW upper flank lower flank Psilocerataceae M 0.226 0.401 S 0.162 0.149 N 29 4 Sig. 0.025 Eoderocerataceae M 0.187 0.331 S 0.110 0.175 N 152 7 Sig. 0.001 Hildocerataceae M 0.156 0.368 S 0.102 0.169 N 12 60 Sig. 0.001 0.45 0.4 0.35 . 0.3 . 0.25 0.2 0.15 0.1 0.05 D upper flank • lower flank Psilocerataceae Eoderocerataceae Hildocerataceae Tuberc Position (5) Shells tend to be more involute as whorl shape changes from quadrate, rectangular->rounded->ellipsoid->oval,ogival->triangular. Superfamily WhorlW quadrate rounded ellipsoid oval ogival triangular Psilocerataceae M 0.186 0.227 0.299 0.436 0.618 0.794 S 0.137 0.167 0.225 0.214 0.251 0.166 N 52 73 79 39 20 18 Sig. 0.07 0.01 0.001 0.003 0.008 Eoderocerataceae M 0.184 0.214 0.240 0.308 0.350 0.588 S 0.131 0.165 0.169 0.169 0.166 0.150 N 96 71 117 26 36 7 Sig. 0.09 0.12 0.03 0.13 0.001 lildocerataceae M 0.306 0.312 0.324 0.442 0.457 0.651 S 0.133 0.151 0.163 0.215 0.182 0.165 N 152 22 127 75 131 27 Sig. No No 0.001 0.2 0.001 Morphological Variation and Covariation 77 H i l d o c e r a t a c e a e P s i l o c e r a t a c e a e E o d e r o c e r a t a c e a e o v a l tr ia n g u l a r o g i v a l r o u n d e d e l l i p s o i d q u a d r a te 4.3.4 Whorl Shape (1) Tuberculate shells are more depressed than nontuberculate shells. Superfamily Tub\WWWH with without Psilocerataceae M 1.003 0.849 S 0.29 0.246 N 29 242 sig. 0.001 Eoderocerataceae M 1.125 0.954 S 0.309 0.303 N 226 136 Sig. 0.001 Hildocerataceae M 0.816 0.742 S 0.17 0.203 N 60 355 Sig. 0.004 WWWH 1 . 2 , / 1.1 1 0.9 0.8 0.7 0.6 -0.5Ud • with B without Psilocerataceae Eoderocerataceae Hildocerataceae with or without tubercles (2) Conversely the frequency of shells without tubercles is higher in highly compressed forms (WWWH<0.7). Superfamily WWWH\F% WWWH>0.7 WWWH < 0.7 Psilocerataceae M 89.74 94.93 N 302 79 Eoderocerataceae M 36.34 66.66 N 322 60 Hildocerataceae M 87.85 91.32 N 288 219 Morphological Variation and Covariation 78 100 90 80 Nontuberculate 70 Frequency 60 5 0 4 0 30 ^ T ^ " \A l^"l I gsgsss D wwwhX).7 H wwwh<0.7 Psi locerataceae Eoderocerataceae Hi ldocerataceae From (1) and Buckman's law, we can infer: (3) Frequency of shells without tubercles is greater in involute forms (V>0.5). Superfamily V\F% V<0.5 V>0.5 Psilocerataceae M 88.81 96.84 N 286 95 Eoderocerataceae M 39.76 51.11 N 337 45 Hildocerataceae M 88.99 90 N 327 180 1 0 0 9 0 -8 0 -Nontuberculate '" Frequency gO 50 . 40 301^ €5535 j _ D V O . 5 a v>o.5 Ps i locera taceae E o d e r o c e r a t a c e a e H i l d o c e r a t a c e a e (2) and (3) are related by Buckman's law. It is an interesting question to find out which covariation predominates. Take a subsample of rapidly expanding forms (W>2.2) from superfamily Eoderocerataceae, calculate the average WWWH and V against tuberculation: Average Tub ere nontuberculate unituberculate bituberculate V M 0.438 0.282 0.522 S 0.156 0.164 0.222 N 30 14 27 WWWH M 0.778 0.970 1.114 S 0.241 0.237 0.241 N 28 18 27 Morphological Variation and Covariation 79 There is an increase in WWWH as the number of tubercles increases, whereas, a correlation is not evident for V. It seems WWWH is directly correlated with tuberculation, and V is more or less related to tuberculation through Buckman's law. (4) WWD increases if the shells are tuberculate. Superfamily TubYWWD with without Psilocerataceae M 0.338 0.279 S 0.105 0.091 N 22 218 Sig. 0.002 Eoderocerataceae M 0.370 0.311 S 0.118 0.081 N 213 127 Sig-0.001 Hildocerataceae M 0.296 0.281 S 0.072 0.065 N 59 321 Sig. 0.05 WWD • with H without Psilocerataceae Eoderocerataceae Hildocerataceae with or without tubercles From this covariation, we can infer: (5) Frequency of shells without tubercles increases if the fineness ratio of the shell is small (WWD<0.2). Superfamily WWD\F% WWD > 0.2 WWD < 0.2 Psilocerataceae M 90.06 100 N 352 29 Eoderocerataceae M 40.27 58.82 N 365 17 Hildocerataceae M 88.93 100 N 488 19 Nontubercu la te Frequency • wwd >0.2 H wwd <0.2 Psi locera taceae E o d e r o c e r a t a c e a e H i ldocera taceae Morphological Variation and Covariation 80 (6) WWD decreases as shell diameter(D) increases. Superfamily D(cm)\WWD <3 3-6 6-9 9-15 >15 Psilocerataceae M 0.340 0.273 0.260 0.264 0.271 S 0.130 0.073 0.079 0.07 0.065 N 63 105 53 50 43 Sig. 0.001 0.12 No No Eoderocerataceae M 0.378 0.348 0.318 0.299 0.269 S 0.104 0.102 0.109 0.127 0.078 N 121 184 105 56 20 Sig-0.006 0.009 0.13 0.14 Hildocerataceae M 0.326 0.293 0.267 0.253 0.241 S 0.086 0.069 0.044 0.055 0.048 N 90 202 136 85 29 Sig. 0.001 0.001 0.02 0.11 This covariation is most significant when shell diameter D is relatively small, which indicates significant change in WWD during the early stage of the growth. 4.3.5 Ribs (1) Simple primary ribs are coarser than primary ribs that furcate. Superfamily Rib\RW simple furcated Psilocerataceae M 0.179 0.105 S 0.059 0.042 N 300 34 Sig-0.001 Eoderocerataceae M 0.203 0.162 S 0.065 0.061 N 217 155 Sig. 0.001 Hildocerataceae M 0.153 0.142 S 0.056 0.042 N 349 153 Sig. 0.015 Morphological Variation and Covariation 81 RW D simple • furcated 0.08 Psilocerataceae Eoderocerataceae Hildocerataceae Rib Furcation The reverse is also evident: (2) Frequency of shells with simple ribs increases if the shells are coarsely ribbed (Rib Width>0.22). Superfamily RW\F% RW < 0.22 RW > 0.22 Psilocerataceae M 90.07 97.75 N 292 89 Eoderocerataceae M 51.38 78.94 N 218 152 Hildocerataceae M 72.43 81.81 N 428 77 • RW<0.22 H RWX).22 Psilocerataceae Eoderocerataceae Hildocerataceae (3) Frequency of shells with straight ribs increases if whorl shape is rounded. Superfamily Whorl Shape\F% others rounded Psilocerataceae M 53.36 59.52 N 298 84 Eoderocerataceae M 83.16 93.10 N 297 87 Hildocerataceae M 22.87 57.69 N 494 26 Morphological Variation and Covariation 82 Frequency of Straight Rib 100 90 80 70 60 50 40 . 30 . 20 -10 . 0 \A .SZZL • others • rounded Psilocerataceae Eoderocerataceae Hildocerataceae Whorl Shape (4) Frequency of sparsely ribbed (PRHW<14) forms increases if the shells are depressed (WWWH>1.2). Superfamily WWWH\F% wwwh< 1.2 wwwh> 1.2 Psilocerataceae M 30.82 46.15 N 318 26 Eoderocera1 M 45.76 60.78 taceae N 177 51 Hildocerataceae M 12.95 66.66 N 363 6 70 60 50 Frequency of 40 PRHW<14 3 0 • wwwh<1.2 H wwwh >1.2 Psilocerataceae Eoderocerataceae Hildocerataceae WWWH 4.3.6 Tuberculatum (1) Frequency of shells with tubercles increases if the whorl shape is quadrate. Superfamily Whorl Shape\F% others quadrate Psilocerataceae M 4.64 61.11 N 345 36 Eoderocerataceae M 61.39 83.54 N 303 78 Hildocerataceae M 12.94 27.45 N 456 51 Morphological Variation and Covariation 83 • others • quadrate Psilocerataceae Eoderocerataceae Hildocerataceae Whorl Shape (2) Frequency of shells with tubercles increases if ribs furcate. Superfamily Rib\F% non-furcate furcate Psilocerataceae M 8.96 20 N 346 35 Eoderocerataceae M 58.95 76.47 N 229 153 Hildocerataceae M 4.49 37.74 N 356 151 Frequency of Tuberculate Form • non-furcate H furcate Psilocerataceae Eoderocerataceae Hildocerataceae Ribs (3) Frequency of shells without tubercles increases if ribs are weak. Superfamily Rib\F% med.-strong weak Psilocerataceae M 87.64 98.24 N 267 114 Eoderocerataceae M 37.76 67.44 N 339 43 Hildocerataceae M 85.62 95.36 N 313 194 Morphological Variation and Covariation 84 Frequency of Nontuberculate Forms 100 90 801-70 60 50 40 30 20 rfl • med.-strong • weak Psilocerataceae Eoderocerataceae Hildocerataceae Ribs This positive correlation between tuberculation and rib strength may point to the importance of buoyancy control and shell building material supply during growth. Both tuberculate forms and strongly ribbed forms are concentrated in the low W and high U geometric region which provides high buoyancy and carbonate efficiency, whereas nontuberculate and weakly ribbed forms are concentrated more in the high W and low U region which has low buoyancy and carbonate efficiency. (4) Frequency of shells without tubercles increases if the ribs are projected. Superfamily Rib\F% others projected Psilocerataceae M 87.89 100 N 289 92 Eoderocerataceae M 34.53 85.71 N 333 49 Hildocerataceae M 89.20 100 N 500 7 Frequency of Nontuberculate Forms 100 901-80 70 60 50 40 30 20 l 0.25 WWD < 0.25 WWWH<0.6 Psilocerataceae M 30.79 42.52 44.44 N 302 87 54 Eoderocerataceae M 10.65 38.27 62.06 N 310 81 47 Hildocerataceae M 66.67 76.47 84.67 N 390 153 124 90 80| . 70 60 Frequency of 50 . Carinate Venter 40 • 30 . 20 . 10 0 Psilocerataceae Eoderocerataceae Hildocerataceae • wwd X5.25 M wwd <0.25 El wwwh <0.6 (3) Frequency of shells with plain venters increases if the shells have high fineness ratios (WWD>0.5). Morphological Variation and Covariation 86 Superfamily Condition\F% WWD<0.5 WWD>0.5 WWWH>1.3 Psilocerataceae M 28.53 42.85 16.66 N 382 7 18 Eoderocerataceae M 76.74 100 99.08 N 344 47 108 Hildocerataceae M 2.80 37.5 50 N 530 8 6 Frequency of Plain Venter 100 80 60 40 20 0 • wwd <0.5 m wwd X).5 IS wwwh >1.3 Psilocerataceae Eoderocerataceae Hildocerataceae One interesting point here is that depressed shells (WWWHM.3) do not show an increase in frequency of plain venters for all three superfamilies, whereas high fineness ratios do. It may be that WWD is directly correlated with ventral morphology, and WWWH is related through WWD. 4.3.8 Summary & Speculations It is generally agreed among ammonite workers that the shell of ammonite served two prime functions: as a protection for the soft parts and as a hydrostatic device. Ornamentations such as ribs and tubercles were highly functional features of the shell, as is demonstrated by the common covariations documented above. Their significance has been thought of as (Kennedy and Cobban 1976): (1) Mechanical; (2) Protective, serving for both physical protection and as an aid to camouflage; (3) An aid to stability; (4) A means of regulating buoyancy; (5) A means of improving streamlining; (6) Sexually selected display features; (7) Sensory. Morphological Variation and Covariation 87 The inter-relationships of shell expansion rate, degree of involution, whorl shape, ribs, tubercles, and venter have been studied using Amnion database. The major covariation patterns are: (a) The faster expanding shells tend to be more involute, the involute shells are more compressed than evolute shells, and the compressed shells have finer ribs. Possible interpretations for this covariation, also known as Buckman's Law, are the restrictions imposed by overlap ratio and relative area of the whorl (equations 1, 2 in section 4.2), buoyancy control and carbonate efficiency (Fig. 4-29). (b) Frequency of shells with tubercles increases if ribs furcate. Westermann (1978) suggested that a point of rib division would appear to be a mechanically good location for lateral tubercles which may exert localized stress on the shell, this would explain the repeated pattern of rib furcation and tuberculation during ontogeny that bundling ribs and prominent tubercles on the inner whorls fade to simple ribs at maturity when the wall has gained sufficient thickness. The division of ribs may also be due to the increase of circumference with increasing radius (Westermann 1978). (c) Tubercles of compressed shells tend to be on the lower flank whereas tubercles of depressed shells tend to be on the upper flank, which may be a reflection of Westermann's observation that tubercles are usually situated on the shoulders or the maximal whorl width which are often in the lower flank of compressed shells. This would also explain the fact that the frequency of shells with tubercles increases if whorl shape is quadrate. (d) Shells with sinuous ribs are more involute and more compressed than shells with straight ribs. (e) There is a positive correlation between tuberculation and rib strength which may point to the importance of buoyancy regulation and shell building material supply during growth. Both tuberculate forms and strong ribbed forms are concentrated on low W and high U geometric region which provides high buoyancy and carbonate efficiency whereas Morphological Variation and Covariation 88 nontuberculate and weak ribbed forms are concentrated more on high W and low U region which has low buoyancy and carbonate efficiency; (f) As expected, the frequency of shells with a keels increases in shells that are compressed, or have a small fineness ratio. It should be noted that the observed covariation patterns may be unique to the data set used except for Buckman's Law which has been recognized in other ammonoid stocks. To be confident that these covariation patterns are due to functional rather than phylogenetic constraints would require examining earlier and later ammonoid records. Morphological Variation and Covariation 89 4.4 Ontogenetic Variation The geometric data used in the previous analyses were gathered from specimens with shell diameters larger than 4 cm to reduce the impact of ontogenetic variation. However, the problem of ontogenetic change cannot be ignored and an attempt is made here to describe such changes using measurements from different shell diameters for each species. The sample is restricted to species with at least 6 occurrences in the database and the shell diameters of the specimens have a large enough range to show ontogenetic variations, if present. Because the number of specimens for each species in the database is limited, they are not subdivided into groups based on geographic areas. This may blur true ontogenetic change or create false patterns if morphological variations for different geographic regions are large. The limitations of the data should be kept firmly in mind while interpreting the results of these inquires. 4.4.1 Umbilical Ratio (U) "Ontogenetic variations have been found in practically all ammonoid groups. In some instances the ontogenetic change has the effect of making the shell more evolute but in the majority of cases the change is toward involute" (Raup 1967). This generalization is probably true for Paleozoic ammonoids, especially goniatites, but Lower Jurassic ammonite data show otherwise: 235 out of 670 species studied become more evolute during ontogeny, only 49 species tend to be more involute and the rest remain more or less constant. Ontogenetic change is determined by (1) visually examining the U-D plots like Fig. 4-31, 4-32; (2) computing the difference between the U value measured at the largest diameter of the species and the one at the smallest diameter. If it is larger than the within species mean standard deviation of U which is 0.043 in this data set, a significant change on U during ontogeny is inferred. The top ten species to undergo significant either increasing (+) or decreasing (-) ontogenetic change in U are: Fanninoceras carlottense (-) , Fanninoceras disciforme (-), Morphological Variation and Covariation 90 Fanninoceras fannini (-), Hildoceras bifrons (+), Haugia jugosa (+), Psiloceras planorbis (+), Psiloceras johnstoni (+), Vermiceras scylla (+), Aveyroniceras acanthoides (+), Dubariceras silviesi (+). It is noteworthy that increase in U does not necessarily indicate less whorl overlap because it could also be the result of a reduction in shell expansion rate during ontogeny. This is common in the genus Vermiceras. 0.3 0.25 as 0.2 OH "(0 •^ 0.15 E 3 0.1 0.05 0 _ • • • • • . • • • • • • • • • • • 3 4 5 D - Shell Diameter (cm) Figure 4-31 Plot of ontogenetic change in U for Fanninoceras fannini 0.6 0.5 I °-4 I 0.3 0.2 0.1 8 s 1 i 4 6 8 D - Shell Diameter (cm) 10 Figure 4-32 Plot of ontogenetic change in U for Dubariceras silviesi 12 Morphological Variation and Covariation 91 4.4.2 Shell Expansion Rate (W) Using the same method as described above, it was found that 181 out of 670 species studied show an expansion rate decrease during ontogeny, only 40 species show increase and the majority remain more or less constant. The top ten species that undergo significant ontogenetic change on W are: Pleuroceras solare (-), Hammatoceras speciosum (-), Dubariceras silviesi (-), Phricodoceras taylori (+), Pseudogrammoceras muelleri (-), Arnioceras ceratitoides (-), Metaderoceras talkeetnaense (-), Vermiceras scylla (-), Vermiceras rursicostatum (-), Haugia variabilis (-). Fig. 4-33 shows that expansion rate decreases during ontogeny for Dubariceras silviesi and the negative correlation between U and W is evident by comparing Fig. 4.33 with Fig. 4-32. Fig. 4-34 shows that expansion rate increases during ontogeny for Phricodoceras taylori. 2.5 CD 0£ c 1.5 CO CD X I 111 0.5 • 4 6 8 D - Shell Diameter (cm) 10 12 Figure 4-33 Plot of ontogenetic change in W for Dubariceraas silviesi Morphological Variation and Covariation 92 ro CC c o (0 c CD n X 111 1 5 3.5 3 2.5 2 1.5 1 0.5 0 0 2 4 6 8 10 12 14 D - Shell Diameter (cm) Figure 4-34 Plot of ontogenetic change in W for Phricodoceras taylori 4.4.3 Ratio of Whorl Width to Whorl Height (WWWH) It is found that 224 out of 623 species studied become more compressed during ontogeny, only 68 species become more depressed and the rest remain more or less constant. The top ten species in the database that undergo significant ontogenetic change in WWWH are: Amaltheus margaritatus (-), Androgynoceras maculatum (-), Aegoceras luridum (+), Dactylioceras anguinum (-), Phricodoceras urcuticum (-), Phricodoceras taylori (-), Prodactylioceras davoei (-), Coeloceras incertum (+), Phymatoceras rude (-), Phymatoceras tumefacta (-). Fig. 4-35 shows that Phricodoceras taylori becomes more compressed during ontogeny and the negative correlation between W and WWWH is evident by comparing Fig. 4.35 with Fig. 4-34. Fig. 4-36 shows that Aegoceras luridum becomes more depressed. Morphological Variation and Covariation 93 1.2 1 OR 0 6 0 4 0? n • < • • • • i> 6 8 D - Shell Diameter (cm) 10 12 14 Figure 4-35 Plot of ontogenetic change in whorl shape for Phricodoceras taylori 1.6 1.4 1.2 1 0.8 0.6 0.4 0.2 0 «> > ii 0.5 1.5 2 2.5 3 D - Shell Diameter (cm) 3.5 4.5 Figure 4-36 Plot of ontogenetic change in whorl shape for Aegoceras luridum Morphological Variation and Covariation 94 4.4.4 Primary Rib Density (PRHW) It is found that primary rib density for virtually all species remains more or less constant (61%) or increases (39%) during ontogey, none show significant decrease in primary rib density during ontogeny although the weakening of ornamentation is common. The top ten species that undergo significant significant ontogenetic change on primary rib density are: Amaltheus conspectus, Amaltheus margaritatus, Amaltheus extremus, Arieticeras algovianum, Harpoceras chrysanthemum, Harpoceras falciferum, Protogrammoceras praecurionii, Pseudolioceras lythense, Reynesoceras italicum, Schlotheimia angulata. Fig. 4-37 shows that the rib density of Amaltheus conspectus increases during ontogeny and Fig. 4-38 shows the rib density change for Arieticeras algovianum. 30 25 !L_ 20 • . • X 15 • °-10 5 0 J | I | I | | 0 2 4 6 8 10 12 14 D - Shell Diameter (cm) Figure 4-37 Plot of ontogenetic change in PRHW for Amaltheus conspectus Morphological Variation and Covariation 95 25 20 s 16 X °- 10 • • • • • I I • • • » • • • • • • • • • • 0 1 2 3 4 5 6 7 8 D - Shell Diameter (cm) Figure 4-3 8 Plot of ontogenetic change in PRHW for Arieticeras algovianum 4.4.5 Superfamily The difference of parameter values on the largest and smallest specimens is used to represent the degree of ontogenetic variation for each species with more than four specimens. Table 4-3 shows the average ontogenetic changes of species within superfamilies. the Psilocerataceae has the largest ontogenetic variation in U whereas the Eoderocerataceae shows greater ontogenetic variation in WWWH. Members of the Hildocerataceae are more likely to undergo ontogenetic change on W Table 4-3 Average ontogenetic changes of species within superfamilies Superfamily Psilocerataceae Eoderocerataceae Hildocerataceae U 0.071 0.049 0.053 W 0.165 0.173 0.186 WWWH 0.128 0.205 0.135 Changes through Time 96 Chapter 5 Changes through Time 5.1 Introduction Evolutionary change is not evenly distributed over time but is concentrated in episodes of evolutionary radiation as clearly indicated by the fossil record (Foote 1991). For ammonites the early Jurassic represents the most important episode because the ammonoid stem barely escaped extinction at the close of the Triassic (Donovan, Callomon and Howarth 1981). Yet, despite its significance, a limited number of approaches have been used to study this diversification, most notably the analysis of taxonomic data (Hallam 1987). The analysis of diversification by 'taxon counting' assumes either that morphologic diversity can be measured by taxonomic diversity or that the number of taxa reflects the number of objectively discernible morphotypes (Foote 1991). We know that taxonomic data and morphologic data do correlate, but taxonomic and morphologic approaches are not simply redundant (Foote 1991). If taxa are consistently defined, then taxonomic data can tell us about the number of biological units at a given time. But if we want to know the nature of these units, how they originate, how they evolve once established and how discrete they are from each other then morphological data are clearly necessary. "Since form represents the raw data of paleobiology, it is important to document significant events in the history of life from the standpoint of morphology" (Foote 1991). This study represents an attempt to analyze in detail the Lower Jurassic ammonite record, in terms of morphologic and taxonomic diversity and their relationship at 20 successive levels (zones) through an approximately 30-Ma interval (Harland et al. 1990). Changes through Time 97 Table 5-1 Lower Jurassic zonal scheme for northwest Europe Series Middle Jurassic Lower Jurassic Age at base 179 Ma 187 Ma 196 Ma 203 Ma 208 Ma Stage Aalenian Toarcian Pliensbachian Sinemurian Hettangian Zone Opalinum Levesquei Thouarsense Variabilis Bifrons Falciferum Tenuicostatum Spinatum Margaritatus Davoei Ibex Jamesoni Raricostatum Oxynotum Obtusum Turneri Semicostatum Bucklandi Angulata Liasicus Planorbis 5.2 Stratigraphic Division The traditional stratigraphic division of the Lower Jurassic into 4 stages and 20 primary standard zones is adopted here with the age at the base of each stage taken from Harland et al. (1990)(Table5-l). 5.3 Choice of Characters I have attempted to represent ammonite morphologic diversity in terms of basic shell geometry and ornamentation, which are the major describable morphological characters for species identification. Basic shell geometry includes parameters: W, U, WWWH; as well as Changes through Time 98 venter for each species. Ornamentation includes PFORM (primary rib form), PRHW (primary rib density), FURC (a combination of pattern and position of rib furcation), and tuberculation (a combination of pattern and position of tubercles). All parameters are defined in Chapter 2. Aperture shape is not included in this study due to limited data available. This study is restricted to external morphology rather than internal characters, such as the septal suture. In strong contrast to earlier systems, the septal sutures of Jurassic ammonites are seldom useful for defining major groups and are hardly ever employed at lower levels of classification (Donovan, Callomon and Howarth 1981). The data used in this study comprise observations made on 6784 specimens, representing 15 families, 179 genera, and 1319 species. This comprises virtually complete coverage of the ammonite genera known to occur in the Lower Jurassic as catalogued by Donovan, Callomon and Howarth (1981). 5.4 Geometry through Time It is tempting to search the biometrical data for evidence of correlation between geometry and stratigraphic time. W-U plots have been made for the four stages. A bimodal distribution characterizes the Hettangian (Fig. 5-1), with one peak corresponding to evolute and slowly expanding forms, and another peak corresponding to moderately involute forms. Sinemurian ammonites fully explored the region of the first peak (Fig. 5-2) but the W-U distribution for the Pliensbachian concentrates on the second more involute peak (Fig. 5-3), a trend that continues for the Toarcian (Fig. 5-4). Changes through Time 99 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 w Figure 5-1 Density diagram for Hettangian ammonites (101 species) 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 1.20 1.40 1.59 1.79 1.99 2.18 2.38 2.58 2.77 2.97 3.16 3.36 3.56 3.75 3.95 W Figure 5-2 Density diagram for Sinemurian ammonites (366 species) Changes through Time 100 1993). I will use as a starting point the sum of the morphological range as a measure of morphological diversity. Figure 5-7A shows the morphological diversity for each of the 20 successive zones using the four basic characters of shell geometry. Each bar in the graph represents a zone and each shaded portion represents the morphological diversity for a character with all characters having the same weight. Figure 5-8A adds ornamentation to the four shell geometry characters. In Chapter 4, I demonstrated that covariation is widespread in ammonites and covariation will introduce a certain amount of redundancy into the measures of morphologic diversity, as is evident in Table 5-2. The shaded boxes in Table 5-2 indicate pairs of characters with correlation coefficients greater than 0.5. the most significant correlation occurs among the three parameters describing rib density, form and furcation (coefficient > 0.8) which are therefore combined (averaged) into one parameter (RIB) for this study. The covariations among W, U, and WWWH demonstrated by Eqs (1) and (2) in section 4.2 are also evident here. As can be expected, there is a significant correlation between ornamentation and whorl shape, and a correlation between rib furcation and tuberculation. To eliminate the redundancy caused by covariations, a multiple linear regression was performed for each parameter using the rest of the parameters. The ratio of residual to total variance which indicates the degree of independence of each parameter with respect to the rest (Table 5-3) can then be used as a weight in the summing up of the MRDI values for each zone as shown in Fig.5-7B, 5-8B. Table 5-2 MRDI correlation matrix (Shaded values have correlation coefficients > 0.5) w u WWWH VENTER PRHW PFORM FURC TUBERC W 1 0^635982 0 559241 0.066713 0.096465 0.365184 0.203162 0.440936 U 1 0.6933 0.421967 0.208958 0.326135 0.387015 0.366407 WWWH 1 0.252447 0.565855 0.601697 0641858 0.492782 VENTER 1 0.156352 0.19651 0.257381 0.119988 PRHW 1 0.841871 0.922446 0.34703 PFORM 1 0.842275 0.521663 FURC 1 0.539111 TUBERC 1 Changes through Time 101 5.5 Taxonomic Diversity Ammonites have served as classic examples of biostratigraphic index fossils. Their fossil record is exceedingly rich and their taxonomy is mature in the sense that it no longer shows an exponential increase in description of new taxa each year (rather, the reverse is happening) which makes them well suited for taxa counting (Ward 1983). The data sets become more comprehensive moving up the taxonomic and stratigraphic hierarchy as sampling failure becomes less likely. Even so, there is no reason to assume any non-random bias in sampling even down to the level of species and zones, so that the data can be confidently used to assess relative, if not absolute, changes in diversity and turnover through time. The method of taxonomic diversity analysis adopted here is similar to that presented for a number of invertebrate groups in the Lower Jurassic of northwest Europe by Hallam (1987). The diversity graphs are simple plots of numbers of taxa for each successive zone; the graphs of times of family first and last appearances are self explanatory. The major difference is my greatly expanded database which enables me to work at the species as well as the generic level. As illustrated in Fig. 5-5A, species diversity shows a slow increase from the oldest Planorbis Zone to the Bucklandi Zone, followed by a slight decline to the Turneri Zone, and rapid rise to a middle Pliensbachian maximum followed by a spectacular crash through the Tenuicostatum Zone to a Falciferum Zone minimum. Thereafter there is a further rise to the Bifrons Zone to match Sinemurian but not Pliensbachian levels followed by a decline to the Thouarsense Zone and a final rise to the Levesquei Zone. It is evident from Fig. 5-5B,C that diversity curves for genera and families closely resemble the one for species. The overall similarity among the three diversity curves suggests that they reflect a common underlying pattern which supports the general claim made by Bambach and Sepkoski (1992) that large-scale spatial and temporal diversity patterns at the level of species, genus, and family are well correlated. It is interesting to note that diversity peaks first at the family level in the Ibex Thouarsense Bifrons Tenuicostatum Margaritatus Ibex Raricostatum Obtusum Semicostatum Angulata Planorbis 1 zC n_ 1 i " 1 1 . 1 -| ' = 1 zf t ±1 I IT" H \ ^—^-1 1 J 1— 1 1 50 100 150 Number of species 200 ^T JL. —i 1 1 10 20 30 Number of genera ^ ^ ^ 1 1 5 10 Number of families Number of families making their first appearance Number of families making their last appearance Figure 5-5 Lower Jurassic Ammonite Taxonomic Diversity Changes through Time 102 Changes through Time 103 A B C Figure 5-6 Diversity of Lower Jurassic ammonite (A), bivalve (B), and brachiopod (C) diversity. Number of genera for ammonites, number of species for the rest (Hallam 1987). Zone, followed by generic data one zone later, and finally species which implies significant delay in radiation for lower levels of ammonite taxa. The observed genus diversity change pattern is in general agreement with the one shown for ammonite genera (Fig. 5-6A) by Hallam (1987) where there is a more or less steady rise in diversity from a very low level in the early Hettangian through to the Pliensbachian followed by a marked decline into the early Toarcian after which it tends once more to increase. The major difference between the two is that ammonite genera reach their highest diversity level in the Pliensbachian instead of the middle Toarcian in my data set. My ammonite species diversity peak coincides with Hallam's bivalve and brachiopod diversity peaks of the late Pliensbachian (Fig. 5-6B, C). Fig. 5-5 D, E shows the Oxynotum Zone has the highest family origination rate and one of the lowest species diversity. The late Sinemurian and early Pliensbachian also have high family origination rates and relatively low species diversities; species reach their highest diversity Changes through Time 104 level in the late Pliensbachian which happens to have the highest family extinction rate and an almost zero origination rate. Raup and Sepkoski (1986) identified the Pliensbachian as a time of mass extinction at the family level that was part of a 26 Ma periodic series. The average ammonite family extinction rate for the Upper Pliensbachian is 50% which is significantly higher than 7% — the average for the rest of Lower Jurassic zones (Fig. 5-5). The claim of periodic extinction has provoked speculation about an ultimate cause, such as sea level changes (Hallam 1987), climatic shifts, volcanic eruptions (Officer et al. 1987) or extraterrestrial events (Raup 1986). A central issue has been how rapidly the extinction occurred. It is evident from Fig. 5-5C, E that the Pliensbachian extinction event was gradual for ammonites at the family level, it started at Davoei Zone with a family extinction rate of 22% and followed by high extinction rate of 50% in the Margaritatus Zone and the Spinatum Zone. 5.6 Morphological Diversity 5.6.1 Morphological Range Diversity Index (MRDI) The variance seems to be a good choice to represent morphological diversity but unfortunately, most paleobiological data sets include both quantitative and qualitative data and there is no meaningful distance measurement between nominal data, such as the pattern of ribs. As a result, the range of forms is generally accepted as a measure of morphological diversity. For qualitative data, the MRDI is the percentage of occupied character states. For quantitative data, MRDI is the difference between the maximum and minimum of the morphologic characters with normalization so that the MRDI value always falls between 0 and 1. Van Vale (1974) discusses the multivariate generalization of the univariate range, suggesting two measures: the sum of the univariate range of morphological variables and the product of univariate ranges. The latter represents the volume of morphospace occupied, but this quantity vanishes or nearly vanishes if any of the ranges is zero or nearly zero (Foote 1993). I will use as a starting point the sum of the morphological range as a measure of Changes through Time 105 morphological diversity. Figure 5-7A shows the morphological diversity for each of the 20 successive zones using the four basic characters of shell geometry. Each bar in the graph represents a zone and each shaded portion represents the morphological diversity for a character with all characters having the same weight. Figure 5-8A adds ornamentation to the four shell geometry characters. In Chapter 4,1 demonstrated that covariation is widespread in ammonites and covariation will introduce a certain amount of redundancy into the measures of morphologic diversity, as is evident in Table 5-2. The shaded boxes in Table 5-2 indicate pairs of characters with correlation coefficients greater than 0.5. the most significant correlation occurs among the three parameters describing rib density, form and furcation (coefficient > 0.8) which are therefore combined (averaged) into one parameter (RIB) for this study. The covariations among W, U, and WWWH demonstrated by Eqs (1) and (2) in section 4.2 are also evident here. As can be expected, there is a significant correlation between ornamentation and whorl shape, and a correlation between rib furcation and tuberculation. To eliminate the redundancy caused by covariations, a multiple linear regression was performed for each parameter using the rest of the parameters. The ratio of residual to total variance which indicates the degree of independence of each parameter with respect to the rest (Table 5-3) can then be used as a weight in the summing up of the MRDI values for each zone as shown in Fig.5-7B, 5-8B. Table 5-2 MRDI correlation matrix (Shaded values have correlation coefficients > 0.5) w u WWWH VENTER PRHW PFORM FURC TUBERC 0.63598 0.55924 0.06671 0.09646 0.36518 0.20316 0.44093 0.693 0.42196 0.20895 0.32613 0.38701 0.36640 WWW 0.25244 0.56585 0.60169 0.64185 0.49278 VENTE 0.15635 0.1965 0.25738 0.11998 PRH 0 84187 $92244 0.3470 PFOR 0.84227 0 52166 FUR 0.53911 TUBER o a 9 SI 0.5 1 1.5 2 2.5 3 All characters with equal weight The weight for each character is based on its degree independence (Table 5-3) Figure 5-7 The Accumulation of Morphological Range Diversity Index for Basic Shell Geometry 106 ABIhouarsenBfrorS______________________________1garitatus_____________________________________•Ri1TenUI0statumIbex___________________________0Ventet________WWMObtusum_________SWSem005tatm____________Mgulata_______012450o.511.52pianorbi0ara°WitheqUa’Theweightforeachcharactetisbased0nitSdegree0tIdepefldegable5-3)jgUrC5-8TheAccumulation0forphob0I’gaUgeDiVersitYIndexforAll?aramets107Changes through Time 108Table 5-3 Measure of independence--residuals from multiple linear regressionSum of Squares W U WWW VENTER RIB TUBERCTotal 0.320 0.189 0.731 0.121 0.512 0.341Residual 0.197 0.050 0.278 0.231 0.174 0.124Ratio % 38.10 20.92 27.55 65.62 25.36 26.66The diversity of basic shell geometry (Fig. 5-7B) shows a rapid rise to an early Sinemurianmaximum through morphological radiation, followed by a pronounced fall in the middleSinemurian. Thereafter morphological diversity remains high and is stable apart from twomodest troughs, one in the Falciferum Zone (which, incidentally, correlates with the earlyToarcian anoxic event in northwest Europe) and another in the Thouarsense Zone. Fig. 5-8Bshows a similar general pattern except that the Pliensbachian and Toarcian ammonites havesignificantly higher ornamentation diversities than those of the Hettangian and Sinemurian.5.6.2 Shannon Diversity Index (SDI)The measure of information proposed by Shannon (1948) is the bit. Thus, if we have adevice such as a switch, which has two stable positions, on or off, then it can store 1 bit ofinformation1og2 = 1.0 bitThere is a close relationship between information and uncertainty, so the more uncertain ananswer is, then the more information is passed when the answer is given. If there are numberof alternatives, then the amount of information is maximized when each is equally likely tooccur. If we consider a system with N alternatives, and the probabilities of each alternative isgiven byPi’ P2’ P3’ Pthen the information H is given byH=-Zp1log2p i1,2 ,nChanges through Time 109 H is the entropy of the system. If we consider the case of two alternatives, each being equally likely, then Pl=P2 = 0-5 H = -0.5 log20.5 - 0.5 log20.5 = 1.0 if/?, = 1 mdp2 = 0 (or vice versa), then H=0. Thus H is maximized when/?/ = p2 = ••• = pn and H is equal to log2 n, the ratio -Lpt\og2Pi I log2n i = 1,2, .... ,n is known as the relative entropy (RE) (Shannon 1948), and can be used as an alternative to the morphological diversity range index. RE describes not only the range of the morph space occupied, but also the evenness of the occupation. For qualitative morphological characters (VENTER, FURC, TUBERC) the Shannon diversity index (SDI) is defined as SDi = -z/;iog„y; i = i,2,....,n n — number of the states for the character fj — frequency of the state i For quantitative morphological characters (W, U, WWWH, DMAX), there are no natural division of states, therefore each character is divided into n evenly spaced intervals. If n is equal to one, the whole character range is considered as one state and the SDI is equal to zero. As n increases, the SDI gradually rises to approach the true diversity of the character. Experiment shows that the SDI starts to stabilize when n is bigger than one fifth of the sample size if the sample size is not too small (>40), and this value is subjectively adopted here. This is not critical since the current study is not meant to estimate the absolute morphological diversity of ammonite species that occurs in each zone, but to assess the relative changes. The change in diversity shown in Figs. 5-9 and 5-10 is in general agreement with the pattern observed in Figs. 5-7 and 5-8. There is a rapid rise to an early Sinemurian maximum through morphological radiation, followed by a pronounced fall in the middle Sinemurian with diversity remaining relatively high and stable thereafter. This temporal pattern is also reflected in Fig. 5-11 where the first ammonite superfamily in the Early Jurassic — the Psiloceratacea. o SI 0.5 1 1.5 2 2.5 3 All characters with equal weight 3.5 • Venter • WWWH IU IW 0 0.2 0.4 0.6 0.8 1 1.2 1.4 The weight for each character is based on its degree of independence (Table 5-4) Figure 5-9 The Accumulation of Morphological Shannon Diversity Index for Basic Shell Geometry 110 12 3 4 All characters with equal weight ITuberc •Rib D Venter OWWWH • U IW 0 0.5 1 1.5 2 The weight for each character is based on its degree of independence (Table 4-6) Figure 5-10 The Accumulation of Morphological Shannon Diversity Index for AH Characters 111 Hildocerataceae 1 ^i Eoderocerataceae 1 5^— Psilocerataceae 1 , 0 1 A • \ / / \ \ \\^ J! 2 3 4 5 All characters with equal weight B i^i^l^i^H \ / // \ \ \ ^^5= ^^ • 0 0.5 1 1.5 2 The weight for each character is based on its degree of independence (Table 4-6) •Tuberc BRib D Venter DWWWH •U •w Figure 5-11 The Accumulation of Morphological Shannon Diversity Index by Superfamily 112 Changes through Time 113 Table 5-4 Residuals from multiple linear regressions of SDI Sum of Squares Total Residual Ratio % W 0.108 0.029 21.16 U 0.093 0.051 35.41 WWW 0.309 0.131 29.77 VENTER 0.397 0.286 41.87 RIB 0.056 0.014 20 TUBERC 0.346 0.137 28.36 shows the greatest morphological diversity, followed by the morphologically more restricted Eoderocerataceae, and a diversity rebound with the Hildocerataceae. 5.7 Discrepancies between Morphological and Taxonomic Diversity It is evident by comparing Fig. 5-5 with Figs. 5-8 and 5-10 that initial morphological diversification in Lower Jurassic ammonites far exceeded the proliferation of lower-level taxa. Such a pattern suggests that morphological transitions were larger earlier in this clade's history, a point that is relevant to the ecological and evolutionary mechanisms of diversification (Stanley 1979; Foote 1992, 1993). A similar pattern has been discussed for echinoderms (Foote 1992; Sprinkle 1980), and stenolaemate bryozoans (Anstey and Pachut 1992). The most striking fact emerging from the comparison is that the morphological diversity of the Bucklandi Zone with 46 species is higher than that of the Margaritatus Zone with 177 species which demonstrates morphological diversity need not increase as taxonomic diversity increases. Such morphological stagnation indicates taxonomic diversification that is highly constrained morphologically (Foote 1993). Two patterns are seen during the decline of taxonomic diversity: (1) from the Spinatum Zone through the Tenuicostatum Zone to the Falciferum Zone, the number of species drops to 49 from a high level of 161, whereas the morphological diversity remains relatively stable suggesting that the extinct species are randomly distributed with respect to morphology; (2) from the Bucklandi Zone through the Semicostatum Zone to the Turneri Zone, morphological diversity decreases along with Changes through Time 114 taxonomic diversity which may imply selective extinction in certain regions of the morphospace, but could also be due to the very low level of species diversity in the Turneri Zone. 5.8 Other interesting observations Table 5-5 shows that all families that radiate into numerous species (>13) in the first zone of their occurrence have durations of less than 4 zones, which may imply that evolution rates associated with these families are high. In other words, rapid origination is associated with short duration, although the time resolution of my data does not warrant a firm conclusion. Fig. 5-12 shows the average shell diameter changes for Lower Jurassic ammonite superfamilies through 20 successive zones. The basic calculation unit is species and the maximum shell diameter achieved for the species is used to compute the average for the superfamily. The rationale for using maximum instead of average shell diameter for species is to eliminate juvenile and immature forms from the calculation whenever possible. The average maximum diameter curves for the three superfamilies are more or less parallel. Most noticeably, the diameter curves show a synchronized drop from the Obtusum Zone to the Oxynotum Zone, followed by a parallel rise in the Raricostatum Zone. Furthermore, the mean maximum diameters for all three superfamilies decrease from the Jamesoni Zone to the Ibex Zone. It is possible that the observed parallelism among the average diameters for the three superfamilies is a coincidence which may disappear at the family level. However, Fig. 5-13 presents a similar pattern with the diameter curves showing a pronounced trough in the Oxynotum Zone, and six out of eight families showing a significant decrease in shell diameter in the Ibex Zone. Interestingly, these two zones show high family origination rates, relatively low species diversity (Fig. 5-5A, D) and are times of regression (Hallam 1988). This may imply r selection whereby times of regression cause a deterioration of the environment, increasing the stress on organisms and promoting the origination of high-level Changes through Time 115 taxa which radiate at lower taxonomic levels during sea level rise. "The new taxa evolving at times of low sea-level stand are often smaller than their ancestors, and increase in size phyletically during the subsequent, environmentally less stressful times of high sea-level stand" (Hallam 1987). Another possible explanation for the observed correlation is that it is an artifact of preservation bias but my data do not contain information on facies and so cannot address this problem. Table 5-5 Number of species in each zone for Lower Jurassic ammonite families Zone\Family Levesquei Thouarsense Variabilis Bifrons Falcifer Tenuicostatum Spinatum Margaritatus Davoei Ibex Jamesoni Raricostatum Oxynotum Obtusum Turneri Semicostatum Bucklandi Angulata Liasicus Planorbis Psi 7 8 12 30 Sch 2 4 2 1 2 11 14 12 Oxy 5 6 7 1 12 11 11 Cym 1 2 1 1 1 1 Ech 38 14 Ari 2 18 17 28 27 8 5 Ama 19 /h Coe 10 7 17 4 1 Dae 10 43 12 30 23 12 15 7 Eod 2 8 9 18 16 5 5 4 Lip 2 29 74 Phr 2 3 2 12 3 Pol 6 33 53 Hil 40 23 14 38 37 72 114 126 41 7 1 Phy 13 5 33 7 116 s I 0> a u > < 14 12 10 i i i Trri i^Trri i i T r r i i i /1 i ^s"^« i i ^r i \ i i i i i i i I i i i i / i i -.*^'^vsSt i ' W^ ' \ ' ' ' ' ' ' ' l l ' i i t i ^j*000^ 'X^s. i i /i i \ i i i i i i i i i i i i / i B^ i \ x^ i /^ i \ i i i i i i i i i i i i / i i ' \ A ' /T^v ' \ ' ' ' ' ' ' ' ' _M I 1 1 / 1 1 1 \ 1 \ 1 / /l >v 1 \ 1 1 1 1 1 • 1 l ^0*-***>\. ' ' ' / ' \ '\ ' //' >^ ' i i i i /TV J^"^ i X. 1 l/ 1 1 1 V X ' / / ' *\ ' \ ' ' ' ' / ' W 1 1 ^^ i ^i i i i • X t / / i i\ i \ i i i i / i i i i W jto W 1 1 1 "\ \ ' / / ' ' \ ' X ' ' ' ' / ' ' ' ' ' — -^^ 1 1 1- 1 r-X—V—i- -j ~j—i 1 - \— -t- \^ j 1 1 — / 1 + 1 i 1 yT | | 1 | | ' \ X ' / / ' ' \ ' M ' ' '/' ' ^ ' ' 1 1 I 1 1 'XX1//1 ' \ ' M\ ^ 1 1 / 1 1 y/ 1 1 1 1 1 1 1 1 1 \ T/ i\ I i \ ' ^00- M B till 1 1 1 1 1 1 \ 1 / 1 1 X. 1 B \ ^ ^-**^'^ 1 1 1 1 1 1 i i i i i i \i/ i i x. 1 ^^"^ i XT i i i i i i i l i ! l l 1 Xi I I WT 1 \L _J^*-^*W 1 1 1 i i t i i i W I I I I mr i i i i i i l 1 I 1 1 1 I t 1 1 1 I I 1 1 I I I 1 I 1 1 ! 1 1 1 1 1 1 1 1 1 1 1 1 1 1 I 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 I | 1 1 1- \ | | 1 1 -|- -1 1 1 1 1 -t -1 1 1 1 1 1 1 1 1 1 1 ! 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 i 1 1 1 1 1 1 1 1 1 i 1 1 1 I 1 1 1 1 1 1 3 3 ! 3 m I t/3 t? s 3 O I o c X O B 1 c o I Zone o Q g 'S I o "3 c o s I 73 Xl C3 > e 1 3 O 3 a-tZ) > u • Psilocerataceae • Eoderocerataceae - Hildocerataceae Figure 5-12 Average Shell Diameter Change for Lower Jurassic Ammonite Superfamihes 117 Average Diameter (cm) N o CD An Aid to Identification 119 Chapter 6 An Aid to Identification 6.1 Introduction Identifying ammonite species requires the recognition of associations of ammonite shell morphologies which can be demonstrated to maintain their superpositional relationships throughout their entire geographic distribution. Each species shows variation within the population and also during ontogeny, variation which must be determined before a species can be identified with confidence. Traditionally intraspecific variation is determined by examining the illustrations and descriptions of the specimens of the taxon under consideration which means scouring a voluminous literature that is in many different languages and often reaches back well into the last century (Smith 1986). In order to effectively utilize the literature, the attributes of a large number of specimens have to be memorized and evaluated in an objective manner. Direct comparison of two specimens is relatively easy but the problem increases rapidly as more specimens are involved. To a large extent the image database Ammon can overcome these problems. The basic idea is that given information supplied by the user, a search of Ammon is made and closely matching species are displayed on the screen for visual comparison with the specimen in question. If the candidate list is large, both the rough stratigraphic range and geographic locality of the specimen can be used to narrow the search. Searches can also be restricted to a certain diameter range to circumvent the problem of ontogenetic variation. amnion Image Database Retrieve by: Display Image Window Taxonomv => Stratiaraohv =: Moroholociv => Reference => Combination Some Utility: Previous Pacie Goto Specimen Brightness: Main List SDeci Sub ist WELCOME TO JURASSIC AMMONITE IMAGE DATABASE You can retrieve Jurassic ammonites by: 1. Taxonomy: Family, Genus, and Species. 2. Stratigraphy: Stage and Standard Zone. 3. Geography: Geographic Area and Country. 4. Morphology: Volution. Expansion Rate, Whorl Shape. Ribs, Tubercles. 5. Reference: in which the figure of the specimen appears. You can also retrieve by combining the above criteria. Figure 6-1 The start-up screen of the database Amnion An Aid to Identification 121 6.2 User Interface Arietitidae Ecfiioceratldae Oxynoticeratidae t Cymbitidae Eoderoceratldae f C ^Mffif hitidae Llparoceratidae i Amaltheidae Ammon has an easy to use, menu-driven user interface which is written in Sunview and the embedded SQL query language of Oracle RDBMS. Fig. 6-1 shows the start-up screen which consists of three windows: the upper-right window displays a welcome message and explains what user can do with the system, the lower-right is a graphics window showing the lateral and frontal views of a Lower Jurassic ammonite specimen and the left window hosts available command buttons, menu-buttons and sliders. Users can retrieve Jurassic (mainly Lower Jurassic) ammonites by Taxonomy, Stratigraphy, Geography, Morphology, Reference or various Combinations: 1. Taxonomy When the Taxonomy is pressed with the right mouse button in the left window, a pull-right menu appears which shows the available ammonoid families in the database (Fig. 6-2). If, for example, the user selects the ammonite family Dactylioceratidae by highlighting it and releasing the mouse button, all specimens of the family in the database will be retrieved. Each item itself in the family menu has a pull-right menu such that if the user pulls right from the item Dactylioceratidae, a genus list for the family would appear (Fig. 6-2). Suppose that Dactylioceras is selected, then the screen shown in Phymatoceratldae < \ Collina Graphoceratidae f j Dactytoceras Sonninlldae r Cardioceratidae i Erycitidae f Porpoceras Kosmoceratidae Otoltidae t Sphaeroceratidae r R e y n e s o c e r a s Stephanoceratidae t Oppeliidae Perisphinctidae Reineckelidae Discophyllitidae l Phylloceratidae Lytoceratidae r • — — M Nodlcoeloceras Peronoceras Preperonoceras Prodactyiioceras • Zygodactylies Figure 6-2 Family Menu (Left) Genus submenu of Dactylioceratidae Amnion Image Database Display Image Window Figure 6-3 The retrieval results of Dactylioceras An Aid to Identification Fig. 6-3 would be the query result. The top-right window records the query text and gives the number of images retrieved and the number remained to display. Images are displayed in order of size for efficient utilization of the screen space and the user can go to next screen of images by pressing the Next Page with the left mouse button and back to previous screen by pressing the Previous Page button. A user Figure 6-4 Stage Menu (Left) ESI : E ; Bajocian r : Aalenian r-Toarcian r Pliensbachian r Sinemunan r ESI NKJ Spinatum H6ttangian r- N< Davoef Ibex Jamesoni interested in a specific specimen can click on the image with the left mouse button which will display all information related to the specimen in the middle-right text window (Fig. 6-3). A user interested in the species to which the specimen belongs and wants to examine the intraspecific variation can mark the specimen with the middle mouse button and click on the Speci Sublist (Fig. 6-3). The user can return to the genus level by clicking on the Main List button. Exercises such as this enable the user to get familiar with a particular taxonomic group very quickly. 2. Stratigraphy The Stratigraphy button has a two-level menu. The top level is the stage menu (Fig. 6-4) which lists the four Lower Jurassic stages and two of the Middle Jurassic stages. Each stage has a pull-right menu which shows the zones (northwest Europe scheme) in the stage. The user can scan the Zone Submenu of Pliensbachian Cn yn?ry I , I Country 3ritain nada tile lina Ecuador linCS::;: Jermany jreece «|ngary Ireland Japan Madagascar rfexico 3ortugal m lussia Saudi Arabia Switzerland Jriited States Figure 6-5 Country Menu 123 An Aid to Identification 124 falcoid falcate biconcave projected Figure 6-6 Morphology Menu (Left), Rib Submenu (Middle) and Rib Form Sub-submenu (Right) database by zone and get some idea of how ammonite morphology changes through time. 3. Geography The user can explore morphological and temporal changes of ammonite taxa in different parts of the world by using Geography as query criterion, he or she can retrieve ammonites by geographic region or country (Fig. 6-5). There are five geographic regions: Northwest Europe, Western Tethyan, Western Pacific, North America and South America each of which has thousands of specimens in the database and could easily overwhelm the user. Geographic regions are most commonly used with other criteria to narrow a search. 4. Morphology Morphology is one of the two foundations for fossil identification. The user can also search the database using morphological characters such as the degree of involution, shell expansion rate, rib form & furcation pattern, tubercle pattern, whorl shape and ventral geometry (Fig. 6-6). If the images displayed in the graphics window are fuzzy or do not have An Aid to Identification 125 Reference §9 ArkeilEtc 1957 Atlas Ed. ByRepin 1968 Crickmay Dean, Donovan, Howarth 1961 Freboid Gabb1869 Geczy 1976 lillex Hall and Westerman 1980 Hlllebrandt imlay 1968 Jakobs1992 Mclearn 1932 dferien 1985 Poulton ; Quinzio Sinn 1987 Schlatter 1991 Smith 1976 • Smith and Tipper Taylor 1988 Tilmann 1917 Wang and Smith 1986 Whiteaves 1884 Wiedenmayer 1980 Reference H i • : • • • • : . • : • • • • : • • • . . • : • . • : • : • : • : • : • : • : • : • : • • • • • • . • • • • : • • : • • : • . • • . . Arthur 1985 8iascoT978 \ Dagis ; Erben1956 Freboid and Mountjoy etc 1967 iGabilly 1976 | Geyer I Hall 1987 j Half and Howarth 1983 ! Hirano Imlay 1981 i Kalacheva 1980 I Meister 1986 I Palfy 1991 | Poulton And TipperT991 I Repin 1974 | Schiegelmilch 1976 i Smith 1981 ! Stankevich1964 ! Thomson And Smith 1992 j Tipper and Smith etc 1991 j White 1889 : Wiedenmayer 1977 : Others Figure 6-7 Reference Menu the right brightness, the user can adjust them using the Brightness and Contrast sliders in the command window. 5. Reference A user interested in a specific person's work can query the database by Reference (Fig. 6-7) which has a two-column author menu with authors arranged in alphabetic order and the list will grow as new references are added to Ammon. 6. Combination An Aid to Identification 126 The Taxonomy, Stratigraphy, Geography, Morphology and Reference menu system offers the user easy access to the database but at the same time reduces flexibility because the user can only search the database in one area of inquiring at a time and the file that lists all menu items needs to be updated whenever new character states are added. For any serious application, a combination of the above search criteria is needed as provided by the Combination button in the command window (Fig. 6-3). Suppose that the illustrations in the start-up screen are of interest and the user wants to know the species name and the locality where the specimen was collected. The user composes a query using the morphological features available from the image: a carinate venter, 13 ribs per half whorl at a shell diameter of 12 cm, the average trend of ribs is gently rursiradiate, no tubercles. Taking into account measurement error, the query is typed into the search field in the top-right text window as : venter=carinate and prhw>10 and prhw<16 and d>10 and d<14 and ptrend=grursiradiate and tuberc=no and the Combination button pressed to search the database. The response to the query (Fig. 6-8) shows the specimen that appears in the start-up screen, click on it with the left mouse button, all information related to this specimen is displayed in the middle-right window: the specimen is named as Agassiceras scipionianum and was collected from southwest Germany. With the Save Image As button and the File: name field, the user can save the whole or any part of the graphics window (using mouse button to mark the region of interest) as a file for later reference or print out. The textual information displayed in the middle-right window can be saved as an ASCII file using the pull-right menu of the window, so that the information is available to other applications. Amrnon Image Database Display Image Window Figure 6-8 The retrieval of the specimen in the start-up screen An Aid to Identification 128 6.3 Examples It would be interesting to see what kind of role that Ammon can play and how effective it can be in dealing with the problem of fossil identification. A colleague of mine, Genga Nadaraju of the UBC Paleontology Lab has just finished her Master's thesis entitled "Triassic-Jurassic biochronology of the eastern Iskut River map area, northwestern British Columbia" but the illustrations and taxonomic descriptions of her ammonite collections have not yet been entered into Ammon. Most of the ammonite specimens from Nadaraju's collection are poorly preserved and fragmentary thereby providing a challeging test of the system. 1. Example 1 - Fig. 6-9 (Nadaraju 1993, Plate V, Fig. 1 ) Measurements (From Nadaraju 1993, p.98): SPECIMEN C-201415a D(cm) «8.53 UD (cm) 5.00 U 0.58 PRHW 33 Description: Evolute form with a wide umbilicus. Flanks slightly convex and ornamentation consisting of numerous simple ribs that trend prorsiradiately on the outer part of the flanks. A query based on the above measurements and description can be composed: U>0.55 and UO.62 and UD>4 and PRHW>25 and PRHW<40 and PTREND like prorsiradiate and FURC=no and TUBERC^no. Each character in the query is Figure 6-9 Plate V, Fig. 1 of Nadaraju 1993 given a range centering around the Amnion Image Database Retrieve by: Display Image Window H1.55 and iKO'.Bl 25 and prhui<40 and ud>4 and ptrend like [EMREiETEi. Geoqraphv => D: 13.59 LIB: 7.7b LI: 0.58 EXP: 1.58 WH: 3.1 shallow. VENTER:carinate-sulcate. PTP.END:prors1rai ie. IBWIDTH: 0.10 EXPO: 1.71 VOLUTIOND: 0.13 Figure 6-10 Query results of Example 1 H ^o An Aid to Identification 130 measured value as well as taking into account the measurement errors and intraspecific variations. For example, "PTREND like prorsiradiate" would include specimens with either prorsiradiate ribs or gently prorsiradiate ribs. As result of the query, 5 specimens are retrieved from the database. Fig. 6-10 shows the first two specimens and by clicking on the left specimen with the left mouse button, all textual information related to it appears in the middle-right window: a Paracaloceras multicostatum from Upper Hettangian and Lower Sinemurian. Paracaloceras cf multicostatum was the identification made by Nadaraju (1993). The other four candidates are : Paltechioceras yakounense, Paltechioceras harbledownense, Echioceras aklavikense, Leptechioceras alvarezi, all from Upper Sinemurian If it is known that the specimen is from Hettangian or Lower Sinemurian, then Paracaloceras multicostatum offers the best candidate. Example 2 - Fig. 6-11 (Nadaraju 1993, Plate VI, Fig. 1 ) Measurements SPECIMEN C-201631b D(cm) «14 U 0.73 W 1.46 PRHW «36 Description: Evolute, ellipsoidal shell with many whorls. Ornamentation consists of simple ribs that are dense. No keel observed due to the state of preservation. A query based on the above measurements and description can be composed: U>0.67 and W<1.5 and PRHW>30 and D>12 and FUROno which leads to retrieval of four specimens from the database and the first one of which (Fig. 6-12) is Alsatites cf. proaries, the identification made by Nadaraju (1993). The other candidates are : Alsatites liasicus from the Middle Hettangian and Coroniceras longidomus from the Lower Sinemurian. An Aid to Identification 131 &£TO'' t§6 MI* % r-tb ^ 7 * . ~v ft.- rt* **i^Ji^s Figure 6-11 Plate VI, Fig. 1 of Nadaraju 1993 Amman Image Database Display Image Window Figure 6-12 Query results of Example 2 An Aid to Identification 133 Example 3 - Fig. 6-13 (Nadaraju 1993, Plate VIII, Fig. 1 ) Measurements SPECIMEN C-201453 D(cm) «4.2 U 0.42 WWWH 1.00 PRHW 13 Description: Midvolute form with an elliptical whorl section reaching its greatest width near the middle of the flank. Each whorl embraces nearly half of the preceding one. Rounded, plain venter. Ornamentation consists of straight ribs that arise at the umbilical shoulder becoming progressively sharper and thicker to mid-flank and then fading at the ventro-lateral shoulder. A query can be formulated as: U>0.37 and U<0.47 and WWWH>0.85 and WWWH<1.2 and PRHW>10 and PRHW<16 and D>3 and D<6 and VENTER=plain and TUBERC=no Fig. 6-14 shows the query result. Most of the specimens have ribs that cross the venter which does not fit the above description. The only two species that have unornamented venters are Badoiaia canadensis and Franziceras coronoides. The former has ribs that gradually fade whereas the latter has ribs that terminate suddenly at the ventro-lateral shoulder. Fig. 6-13 is probably a Badoiaia canadensis, the identification made by Nadaraju (1993). Rib strength change across flank can be perceived easily by the human eye but it is difficult to describe in rigid morphological terms that can be used in a computerized database. In order to maximize the benefit and minimize the potential for errorious conclusions, it is clear that human and computer interaction is the best approach to identification. Fig. 6-13 Plate VIII, Fig. 1 of Nadaraju 1993 Ammori Image Database Display Image window Retrieve by: and D<6 and VENTER=plain and TUB! •lumber of Imaqes Remained to Dieplav: 0 Figure 6-14 Query results of Example 3 An Aid to Identification 135 In summary, Amnion can be very useful in assisting identification of Lower Jurassic ammonites. Instead of memorizing thousands of species, the user need only to know a dozen morphological descriptors and a few database operators such as AND, OR, NOT, LIKE, IN. A new user of Ammon may need to measure a few quantitative morphological parameters but after some practices the user should be able to build up a sense of relationship between quantitative and qualitative parameters. At this point identification becomes fun. A computerized ammonite image database cannot replace the human expert but does alleviate the burden of memorizing many species and associated data allowing the user to focus on more important questions The following figures show the variations of basic shell geometry for Lower Jurassic ammonite genera which aims to define these genera more objectively; similar plots for species are not made due to space limitations. 136 Figure 6-15 Shaded boxs show the range of expansion rate for each genus, the figures in the bracket show number of specimens in each genus I Coeloceras(87) Catacoeloceras(11) Canavaria(46)_ Caloceras(11) Brodieia(4) Brasilia(2) Bifericeras(21) Aveyroniceras(44) Asteroceras(41) Arnioceras(154) Arieticeras(144) Apoderoceras(13) Androgynoceras(71) Amaltheus(264) Alsatites(14) Aegoceras(49) Acanthopleuroceras(79) 137 Figure 6-16 Shaded boxes show the range of expansion rate for each genus, the figures in the bracket show number of specimens in each genus Gagaticeras(8) Frechiella(6) Fontanelliceras(22) Fanninoceras(98) Eudmetoceras(21 EsericerasO) Erycites(2) Epideroceras(16) Eoderoceras(15) Eleganticeras(36) Dumortieria(51) Discamphiceras(18) Dayicerasd 1) Dactylioceras(200) Cycl icocerasd Costileiocerasd) Collina(20) W 138 Figure 6-17 Shaded boxes show the range of expansion rate for each genus, the figures in the bracket show number of specimens in each genus o Oregonites(IO) Nodicoelocerasd6) Nejdiad) Miltoceras(4) Metarniocerasd) Mercaticeras(5) Liparoceras(50) Leukadiella(14) Leptaleoceras(98) Laqueoceras(5) Hyperliocerasd) Hudlestonia(6) HildaitoidesO) Haugia(55) Haplopleurocerasd) Graphoceras(2) Gleviceras(48) 139 Figure 6-18 Shaded boxes show the range of expansion rate for each genus, the figures in the bracket show number of specimens in each genus I Pseudasterocerasd) Protogrammoceras(256) Promicroceras(6) Praesphaerocerasd) Pompeckiocerasd) Polymorphites(37) Podagrosiceras(5) Pleuroceras(47) Planammatoceras(21) Phymatoceras(98) Phlyseogrammocerasd 8) Peripleuroceras(3) Paroniceras(7) Parapsilocerasd) Paradiscamphiceras(2) Paltechioceras(120) Oxynoticeras(38) 140 Figure 6-19 Shaded boxes show the range of expansion rate for each genus, the figures in the bracket show number of specimens in each genus CO Yakounia(20) Waehneroceras(45) Uptonia(48) Transipsiloceras(l) Tmaegophiocerasd) Tiltoniceras(41) Taffertiad) Sulciferites(48) Sphenarpitesd) Slatteritesd) Saxoceras(6) Reynesoceras(53) Renzicerasd) Puchenquia(21) Psiloceras(92) Pseudoskirroceras(6) Pseudolioceras(206) 141 Figure 6-20 Shaded boxes show the range of whorl overlap (U) for each genus, the figures in the bracket show number of specimens in each genus 00 I Coeloceras(87) Catacoelocerasd 1) Canavaria(46) Calocerasd 1) Brodieia(4) Brasilia(2) Bifericeras(21) Aveyroniceras(44) Asteroceras(41) Arnioceras(154) Arieticeras(144) Apoderoceras(13) Androgynoceras(711 Amaltheus(264) Alsatites(14)~ Aegoceras(49) Acanthopleuroceras(79) =ZT • U ^ E£ ¥ ? 5L 2 . ^ —*-—•—•—*—uy /• ~ ^ 5 S" 3> _ -5 ^ ~ E 2 X 0.1 0.2 0.3 0.4 U 0.5 0.6 0.7 0.8 142 Figure 6-21 Shaded boxes show the range of whorl overlap (U) for each genus, the figures in the bracket show number of specimens in each genus 05 1 Gagaticeras(8) Frechiella(6) Fontanelliceras(22) Fanninoceras(98) Eudmetoceras(21) EsericerasO) Erycites(2) Epideroceras(16) Eoderoceras(15) Eleganticeras(36) Dumortieria(51) Discamphiceras118) Dayicerasd 1) Dactylioceras(200) Cycl icocerasd) Cost i le iocerasd) Collina(20) 143 Figure 6-22 Shaded boxes show the range of whorl overlap (U) for each genus, the figures in the bracket show number of specimens in each genus O Oregonites(IO) Nodicoeloceras(16) Nejdiad) Miltoceras(4) Metarniocerasd Mercaticeras(5) Liparoceras(50) Leukadiella(14) Leptaleoceras(98) Laqueoceras(5) Hyperliocerasd Hudlestonia(6) HildaitoidesO) Haugia(55) Haplopleurocerasd Graphoceras(2) Gleviceras(48) 0.8 144 Figure 6-23 Shaded boxes show the range of whorl overlap (U) for each genus, the figures in the bracket show number of specimens in each genus I Pseudasterocerasl 1) Protogrammoceras(256) Promicroceras(6) Praesphaeroceras( 1 Pompeckiocerasd) Polymorphites(37) Podagrosiceras(5) Pleuroceras(47) Planammatoceras(21 Phymatoceras(98) Phlyseogrammocerasd 8) Peripleuroceras(3) Paroniceras(7) Parapsilocerasd) Paradiscamphiceras(2) Paltechiocerasd 20) Oxynoticeras(38) 0.8 145 Figure 6-24 Shaded boxes show the range of whorl overlap (U) for each genus, the figures in the bracket show number of specimens in each genus 05 I Yakounia(20) Waehneroceras(45) Uptonia(48) Transipsiloceras(1 Tmaegophioceras( 1 Tiltoniceras(41 Taf fer t iad) Sulciferites(48) Sphenarpitesd Slat ter i tesd) Saxoceras(6) Reynesoceras(53) Renzicerasd Puchenquia(21 Psiloceras(92) Pseudoskirroceras(6) Pseudolioceras(206) 0.8 146 Figure 6-25 Shaded boxes show the range of WWWH for each genus, the figures in the bracket show number of specimens in each genus 1 o Coeloceras(87) Catacoelocerasd 1) Canavaria(46) Calocerasd 1) Brodieia(4) Brasilia(2) Bifericeras(21) Aveyroniceras(44) Asteroceras(41) Arnioceras(154) Arieticeras(144) Apoderoceras(13) Androgynoceras(71) Amaltheus(264) Alsatites(14) Aegoceras(49) Acanthopleuroceras(79) r 0 c XT fi 0 A Q f / l> f -0 r 0.5 1.5 W W W H 2.5 147 Figure 6-26 Shaded boxes show the range of WWWH for each genus, the figures in the bracket show number of specimens in each genus a O Fuciniceras(161 FranzicerasO) Fieldingiceras(3) Exomilocerasd Eudmetoceras(21) EsericerasO) Erycites(2) Epideroceras(16) Eoderoceras(15) Eleganticeras(36) Dumortieria(51 Discamphicerasd 8) Dayicerasd 1 Dactylioceras(200) Cycl icocerasd Costi leiocerasd Collina(20) 148 Figure 6-27 Shaded boxes show the range of WWWH for each genus, the figures in the bracket show number of specimens in each genus 6 Onychocerasd) Neolioceratoides( 19) Mullerites(2) Microderocerasd 6) Metaderoceras(83) Ludwigia(14) Lioceratoides(34) Leptechioceras(29) Leioceras(29) Kammerkarocerasd) Hyperderocerasd 6) Hildoceras(55) Hildaites(51) Harpoceras(165) Hammatoceras(28) Grammoceras(47) Gemmellarocerasd 2) 149Figure 6-28 Shaded boxes show the range of WWWH for each genus, the figuresin the bracket show number of specimens in each genusPseudaetomoceras(1)Protechioceras( 1)Prodactylioceras(37)Praesphaeroceras(1)Pompeckioceras(1)Polymorphites(37)Podagrosiceras(5)Pleuroceras(47)Planammatoceras(21)Phymatoceras(98)Phlyseogrammoceras(1 8)Peripleuroceras(3)Paroniceras(7)Parahildaites(3)Paracymbites(1)Palaeoechioceras(3)Ovaticeras(8)0 0.5 1 1.5 2 2.5 3WWWII150Figure 6-29 Shaded boxes show the range of WWWH for each genus, the figuresin the bracket show number of specimens in each genus-: --I--IJI,I-L)VI-IJ IYakounia(20)Waehneroceras(45)Uptonia(48)Transipsiloceras(1) -Tmaegophioceras(1 ) -Tiltoniceras(41 ) -Taffertia(1)Sulciferites(48)Sphaerocoeloceras(6) -Schlotheimia(40)Reynesocoeloceras(21)Reynesella(1)Radstockiceras(34)Psilophyllites(7)Pseudotropites(1)Pseudomercaticeras(5)Pseudogrammoceras(72)I____--- IIIE_cI I I I I0 0.5 1 1.5 2 2.5 3WWWHSummary and Conclusions 151Chapter 7 Summary and ConclusionsThis thesis presents the first computerized image database for ammonites whichallows automated measurement of morphological parameters from images. The databaseAmmon contains 7790 specimens representing 15 Lower Jurassic arnmonite families, 179genera and 1319 species. Each specimen has 102 descriptors covering taxonomy, quantitativemorphology, qualitative morphology, stratigraphy, locality and general comments. Computerimage analytical teclmiques are used to derive morphological parameters from images in thedatabase and a graphics interface is implemented to give the user easy access.Elliptical Fourier representation is used to quantify whorl shape for the first timewhich allows the construction of intermediate whorl shapes and the theoretical extension ofmorphologic trends beyond the forms available. Fourier representation of whorl shapeenables a more objective documentation and comparison of whorl shape variations withinand among taxa.The species density diagrams for Lower Jurassic ammonites are plotted with respectto basic shell geometry. The distributions are strikingly similar to those for Mesozoicammonoids in general, being largely concentrated on low W and high U regions andsuggesting the same geometrical restraints. The data show strong correlations among basicgeometric parameters (W, U, WWWH) which may be related to restrictions imposed by theshape and relative size of the whorl. This has been approached mathematically.Preliminary study of morphological and stratigraphical data from Ammon suggests apossible correlation between basic shell geometry, morphological variability and taxaduration. Low within-population morphological variabilities and short durations areassociated with taxa that inhabit the most densely populated region of low W and high U.Summary and Conclusions 152 Away from this peak in faster expanding regions, there is a steady increase in both morphological variability and taxa longevity implying a decrease in selective pressure. The inter-relationships of shell expansion rate, degree of involution, whorl shape, ribs, tubercles and venter have been studied using the Amnion database. A few covariations have been observed and documented quantitatively. The major covariation patterns are: (a) Faster expanding shells tend to be more involute, involute shells are more compressed than evolute shells, and compressed shells have finer ribs, (b) The frequency of shells with tubercles increases if ribs furcate, (c) Tubercles of compressed shells tend to be on the lower flank whereas tubercles of depressed shells tend to be on the upper flank, (d) Shells with sinuous ribs are more involute and more compressed than shells with straight ribs, (e) There is a positive correlation between tuberculation and rib strength, (f) The frequency of shells with a keels increases in shells that are compressed, or have a small fineness ratio. Some interpretations and speculations for these covariations are given. The taxonomic diversity of Lower Jurassic ammonites peaks first at the family level in the Ibex Zone, followed by generic data one zone later, and finally species in the Margaritatus Zone implying a delay in radiation for lower levels of ammonite taxa. The late Sinemurian and early Pliensbachian have high family origination rates and relatively low species diversities; species reach their highest diversity level in the late Pliensbachian, which also has the highest family extinction rate and an almost zero origination rate. The data support the claim (Raup and Sepkoski 1986) that the Pliensbachian is a time of mass extinction. Furthermore, the data indicate that the extinction event happened in the Late Pliensbachian and was gradual for ammonites at the family level. Two morphological diversity indexes are used to study changes through time. The range index describes the range of the morphospace occupied. The Shannon Index measures both the range and the evenness of the occupation. Both indexes indicate a similar pattern. Summary and Conclusions 153 There is a rapid rise to an early Sinemurian maximum through morphological radiation especially in terms of the basic shell geometry, followed by a pronounced fall in the middle of Sinemurian with diversity remaining relatively high and stable thereafter. The data also show that Pliensbachian and Toarcian ammonites have significantly higher ornamentation diversities than earlier forms in the Hettangian and Sinemurian. It is evident by comparing taxonomic and morphological diversity changes through time that initial morphological diversification in Lower Jurassic ammonites far exceeded the proliferation of lower-level taxa. The most striking fact emerging from the comparison is that the morphological diversity of the Bucklandi Zone with 46 species is higher than that of the Margaritatus Zone with 177 species. It demonstrates that morphological diversity need not increase as taxonomic diversity increases. "Such morphological stagnation indicates taxonomic diversification that is highly constrained morphologically" (Foote 1993). There are two interesting observations although the resolution and type of my data does not warrant firm conclusions: (1) All Lower Jurassic ammonite families that radiate into numerous species in the first zone of their occurrence have durations of less than 4 zones; in other words, rapid origination is associated with short duration. (2) The mean maximum shell diameters of species within families and superfamilies show synchronized drops in the Oxynotum Zone and Ibex Zone. Interestingly, these two zones show high family origination rates and relatively low species diversities. Finally a few specimens collected from the Iskut River map area are used to test Amnion as a tool for identification; the results are encouraging. References 154 References Ackerly, S. C. 1989. Kinematics of accretionary shell growth with examples from brachipods and molluscs. Paleobiology 15 : 147-164. Anstey, R. L. and Delmet, D. A. 1973. Fourier analysis of zooecial shapes in fossil tubular bryozoans. Geological Society of America Bulletin 84: 1753-1764. Arkell, W. J., Kummel, B. and Wright, C. W. 1957. Mesozoic ammonoidea. in The Treatise on Invertebrate Paleontology (Moore, R. C , ed.), University of Kansas Press. Arnold, A. J. and Fristrup, K. 1982. The theory of evolution by natural selection: a hierarchical expansion. Paleobiology 8(2): 113-129. Anonymous 1990a. Introduction to SQL by Oracle Corporation. — 1990b. SQL*Loader User's Guide (Version 1.0) by Oracle Corporation. — 1990c. SQL Language Reference Manual (Version 6.0) by Oracle Corporation. Arthur, A.J. 1985. Biostratigraphy of the Lower to Middle Jurassic sediments, Ashcroft area, south central British Columbia. B.Sc. thesis, University of British Columbia. — 1987. Mesozoic stratigraphy and paleontology of the west side of Harrison Lake, southwestern British Columbia. M.Sc. thesis, University of British Columbia. Arthur, A., Smith, P. L., Monger, J. W. and Tipper, H. W. 1992: Mesozoic stratigraphy and Jurassic paleontology west of Harrison Lake, southwestern British Columbia. Geological Survey of Canada Bulletin 441. Batt, R. J. 1989. Ammonite shell morphotype distributions in the Western Interior Greenhorn Sea and some paleoecological implications. Palaios 4: 32-42. Bayer, U. 1985. Pattern recognition problems in geology and paleontology. Berlin: Springer-Verlag. Bayer, U. and McGhee, G. R. 1984. Iterative evolution of Middle Jurassic ammonite faunas. Lethaia, 17: 1-15. — 1985. Evolution in marginal epicontinental basins: the role of phylogenetic and ecological factors, in Sedimentary and Evolutionary Cycles (Bayer, U. and Seilacher, A., eds.) p. 164-215, Springer-Verlag, Berlin. References 155 Beerbower, J. Jordan, D. 1969. Application of information theory to paleontologic problems: taxonomic diversity. Journal of Paleontology, 43(5): 1184-1198. Billings, E. 1873. On the Mesozoic Fossils from British Columbia collected by Mr. James Richardson in 1872. Geological Survey of Canada, Report of Progress, 1872-1873, p. 71-75. Blasco, G., Levy, R. and Nullo, F. 1978. Los amonites de la formacion Osta Arena (Liasico) y su posicion estratigrafica-Pampa de Agnia-(Provincia del Chubut): VII Congreso Geologico Argentino, Neuquen, Actas, 2: 407-429. Benson, R. H., Chapman, R. E. and Siegel, A. F. 1982. On the measurement of morphology and its change. Paleobiology 8: 328-339. Bisby, F. A. 1983. Information services in taxonomy. In Allkin, R. and Bisby, F. A. eds. Databases in Systematics. Canfield, D. J. and Anstey, R. L. 1981. Harmonic analysis of Cephalopod suture patterns. Mathematical Geology 13: 23-35. Canny, J. 1986. A computaional approach to edge detection. IEEE Trans, on pattern analysis and machine intelligence 8: 679-697. Chamberlain, J. A. 1976. Flow patterns and drag coefficients of cephalopod shells. Paleontology 19(3): 539-563. — 1981. Hydromechanical design of fossil cephalopods In: House, M. R. and Senior, J. R. eds. The Ammonoidea. Systematics Association Special Volume 18: 289-336. Checa, A. 1987. Morphogenesis in ammonites - differences linked to growth pattern. Lethaia 20: 141-148. Checa, A. and Westermann, G. E. G. 1989. Segmental growth in planulate ammonites: inferences on coastal function. Lethaia 22: 95-100. Christopher, R. A. and Waters, J. A. 1974. Fourier series as a quantitative descriptor of miospore shape. Journal of Paleontology 48: 697-709. Clark, M. W. 1981. Quantitative shape analysis: a review. Mathematical Geology 13: 303-320. Cleynenbreugel, V. et al 1988. Knowledge-based road network extraction on SPOT satellite images. 4th International Conference on Pattern Recognition. References 156 Conrad, M. A. and Beightol, D. S. 1988. Expert systems identify fossils and manage large paleontological databases. Geobyte, No. 2 : 42-46. Crickmay, C.H. 1925: A note on two of Hyatt's Liassic ammonites. Proceedings of the California Academy of Sciences, fourth series, 14: 77-81. — 1928: The stratigraphy of Parson Bay, British Columbia. University of California Publications, Bulletin of the Department of Geological Sciences , 18: 51-70. — 1932 : A new Jurassic ammonite from the Coast Ranges of California. American Midland Naturalist, 13:1-7, pi. 1-2. — 1932-1933: Some of Alpheus Hyatt's unfigured types from the Jurassic of California. United States Geological Survey, Professional Paper 175-B: 51-64, pi. 14-18. — 1933: Mount Jura investigation. Bulletin of the Geological Society of America, 44: 895-926, pi. 23-34. Dagis, A.A. 1968. Toarcian Ammonites (Dactylioceratidae) from northern Siberia. U.S.S.R. Academy of Sciences, Siberian Branch, Transactions of the Institute of Geology and Geophysics, no. 40, 108 p., 12 pi. — 1971. On the Toarcian-Pliensbachian boundary and zonation of the Lower Toarcian sediments in the northeastern U.S.S.R.. Geologiya i Geofizika, no. 5 (136), p. 128-132. ~ 1974. Toarcian ammonites (Hildoceratidae) from northern Siberia. U.S.S.R. Academy of Sciences, Siberian Branch, Transactions of the Institute of Geology and Geophysics, no. 99, 188 p., 19 pi. — 1976. Late Pliensbachian ammonites (Amaltheidae) of the North Siberia: Publishing House, Nauka, Siberian Branch, Novosibirsk, 79 p., 17 pi. (in Russian). Davis, J. C. 1986. Statistics and data analysis in geology. New York: Wiley. Dawson, G.M. 1880. Queen Charlotte Islands. Geological Survey of Canada, Report of Progress, 1878-1879. Dean, W.T., Donovan, D.T. and Howarth, M.K. 1961. The liassic Ammonite zones and subzones of North-West european province. Bulletin of the British Museum (Natural History), 4(10), p. 437-505, pi. 63-74. Doguzhaeva, L. 1982. Rhythms of ammonoid shell secretion. Lethaia 15: 385-394. References 157 Dommergues, J. L. 1988. Can ribs and septa provide an alternative standard for age in ammonite ontogenetic studies ? Lethaia 21: 243-256. Donovan, D.T. 1964. Cephalopod phylogeny and classification. Biology Review 39: 259-287 — 1985. Ammonite shell form and transgression in the British Lower Jurassic in Sedimentary and Evolutionary Cycles (Bayer, U. and Seilacher, A., eds.) p. 48-57, Springer-Verlag. Berlin. Donovan, D.T., Callomon, J.H. and Howarth, M.K. 1981. Classification of the Jurassic Ammonitina. in The Ammonoidea, (House, M.R. and Senior, J.R., eds.), Systematics Association, Special Publication 18, Academic Press, p. 101-155. Ehrlich, R. 1983. Comments on the validity of Fourier descriptors in systematics: a reply to Bookstein. Systematic Zoology 32 : 202-206. Erben, H.K. 1956: El Jurasico inferior de Mexico y sus amonitas. XX Congreso Geologico Internacional, 393 p. Foote, M. 1989. Perimeter-based Fourier analysis: a new morphometric method applied to the trilobite cranidium. Journal of Paleontology 63(6): 880-885. — 1991. Morphologic patterns of diversification: examples from trilobites. Paleontology 34(2): 461-485. — 1992. Rarefaction analysis of morphological and taxonomic diversity. Paleobiology 18(1): 1-16. — 1993. Discordance and concordance between morphological and taxonomic diversity. Paleobiology 19(2): 185-204. Frebold, H. 1951: Lowermost Jurassic Fauna in Whitesail Lake map-area, British Columbia, in Contributions to the Palaeontology and Stratigraphy of the Jurassic System in Canada, Geological Survey of Canada Bulletin 18: 18-21, 1 pi. — 1957: The Jurassic Fernie Group in the Canadian Rocky Mountains and Foothills. Geological Survey of Canada Memoir 287:1-197,44 pi. — 1958. Stratigraphy and correlation of the Jurassic in the Canadian Rocky Mountains and Alberta Foothills, in Jurassic and Carboniferous of Western Canada, American Association of Petroleum Geologists. ~ 1959: Marine Jurassic rocks in Nelson and Salmo areas southern British Columbia. Geological Survey of Canada, Bulletin 49: 31 p., 5 pi. References 158 — 1960. The Jurassic faunas of the Canadian Arctic (Lowermost Jurassic and lowermost Middle Jurassic ammonites). Geological Survey of Canada, Bulletin 59: 1-33, pi. 1-15. — 1964a: Lower Jurassic and Bajocian ammonoid faunas of northwestern British Columbia and southern Yukon. Geological Survey of Canada Bulletin 116: 31 p. 8 pi. ~ 1964b: Illustrations of Canadian fossils Jurassic of Western and Arctic Canada. Geological Survey of Canada, Paper 63-4: 1-107, pi. 1-51. — 1966: Upper Pliensbachian beds in the Fernie Group of Alberta. Geological Survey of Canada, Paper 66-27: 1-7, 1 pi. — 1967a: Hettangian ammonite faunas of the Taseko lakes area British Columbia. Geological Survey of Canada, Bulletin 158: 1-35, pi. 1-9. — 1967b: Position of the Lower Jurassic genus Fanninoceras McLearn and the age of the Maude Formation on Queen Charlotte Islands. Canadian Journal of Earth Sciences, 4: 1145-1149. — 1970: Pliensbachian ammonoids from British Columbia and Southern Yukon. Canadian Journal of Earth Sciences, 7: 435-452, pi. 1-4. — 1975. The Jurassic faunas of the Canadian Arctic (lower Jurassic ammonites, biostratigraphy and correlation) Geological Survey of Canada, Bulletin 243, 24 pps., 5 pi. — 1976: The Toarcian and Lower Middle Bajocian beds and ammonites in the Fernie Group of southeastern British Columbia and parts of Alberta. Geological Survey of Canada Paper 75-39 : 20 p., 9 pi. Frebold, H. Mountjoy, E.W. and Tempelman-Kluit, D. 1967. New occurrences of Jurassic rocks and fossils in central and northern Yukon. Geological Survey of Canada, Paper 67-12 Frebold, H. and Tipper, H.W. 1969. Lower Jurassic rocks and fauna near Ashcroft, British Columbia and their relation to some granitic plutons (92-1). Geological Survey of Canada, Paper 69-23: 20 p., 1 pi. Frebold, H. and Tipper, H.W. 1970. Status of the Jurassic in the Canadian Cordillera of British Columbia, Alberta and Southern Yukon. Canadian Journal of Earth Sciences, 7(1): 1-21. Frebold, H., Tipper, H.W. and Coates, J.A. 1969. Toarcian and Bajocian rocks and guide ammonites from Southwestern British Columbia. Geological Survey of Canada, References 159 Paper 67-10: 55 p., 6 pi. Gabb, W.M. 1869. Descriptions of some secondary fossils from the Pacific Coast States. American Journal of Conchology, 5: 5-18, pi. 3 . Gabilly, J. 1975. Evolution et systeque des Phymatoceratinae et des Grammoceratinae (Hildocerataceae Ammonitina) de la region de Thouars, stratotype du Toarcien. Memoires de la Societe Geologique de France, no. 124, Nouvelle Serie, tome LIV, p. 1-196, pi. I-XXXVI. — 1976. Le Toarcien a Thouars et dans le centre-ouest de la France - biostratigraphie -evolution de la faune (Harpoceratinae, Hildoceratinae). Les Stratotypes Francais, Publications du Comite Francais de Stratigraphie, 3: 1-217, pi. 1-29. Geczy, B. 1976. Les ammonitines du Carixien de la Montagne du Bakony. Akademiai Kiado, Budapest. 223 p. Geyer, O. F. 1974. Der Unterjura (Santiago-Formation) von Ekuador. Neues Jahrbuch fur Geologie und Palaontologie, Monatshefte, 9: 525-541. Geyer, O. F. 1979. Ammoniten aus dem tiefen Unterjura von Nord-Peru. Palaontologische Zeitschrift, 53: 198-213. Gould, S. J. 1991. The disparity of the Burgess Shale arthropod fauna and the limits of cladistic analysis: why we must strive to quantify morphospace. Paleobiology 17(4): 411-423. Gregory, S. 1963. Statistical methods and the geographer. Longmans, Green and Co. Ltd. Guex, J. 1980. Remarques preliminaires sur la distribution stratigraphique des ammonites hettangiennes du New York Canyon (Gabbs Valley Range, Nevada). Bulletin de Geologie Lausanne, 250: 127-140. — 1981. Quelques cas de dimorphisme chez les ammonoides du Lias inferieur. Bulletin Soc. Vaud. Sc. Nat., 75:239-248. ~ 1989. Note sur le genre Franziceras Buckman (Ammonoidea, Cephalopoda). Bulletin de Geologie Lausanne, 305:347-354. Hall, R.L. 1987. New Lower Jurassic ammonite fauna from the Fernie Formation, southern Canadian Rocky Mountains. Canadian Journal of Earth Science, 24: 1688-1704, 5 pi. Hall, R.L. and Howarth, M.K. 1983. Protogrammoceras paltum (Buckman), a late Pliensbachian (Jurassic) ammonite from Axel Heiberg Island, Canadian Arctic Archipelago. Canadian Journal of Earth Sciences, 20: 1470-1475. References 160 Hall, R.L. and Westermann, G.E.G. 1980. Lower Bajocian (Jurassic) cephalopoda faunas from Western Canada and proposed assemblage zones for the Lower Bajocian of North America. Palaeontographica Americana, v. 9(52): 1-93, pi. 1-15. Hallam, A. 1985. Jurassic moUuscan migration and evolution in relation to sea level changes. in Sedimentary and Evolutionary Cycles (Bayer, U. and Seilacher, A., eds.) p. 4-5, Springer-Verlag, Berlin. — 1986. The Pliensbachian and Tithonian extinction events. Nature 319: 765-767. — 1987. Radiations and extinctions in relation to environmental change in the marine Lower Jurassic of northwest Europe. Paleobiology 13(2): 152-168. Harland, W.B., Armstrong, R.L., Cox, A.V., Craig, L.E., Smith, A.G. and Smith, D.G. 1989. A geologic time scale, 1989. Cambridge University Press. HiUebrandt, A. von. 1973a. Neue Ergebnisse tiber den Jura in Chile und Argentinien. Munstersche Forschungen zur Geologie und Palaontologie, Heft 31/32: 167-199, pi. 1. — 1973b. Die Ammoniten-Gattungen Bouleiceras und Frechiella im Jura von Chile und Argentinien. Eclogae geologicae Helvetiae, 66/2: 351-363, pi. I-III. — 1982. Faunas de amonites del Liasico inferior y medio (Hertangiano hasta Pliensba-chiano) de America del sur (Excluyendo Argentina). Cuncas sedimentarias del Jurasico y Cretacico de America del sur, 2: 499-538, pi. I-X. ~ 1987. Liassic ammonite zones of South America and correlations with other provinces with descriptions of new genera and species of ammonites. Biostratigrafia de los sistemas regionales del Jurasico y Cretacico en America del Sur, Tomo I: Jurasico anterior a los movimentos malmicos, 1: 111-157, 14 pi. HiUebrandt, A. von and Schmidt-Effing, R. 1981. Ammoniten aus dem Toarcium (Jura) von Chile (Sudamerika) - Die Arten der Gattungen Dactylioceras, Nodicoeloceras, Peronoceras und Collina. Zitteliana, Abhandlungen der Bayerischen Staatssammlung fur Palaontologie und historische Geologie, 6, 74 p., 8 pi. Hirano, H. 1971a. Biostratigraphic study of the Jurassic Toyora Group, Part I. Memoirs from the Faculty of Science, Kyushu University, Series D, Geology, 21(1): 93-128, pi. 14-20. ~ 1971b. Biostratigraphic Study of the Jurassic Toyora Group, Part II. Transactions and Proceedings of the Palaeontological Society of Japan, N.S., no. 89, p. 1-14, pi. 1-4. References 161 - 1971c. Biostratigraphic Study of the Jurassic Toyora Group, Part III. Transactions and Proceedings of the Palaeontological Society of Japan, N.S., no. 90, p. 45-71, pi. 9-10. Hohenegger, J. and Tatzxeiter, F. 1992. Morphometric methods in determination of ammonite species, exemplified through Balatonites shells (Middle Triassic). Journal of Paleontology 66(5): 801-816. Horn, B. K. P. 1986. Robert Vision. The MIT Press. Howarth, M.K. 1992. The ammonite family Hildoceratidae in the Lower Jurassic of Britain. Monograph of the Palaeontographical Society, part 1, 1-106, pi. 1-16. Huber, B. T. 1990. Digital-image processing will replace most hard-copy photography in palynology. Geotimes 35(2): 43-44. Illert, C. and Pickover, C. A. 1992. Generating irregularly oscillating fossil seashells. IEEE Computer Graphics and Applications. No. 5: 18-22. Imlay, R.W. 1968. Lower Jurassic (Pliensbachian and Toarcian) Ammonities from Eastern Oregon and California. United States Geological Survey, Professional Paper 593-C: 51. 9 pi. Imlay, R.W. 1981. Early Jurassic Ammonites from Alaska. United States Geological Survey, Professional Paper 1148: 49 p., 12 pi. Jakobs, G. 1992. Toarcian (Lower Jurassic) ammonite biostratigraphy and ammonite fauna of North America. Unpublished Ph.D. thesis, University of British Columbia, 682 p. Jones, D.L. and Moore, J.G. 1973. Lower Jurassic ammonite from the South-Central Sierra Nevada, California. Journal of Research, U.S.Geological Survey, 1: 453-458. Kaesler, R. L. and Waters, J. A. 1972. Fourier analysis of the ostracode margin : Geological Society of America Bulletin 83: 1169-1178. Kauffman, E. G. 1977. Evolutionary rates and biostratigraphy. In Kauffman, E. G. and Hazel, J. E. (eds.) Concepts and Methods of Biostratigraphy: 109-141. Kennedy, W. J. and Cobban, W. A. 1976. Aspects of ammonite biology, biogeography and biostratigraphy. Special Papers in Palaeontology, Palaeontological Association, London, 17:1-94. Klapper, G. and Foster, C. T. J. 1993. Shape analysis of Frasnian species of the Late Devonian conodont genus Palmatolepis. Journal of Paleontology 1993, supplement to No. 4. References 162 Koch, G. S. J. and Link, R. F. 1971. Statistical analysis of geological data. New York : Wiley. Krumbein, W. C. and Graybill, F. A. 1965. Introduction to statistical models in geology. New York: McGraw-Hill. Kuhl, F. P. and Giardina, C. R. 1982. Elliptic Fourier features of a closed contour. Computer Graphics and Image Processing 18: 236-258. Kullmann, J., Korn, D., Kullmann, P. S. and Petersen, M. S. 1991. The status of GONIAT, a data-base for Paleozoic ammonoids. First Canadian Paleontology Conference, Vancouver, p. 48. Landman, N. H. 1989. Iterative progenesis in Upper Cretaceous ammonites. Paleobiology 15(2): 95-117. Landman, N. H., Rye, D. M. and Shelton, K. L. 1983. Early ontogeny of Eutrephoceras compared to Recent Nautilus and Mesozoic ammonites: evidence from shell morphology and light stable isotopes. Paleobiology 9(3): 269-279. Lehmann, U. 1981. The ammonites — their life and their world. Cambridge University Press. Liang, B. 1988. A knowledge-based system for analysing sedimentary environment. Geological Science and Technology Information 7: 125-130. — 1988. Artificial intelligence and its application to the Guizhou Coal Basin, China. Earth Science 9(3): 350-355. ~ 1990. An object-oriented pattern recognition algorithm. In Zhao, P. D. (ed.): Statistical analysis in mineral exploration, p. 120-123. — 1990. Expert system and its application in sedimentary environment analysis. In Zhao, P. D. (ed.): Statistical analysis in mineral exploration, p. 65-73. Liang, B. and Smith, P. L. 1991. Measurements from ammonoid images using a computer. First Canadian Paleontology Conference, Vancouver, p. 50. — 1992. A Lower Jurassic ammonite image database: applications and implications. Second Canadian Paleontology Conference, Ottawa, p. 16-17. Lohmann, G. P. 1983. Eigenshape analysis of micro fossils : a general morphometric procedure for describing changes in shape. Mathematical Geology 15: 659-672. References 163 Lupher, R.L. 1941. Jurassic Stratigraphy in Central Oregon. Bulletin of the Geological Society of America, 52: 219-270,4 pi., 3 fig. MacKenzie, J.D. 1916. Geology of Graham Island, British Columbia. Geological Survey of Canada, Memoir 88. Marr, D. 1982. Vision. San Francisco: Freeman. Meister, C. 1986. Les ammonites du Carixien des Causses, France. — Mem. Suis. Paleont, 109, 209 p. ~ 1989. Les ammonites du Domerien des Causses, France. — Analyses paleontologiques et stratigraphiques. - Cahiers Pal. (CNRS edit), 98 p., Paris 1989 McLearn, F.H. 1930. Notes on some Canadian Mesozoic faunas. Transactions of the Royal Society of Canada, series 3, 24:1-7, 2pl. - 1932. Contributions to the stratigraphy and paleontology of Skidegate Inlet, Queen Charlotte Islands, British Columbia. Transactions of the Royal Society of Canada, series 3,26:51-80, 10 pi. Mutvei, H. and Reyment, R. A. 1973. Buoyancy control and siphuncle function in ammonoids. Palaeontology 16(3): 623-636. O'Brien, J. A. 1987. Jurassic biostratigraphy and evolution of the Methow Trough, southwestern British Columbia. B.Sc. thesis, University of British Columbia. Okamoto, T. 1988. Analysis of heteromorph ammonoids by differential geometry. Palaeontology 31: 35-52. Palfy, J. 1991. Uppermost Hettangian to lowermost Pliensbachian (Lower Jurassic) biostratigraphy and ammonoid fauna of the Queen Charlotte Islands, British Columbia.-Unpublished M.Sc. thesis, University of British Columbia, Vancouver . Poulton, T.P. 1991. Hettangian through Aalenian (Jurassic) guide fossils and biostratigraphy, northern Yukon and adjacent Northwest Territories. Geological Survey of Canada, Bulletin 410, 95 p., 18 pi. Poulton, T.P. and Tipper, H.W. 1991. Aalenian ammonites and strata of western Canada. Geological Survey of Canada, Bulletin 411, 71 p., 7 pi. Price, D. 1984. Computer-based storage and retrieval of paleontological data at the Sedgwick Museum, Cambridge, England. Paleontology 27: 393-406. References 164 Quinzio Sinn, L. A. 1987. Stratigraphische Untersuchungen im Unterjura des Sudteils der Provinz Antofagasta in Nord-Chile. Berliner geowissenschaftliche Abhandlungen, Reihe A, 87,105 p. Raup, D. M. 1966. Geometric analysis of shell coiling: general problems. Journal of Paleontology 40(5): 1178-1190. — 1967. Geometric analysis of shell coiling: coiling in Ammonoids. Journal of Paleontology 41(1): 43-65. Raup, D. M. and Crick, R. E. 1981. Evolution of single characters in the Jurassic ammonite Kosmoceras. Paleobiology 7(2): 200-215. — 1982. Kosmoceras: evolutionary jumps and sedimentary breaks. Paleobiology 8(2): 90-100. Raup, D. M. and Sepkoski, J. J. 1986. Periodic extinction of families and genera. Science 231: 833-836. Repin, Y.S. 1968. A new ammonoid genus from the Toarcian of the north-eastern U.S.S.R.. Palaeontological Journal, 3: 139-142. -- 1974. Biostratigraphy of the boreal Mesozoic, U.S.S.R. Academy of Sciences, Siberian Branch, 136:51-66,165-174. Rich, D. 1989. Image storage has geologic applications. Geotimes 34(9): 10-11. Riedel, W. R. and Tway, L. E. 1990. Artificial intelligence applications in paleontology and stratigraphy. In: Agterberg, F. P. and Bonham-Carter, G. F. [ed.]: Statistical applications in the earth sciences. Geological Survey of Canada, Paper 89-9: 383-388. Rock, N. M. S. 1988. Numerical geology : a source guide, glossary, and selective bibliography to geological uses of computers and statistics. Berlin; New York : Springer-Verlag. Rogers, M. J., Donovan, D. T. and Rogers, M. H. 1990. A deductive enquiry system for a palaeotological database of museum material. Palaeontology 33(3): 613-622. Sanborn, A.F. 1960. Geology and paleontology of the southwest quarter of the Big Bend quadrangle. California Division of Mines, Special Report 63: 3-26. Saunders, W. B. 1983. Natural rates of growth and longevity of Nautilus belauensis. Paleobiology 9(3): 280-288. References 165 Saunders, W. B. and Shapiro, E. A. 1986. Calculation and simulation of ammonoid hydrostatics. Paleobiology 12(1): 64-79. Saunders, W. B. and Swan, A. R. H. 1984. Morphology and morphologic diversity of mid-Carboniferous (Namurian) ammonoids in time and space. Paleobiology 10(2): 195-228. Savazzi, E. 1990. Theoretical morphology of shells aided by microcomputers. In: Hanley, J. T., Merriam, D. F. eds. Microcomputer applications in geology II: 229-240. Schlegelmilch, R.S. 1976. Die Ammoniten des siiddeutschen Lias. Gustav, Fischer, Verlag, Stuttgart, 212 p., 48 pi. Schlatter, R. 1991. Biostratigraphie und Ammonitenfauna des Ober-Lotharingium und Unter-Pliensbachium im Klettgau (Kanton Schaffhausen, Schweiz) und angrenzender Gebiete, Schweizerische Palaontologische Abhandlungen, 113, 133 p., 21 pi. Sepkoski, J. J. 1993. Ten years in the library: new data confirm paleontological patterns. Paleobiology 19(1): 43-51. Sey, I.I. and Kalacheva, E.D. 1980. Biostratigraphy of the Lower and Middle Jurassic deposits of the Far East. Ministry of Geology, U.S.S.R., Geological Institute, Nedra, 187 p., 34 pi (in Russian). Smith, P.L. 1976. Biostratigraphy of the Snowshoe Formation (Jurassic) in the Izee area Grant County, Oregon. M.Sc. thesis, Portland State University, 213 p., 7 pi. ~ 1980. Biostratigraphy and ammonoid fauna of the Lower Jurassic (Sinemurian, Pliensbachian and lowest Toarcian) of eastern Oregon and western Nevada. Ph.D. hesis, McMaster University. - 1983: The Pliensbachian ammonite Dayiceras dayiceroides and Early Jurassic paleogeography. Canadian Journal of Earth Sciences 20: 86-91. ~ 1986. The implications of data base management systems to paleontology: a discussion of Jurassic ammonoid data. Journal of Paleontology, 60: 327-340. Smith, P.L., Thomson, R.C. and Tipper, H.W. 1984. Lower and Middle Jurassic sediments and volcanics of the Spatsizi map area, British Columbia, in Current Research, Part A, Geological Survey of Canada, Paper 84-1 A: 117-120. Smith, P.L. and Tipper H.W. 1986. Plate tectonics and paleobiogeography: Early Jurassic (Pliensbachian) endemism and diversity. Palaios 1: 399-412. References 166 Smith, P.L. and H.W. Tipper 1988. Biochronology, stratigraphy and tectonic setting of the Pliensbachian of Canada and the United States. Second International Symposium on Jurassic Stratigraphy, Lisbon, 1:119-138. Smith, P.L., Tipper, H.W. Taylor, D.G. and Guex, J. 1988. An ammonite zonation for the Lower Jurassic of Canada and the United States: the Pliensbachian. Canadian Journal of Earth Sciences, 25:1503-1523. Smith, P.L. and Westermann, G.E.G. 1990. Paleobiogeography of the Ancient Pacific. Science, 249, p. 680. Spicer, R. A. Computerized palaeobotanical data bases: the way forward? In: Spicer, R. A. and Thomas, B. A. eds. Systematics and Taxonomic Approaches in Paleobotany. Stankevich, E.S. 1964, Ammonites in the Jurassic sandy-clay deposits of the northwestern Caucasus: Moskow-Leningrad, Nauka, 99 p. (in Russian). Stanley, G.D. Jr. and Yancey, T.E. 1990. Paleobiogeography of the Ancient Pacific. Science, 249, p. 680-681. Stanley, G.D. Jr. and Yang, X. N. 1987. Approximate evolutionary stasis for bivalve morphology over millions of years: a multivariate, multilineage study. Paleobiology 13(2): 113-139. Stansfield, S. A. 1986. ANGY: a rule-based expert system for automatic segmentation of coronary vessels from digital subtracted angiograms. IEEE Trans. Pattern Anal. Machine Intell. 8: 188-199. Sutherland Brown, A. 1968. Geology of the Queen Charlotte Islands, British Columbia. British Columbia Department of Mines and Petroleum Resources, Bulletin 54. Swan, A. R. H. and Saunders, W. B. 1987. Function and shape in late Paleozoic (mid-Carboniferous) ammonoids. Paleobiology 13(3): 297-311. Taylor, D.G. 1988a. Paradiscamphiceras, a new Lower Liassic ammonite genus. Bull. Soc. vaud. Sc.nat. 79:117-122. — 1988b. Middle Jurassic (late Aalenian and early Bajocian) ammonite biochronology of the Snowshoe Formation, Oregon. Oregon Geology 50:123-138. - 1990. Two species of Paracaloceras from the Canadense Zone (Hettangian-Sinemurian) in Nevada (U.S.A.). Bulletin de Geologie Lausanne, 309: 211-219. References 167 Taylor, D.G., Callomon, J.H., Hall, R., Smith, P.L., Tipper, H.W. and Westermann, G.E.G. 1984. Jurassic ammonite Biogeography of western North America: the tectonic implications. Geological Society of Canada Special Paper 27: 121-141. Thomson, R.C. 1985. Lower to Middle Jurassic (Pliensbachian to Bajocian) stratigraphy and Pliensbachian ammonite fauna of the northern Spatsizi area, north central British Columbia. M.Sc. thesis, University of British Columbia. Thomson, R.C., Smith, P.L. and Tipper, H.W. 1986. Lower to Middle Jurassic (Pliensbachian to Bajocian) stratigraphy of the northern Spatsizi area, north-central British Columbia. Canadian Journal of Earth Sciences, 23, no. 12, p. 1963-1973. Thomson, R.C and P.L. Smith 1992. Pliensbachian (Lower Jurassic) biostratigraphy and ammonite fauna of the Spatsizi area, north-central British Columbia. Geological Survey of Canada, Bulletin 437. Tillman, N. 1917. Die Fauna des unteren und mittleren Lias in Nord und Mittel-Peru. N. Jahrb. Min. 41: 628-712, pi. 21-26. Tipper, H.W. and Richards, T.A. 1976. Jurassic stratigraphy and history of north-central British Columbia. Geological Survey of Canada, Bulletin 270, 73 p. Tipper, H.W., Smith, P.L., Cameron, B.E.B., Carter, E.S., Jakobs, G.K. and Johns, M.J. 1991. Biostratigraphy of the Lower Jurassic formations of the Queen Charlotte Islands, British Columbia. In: Woodsworth, G.J. [ed.]: Evolution and Hydrocarbon potential of the Queen Charlotte basin, British Columbia. Geological Survey of Canada, Paper 90-10: 203-235. Torre, V. and Poggio, T. A. 1986. On edge detection. IEEE Trans, on pattern analysis and machine intelligence 2: 147-162. Tozer, E.T. 1982. Late Triassic (upper Norian) and earliest Jurassic (Hettangian) rocks and ammonoid faunas, Halfway River and Pine Pass map areas, British Columbia. Current Research, Part A, Geological Survey of Canada, Paper 82-1A: 385-391. Wang, Y. and Smith, P. L. 1986. Sinemurian (Early Jurassic) ammonite fauna from the Guangdong region of southern China. Journal of Paleontology, 60: 1075-1085. Ward, P. D. 1981. Shell sculpture as a defensive adaptation in ammonoids. Paleobiology 7(1): 96-100. - 1987. The natural history of Nautilus. Allen and Unwin Inc. Ward, P. D. and Signor, P. W. 1983. Evolutionary tempo in Jurassic and Cretaceous ammonites. Paleobiology 9(2): 183-198. References 168 Warren, P.S. 1931. A Lower Jurassic fauna from Fernie, B.C. Transactions of the Royal Society of Canada, series 3, 25: 105-111, pi. 1. Westermann, G. E. G. 1966. Covariation and taxonomy of the Jurassic ammonite Sonninia adicra (Waagen). N. Jb. Geol. Palaont. Abh. 124(3): 289-312 — 1971. Form, structure and function of shell and siphuncle in coiled Mesozoic Ammonoids. Royal Ontario Museum Publications in Life Sciences. ~ 1982. The connecting rings of Nautilus and Mesozoic ammonoids: implications for ammonoid bathymetry. Lethaia 15: 373-383. — 1993. Global bio-events in mid-Jurassic ammonites controlled by seaways. In House, M. R. ed. The Ammonoidea — Environment, Ecology, and Evolutionary Change. White, C.A. 1889. On vertebrate fossils from the Pacific Coast. United States Geological Survey Bulletin, pp. 71-98, pi. 13. Whiteaves, J.F. 1876. On some invertebrates from the coal-bearing rocks of the Queen Charlotte Islands. Geological Survey of Canada, Mesozoic Fossils, 1: 1-92 . Whiteaves, J.F. 1884. Mesozoic Fossils: Part Ill-On the fossils of the coal-bearing deposits of the Queen Charlotte Islands collected by Dr. G.M. Dawson in 1878. Geological and Natural History Survey of Canada-Mesozoic Fossils, 1: 1-261,14 pi. Wiedenmayer, F. (1977): Die Ammoniten des Besazio-Kalks (Pliensbachian, Sudtessin). Schweizerische palaontologische Abhandlung, 98: 1-169, 19 pi. ~ 1980. Die Ammoniten der mediterranen Provinz im Pliensbachian und unteren Toarcian aufgrund neuer Untersuchungen im Generoso-Becken (Lombardischen Alpen): Denkshriften Schweizerischen Naturforschenden Gessellschaft, 93, 34 pi. Willard, B. 1963. Ontogeny of the Jurassic ammonite Arietites from Peru. Pennsylvania Academy of Science, 37: 211-215 Younker, J. L. and Ehrlich, R. 1977. Fourier biometrics: harmonic amplitude as multivariate shape descriptors. Syst. Zoology 26: 336-346. Appendix 1 160.9 1.7-1.9 155 207 207 160 85 49 25 10 III! 1.9-2.1 96 139 185 180 134 113 57 25 12 2.1-2.3 45 64 87 84 118 90 78 35 26 11 2.3-2.5 20 19 40 41 56 65 72 53 27 2.5-2.7 11 19 30 34 42 22 27 19 2.7-3.0 13 14 18 17 23 *.'.'.'.'VV'.'-14 3 . 0 - 3 . 3 — 11 > 3 . 3 .;!.: :.:::. 1 :>fc::::::::::::':::::::::::£ (2)WWWH WXWWWH <1.5 1.5-1.7 1.7-1.9 1.9-2.1 2.1-2.3 2.3-2.5 2.5-2.7 2.7-3.0 3.0-3.3 >3.3 <0.6 o 5 23 64 75 66 34 23 5 5 0.6-0.8 1 34 163 207 139 82 54 22 6 4 0.8-1.0 5 70 167 163 81 37 7 5 4 7 1.0-1.2 18 67 123 86 32 16 9 5 4 Q >1.2 10 101 139 79 36 7 5 4 4 :-V^:::::::::::^,>:,:->>>v.:.::.;:-.::::::;:;:::::: (3) Fineness R a t i o - W W D Appendix 1 (2) Fineness Ratio V\WWD <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 <0.1 15 60 76 48 26 16 0.1-0.2 13 54 98 67 37 21 0.2-0.3 87 82 81 49 28 0.3-0.4 60 80 67 34 17 11 10 0.4-0.5 38 78 51 21 8 0.5-0.6 21 67 47 18 m ... 111ii.111i n illfc; I " " i l l ill I ' I 12 0.6-0.7 33 51 35 12 0.7-0.8 19 28 18 2111 14 0.8-0.9 10 23 12 >0.9 20 (3) Primary Rib Density V\PRHW <10 10-20 20-30 30-40 40-50 50-60 >60 <0.1 10 170 185 59 12 13 14 0.1-0.2 14 261 185 54 17 0.2-0.3 20 298 201 59 18 0.3-0.4 27 254 127 60 19 0.4-0.5 23 221 106 55 13 0.5-0.6 19 194 74 47 15 0.6-0.7 14 139 57 24 0.7-0.8 87 39 11 0.8-0.9 43 23 >0.9 (4) Rib Width V\RIB WIDTH <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 <0.1 38 112 132 108 79 0.1-0.2 39 127 170 136 72 0.2-0.3 42 192 171 122 78 0.3-0.4 48 160 150 89 45 0.4-0.5 75 143 125 61 26 0.5-0.6 83 131 82 45 19 0.6-0.7 73 95 62 15 0.7-0.8 51 69 21 14 0.8-0.9 >0.9 51 10 24 11 ... Appendix 1 171 (5) Primary Rib Form VXPFORM <0.1 0.1-0.2 0.2-0.3 0.3-0.4 0.4-0.5 0.5-0.6 0.6-0.7 0.7-0.8 0.8-0.9 >0.9 straight 335 378 315 190 98 59 36 34 18 4 concave 36 17 19 32 22 13 9 1111111 0 convex 0 1 2 1 0 2 0 0 0 projected 8 15 27 29 30 36 17 7 8 1 sinuous 72 87 160 162 148 139 94 48 23 4 falcoid 11 33 72 68 113 103 87 60 36 4 falcate 4 8 11 11 14 5 6 1 0 (6) Primary Rib Trend VXPTREND <0.1 0.1-0.2 0.2-0.3 0.3-0.4 0.4-0.5 0.5-0.6 0.6-0.7 0.7-0.8 0.8-0.9 >0.9 rursiradiate 14 19 16 10 4 1 2 oilii Ss 0 1 . grursiradiate 38 50 53 33 19 9 5 4 rectiradiate 289 354 416 346 309 257 177 117 57 10 gprorsiradiate 84 80 79 59 56 61 43 20 15 K prorsiradiate 37 23 28 27 18 12 5 iiisfpit .. riP (7) Primary Rib Profile V\PPROF <0.1 0.1-0.2 0.2-0.3 0.3-0.4 0.4-0.5 0.5-0.6 0.6-0.7 0.7-0.8 0.8-0.9 >0.9 non 11 14 10 37 26 18 21 26 25 29 weak 8 12 24 36 31 39 36 24 22 9 round +weak 2 10 21 28 25 38 36 29 17 1 round 89 168 184 189 194 180 126 57 30 4 angular 62 59 80 60 31 15 3 3 a l l l l l l l round +strong 38 50 72 38 28 8 4 4 2 0 strong 166 157 125 68 47 14 6 7 0 0 angular +strong 7 7 3 3 1 0 0 0 0 i Appendix 1 172 (8) Rib Furcation VXFURC non bundled bi intercalatory tn multi ioo£_ <0.1 376 80 15 0.1-0.2 423 12 99 18 0.2-0.3 459 31 97 15 0.3-0.4 431 18 66 16 o: — r - r • 0.4-0.5 356 19 68 l i •iVii'iYriYivriii'iiiVi'iTit 0.5-0.6 310 22 42 0.6-0.7 224 19 29 0.7-0.8 152 16 0.8-0.9 102 1 niiHiHnnYiYi; >0.9 44 (9) Tuberculation VYTUBERC non urn bi bullate clavate <0.1 316 145 23 0.1-0.2 387 154 25 0.2-0.3 466 139 17 13 0.3-0.4 458 68 17 0.4-0.5 400 46 10 10 * n t u t I 0.5-0.6 346 34 11 n 0.6-0.7 256 20 . " ' • 0.7-0.8 164 17 0.8-0.9 110 HWWWI ItWIII.IIMHI >0.9 45 (10) Furcation Position V\FURCPOS <0.1 0.1-0.2 0.2-0.3 0.3-0.4 0.4-0.5 0.5-0.6 0.6-0.7 0.7-0.8 0.8-0.9 >0.9 non 376 423 459 431 355 310 224 151 102 44 <0.25 8 14 36 28 28 20 16 4 0 MMmMmmm 0.25-0.5 6 16 31 36 51 45 30 16 6 0 0.5-0.75 30 46 44 33 15 4 7 3 3 &&*?'•" 4 >0.75 57 58 42 11 4 3 1 4 -0 Appendix 1 173 (11) Unituberculate Position WJNITUBPOS <0.1 0.1-0.2 non <0.25 338 412 0.5-0.75 >0.75 108 111 0.2-0.3 482 24 15 36 79 0.3-0.4 474 20 12 19 26 0.4-0.5 409 21 11 17 0.5-0.6 0.6-0.7 0.7-0.8 0.8-0.9 357 21 260 14 181 118 >0.9 47 (12) Venter VWENTER plain cannate carinate-sulcate sulcate tncannate <0.1 184 131 85 0.1-0.2 204 174 93 10 0.2-0.3 176 239 117 12 0.3-0.4 128 248 102 17 0.4-0.5 84 239 77 0.5-0.6 57 247 28 0.6-0.7 38 187 13 0.7-0.8 39 112 3 i i 0.8-0.9 26 55 >0.9 m (13) Whorl Shape VYWHORL SHAPE coro trape tn lanceo quadrate round rect ellips ogival oval <0.1 10 0 42 76 57 112 25 16 0.1-0.2 14 49 71 95 132 36 18 0.2-0.3 10 40 66 154 142 48 28 0.3-0.4 29 52 128 107 87 30 0.4-0.5 Wi«M«l.tt.M.i.l.t 12 26 99 74 90 30 0.5-0.6 II 11 10 71 57 87 42 0.6-0.7 0.7-0.8 15 10 33 23 35 36 76 16 29 44 34 0.8-0.9 >0.9 am i.i.i.i.i.i,i.im 0 33 30 fiffWW.**}}**** iO 22 Appendix 1 174 (14) Shell Diameter VXD <0.1 0.1-0.2 0.2-0.3 0.3-0.4 0.4-0.5 0.5-0.6 0.6-0.7 0.7-0.8 0.8-0.9 >0.9 <3 63 101 146 160 143 111 56 46 12 2 3-6 211 252 270 243 201 171 135 79 43 12 6-9 114 112 136 80 70 64 48 39 27 17 9-12 61 58 39 38 27 24 18 12 18 6 12-15 14 18 19 7 14 6 11 5 6 7 >15 24 31 26 23 11 16 14 7 12 3 3.WWWH (1) Fineness Ratio WWWHXWWD <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 <0.2 36 29 7 111!! 0.2-0.25 130 189 84 31 5 0.25-0.3 87 286 173 67 21 0.3-0.35 22 127 161 118 53 0.35 -0.4 0 31 61 71 81 0.4-0.45 li £i 6 11 26 79 0.45 -0.5 1 1 5 7 38 0.5-0.55 ill Bllllli 7 8 39 >0.55 I 3 8 62 (2) Primary Rib Density WWWHXPRHW <10 10-20 <0.6 \_4 J 112 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 23 23 31 53 348 327 217 177 20-30 67 206 156 96 88 30-40 51 85 34 28 38 40-50 11 25 7 10 17 50-60 9 12 5 2 4 >60 10 8 5 8 8 (3) Rib Width WWWHXRIBWIDTH <0.6 0.6-0.8 0.8-1.0 <0.1 81 96 45 0.1-0.15 91 223 111 0.15-0.2 40 201 155 0.2-0.25 12 100 140 >0.25 2 26 62 Appendix 1 n& 1.0-1.2 >1.2 23 21 63 74 97 77 82 92 79 96 (4) Primary Rib Form WWWHXPFORM <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 straight 28 164 288 257 319 concave 4 16 38 26 13 convex 111111111 2 1 1 2 projected 19 56 24 8 6 sinuous 82 257 121 37 16 falcoid 87 132 29 6 falcate 5 20 8 7 0 (5) Primary Rib Trend WWWH \PTREND <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 rursiradiate 2 11 16 11 7 grursiradiate 11 43 49 27 11 rectiradiate 163 468 343 230 217 gprorsiradiate 35 99 62 49 72 prorsiradiate 2 -9 34 j 20 | Lao, j (6) Primary Rib Profile WWWTTXPPROF <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 non 43 37 17 6 17 weak 43 57 21 11 round +weak 32 68 16 5 0 round 108 306 154 76 67 angular 4 31 73 46 33 round +strong 5 52 47 34 22 strong -> 49 110 115 176 angular +strona 6 2 3 (7) Rib Furcation WWWHXFURC <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 non 280 595 470 307 214 bundled 8 55 12 10 3 bi 13 84 84 65 131 intercalatory 3 6 3 3 0 tri 10 5 4 14 41 multi 3 4 3 2 12 loop 2 7 4 4 Appendix 1 176 (8) Tuberculation WWWHXTUBE RC <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 non 354 650 431 275 197 uni 21 111 127 106 193 bi 18 45 34 30 bullate 11 8 8 2 clavate i>. i) 0 :Q;:m:^y-(9) Furcation Position WWWHYFURCPOS <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 non 279 595 469 307 214 <0.25 6 56 19 17 4 W 0.25-0.5 18 70 26 12 14 0.5-0.75 4 11 30 20 76 >0.75 7 13 30 43 94 (10) Unituberculate Position WWWHMJNITUBPOS <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 non 354 668 476 309 225 <0.25 7 48 17 12 3 0.25-0.5 5 16 9 7 11 0.5-0.75 3 8 23 17 81 >0.75 7 50 86 78 105 (11) Venter WWWHWENTER <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 plain 46 159 235 214 332 carinate 261 479 225 108 46 carinate-sulcate 13 114 117 78 34 sulcate 8 16 17 12 3 tricarinate M^WSMh^ 2 6 7 7 Appendix 1 177 (12) Whorl Shape WWWHX WHORL SHAPE <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 coro 0 0 2 7 51 trape 0 4 9 3 6 tri 77 14 1 0 2 lanceo 10 12 1 0 0 quad -rate 0 0 140 82 0 round 0 0 167 169 83 rect 69 220 40 35 91 ellips 42 226 74 59 164 ogival 116 183 53 15 1 oval 49 92 45 22 3 (13) Shell Diameter WWWHXD <0.6 0.6-0.8 0.8-1.0 1.0-1.2 >1.2 <3 39 128 125 93 139 3-6 121 311 252 178 188 6-9 94 170 128 80 67 9-12 51 91 52 29 11 12-15 26 39 17 12 6 >15 44 51 37 31 14 4. Fineness Ratio (1) Primary Rib Density Appendix 1 178 (2) Rib Width WWD\RIBWIDTH <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 <0.1 11 64 88 42 17 8 4 8 11 0.1-0.15 21 122 165 120 47 23 10 11 10 0.15-0.2 21 88 183 129 60 31 10 10 8 0.2-0.25 6 65 110 103 56 23 12 9 19 >0.25 2 34 49 55 46 28 12 11 16 (3) Primary Rib Form WWDVPFORM straight concave convex projected sinuous falcoid falcate <0.2 27 15 0.2-0.25 156 15 22 109 63 0.25-0.3 222 19 44 200 90 15 0.3-0.35 233 26 22 110 47 11 0.35-0.4 153 15 34 15 0.4-0.45 88 13 0.45-0.5 39 0.5-0.55 37 >0.55 49 (4) Primary Rib Trend WWDVPTREND <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 rursiradiate 0 10 13 9 6 3 iiiiiiiiii 0 1 grursiradiate 10 38 34 29 12 4 4 7, T~"' rectiradiate 33 257 419 311 156 70 30 33 38 gprorsiradiate 15 48 89 68 26 23 11 8 9 prorsiradiate iplllltiiiiisssi 12 20 24 26 11 ! 3 5 9 Appendix 1 179 (5) Primary Rib Profile WWD\ PPROF <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 non 10 37 20 22 12 7 2 2 9 weak 6 43 41 24 9 2 4 111111 111 round +weak :2 ., : 32 45 23 10 l l l l l l! UL 0 0 round 24 154 244 143 49 23 8 21 11 angular 5 20 47 56 31 10 1 3 llllll! round+strong ; 27 49 39 16 5 2 2 3 strong 4 44 89 98 71 53 26 19 34 angular +strong ;0 2 2 ! 2 1111111 0 1 0 1 (6) Furcation WWD\FURC <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 non 66 338 473 378 165 66 22 18 28 bundled llllllllll 27 33 12 8 3 2 0 i bi 3 41 95 72 54 39 21 21 18 intercalatory $ 2 2 3 4 ;0i;lllllllll!llll|||ll i;'lllllllllll 0 iiiiiiiiiiiii tri 3 6 12 10 9 11 4 5 12 multi 0 •: 4 5 * 0 1 2 3 8 loop 0 1 3 0 1 1 Ills 4 6 (7) Tuberculation WWDYTUBERC <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 non 71 344 490 369 153 57 21 22 20 uni 10 83 122 89 78 52 25 20 29 bi WiMmmmWm i i 13 21 12 12 5 12 23 bullate wmmmm mm 6 13 4 2 2 l l ; i ; i l l l | | | o 0 clavate 0 0 WmWmWi,:M 1 ° 1 o l Appendix 1 180 (8) Furcation Position WWD\FURCPOS <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 non 66 338 473 377 164 66 22 18 28 <0.25 1 I 27 30 18 9 6 2 \ 1 0.25-0.5 2 16 58 27 16 8 2 6 3 0.5-0.75 o ' ;;|ff|| 15 22 19 17 14 14 13 23 >0.75 4 20 38 34 30 26 11 9 12 (9) Unituberculate Position WWD\UNITUBPOS <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 non 71 355 503 389 165 69 25 34 43 <0.25 1 24 29 12 7 6 ft ' 0 0.25-0.5 III 5 15 8 6 5 1 2 5 0.5-0.75 111111 13 14 15 21 13 14 11 18 >0.75 9 47 77 59 47 30 11 7 7 (10) Venter Appendix 1 181 (11) Whorl Shape WWD\ WHORL SHAPE coro trape tn lanceo quad -rate round rect ellips ogi-val oval <0.2 13 14 27 18 0.2-0.25 1 48 17 31 116 104 71 30 0.25-0.3 19 27 52 129 145 166 53 0.3-0.35 10 56 74 86 96 58 0.35-0.4 14 1 H 44 58 23 51 10 0.4-0.45 12 1 23 27 11 27 43 22 0.45-0.5 i .•• 25 0.5-0.55 28 :2 >0.55 40 (12) Shell Diameter WWDVD <0.2 0.2-0.25 0.25-0.3 0.3-0.35 0.35-0.4 0.4-0.45 0.45-0.5 0.5-0.55 >0.55 <3 1 40 100 121 83 41 20 26 39 3-6 22 140 295 219 112 61 23 18 19 6-9 15 119 144 91 34 12 6 6 9 9-12 15 73 57 23 6 2 3 o 3 12-15 11 29 16 11 1 4 ;6:.:Il!III§lf 1 1 3 >15 17 43 26 18 10 3 0 3 0 5. Primary Rib Density (1) Rib Width PRHWXRIBWIDTH <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 <10 16 29 29 78 10-20 108 411 571 502 307 20-30 105 475 397 167 30-40 148 209 69 10 40-50 76 54 32 50-60 >60 54 56 " i n 11 0 M I M I M I M M M I I M Appendix 1 182 (2) Primary Rib Form PRHWXPFOR M <10 10-20 20-30 30-40 40-50 50-60 >60 straig ht 114 947 572 167 44 17 20 concav e 2 105 59 11 5 111111 conve X 1 5 fci- '"•• i> m" projecte d 8 121 41 13 | | i inn Hip sinuou s 30 495 300 92 42 15 14 falcoid .1 172 186 144 40 29 22 falcate 0 33 12 7 4 1 3 (3) Primary Rib Trend PRHWXPTREND <10 10-20 20-30 30-40 40-50 50-60 >60 rursiradiat e 5 52 28 grursiradiate 10 147 71 18 5 rectiradiate 112 1302 787 302 89 39 29 gprorsiradiat e 17 212 215 80 27 9 16 prorsiradiate 6 83 37 22 8 10 14 (4) Primary Rib Profile PRHW\ PPROF <10 10-20 20-30 30-40 40-50 50-60 >60 weak 9 101 61 28 9 5 2 round+ weak 7 90 69 32 7 6 o m round 45 673 373 148 49 19 24 angular 10 175 151 28 12 7 3 round +strong 14 152 78 19 4 I strong 48 363 228 87 18 11 8 angular +strong 2 9 7 4 4 •iSSSSif: Appendix 1 183 (5) Rib Furcation (6) Tuberculation PRHWYTUBERC <10 10-20 20-30 30-40 40-50 50-60 >60 non 76 1464 1003 384 120 54 52 uni 62 411 204 74 22 12 11 bi 27 99 28 i :;""» i l l i . > • 2 3 bullate 2 35 10 1 1 0 0 clavate 2 1 in -m .0 W" 0 (7) Furcation Position PRHWXFURCPOS <10 10-20 20-30 30-40 40-50 50-60 >60 non 120 1527 1002 372 115 57 60 <0.25 16 128 6 3 3 1 1 0.25-0.5 19 181 36 9 2 1 llllllll 0.5-0.75 7 80 89 31 8 V . ,. 2 >0.75 7 71 99 42 15 8 2 (8) Unituberculate Position PRHWYUNITUBPOS <10 10-20 20-30 30-40 40-50 50-60 >60 non 102 1560 1031 385 120 56 55 <0.25 17 99 3 1 3 0 0 0.25-0.5 15 47 5 4 - , 7 ; - - - • - - ; - • ; - -6' * 0.5-0.75 17 77 49 14 6 6 7 >0.75 18 227 157 56 14 6 4 Appendix 1 184 (9) Venter PRHWWENTER <10 10-20 20-30 30-40 40-50 50-60 >60 plain 65 524 296 115 40 28 31 carinate 72 888 484 203 54 20 22 carinate-sulcate 11 256 239 81 29 9 5 sulcate 2 32 44 7 " 6 tricarinate 2 11 9 (10) Whorl Shape PRHW\ WHORL SHAPE <10 10-20 20-30 30-40 40-50 50-60 >60 coro 6 27 16 6 111111 1 0 trape 11 8 2 0 0 0 0 tri • 36 24 11 3 8 5 lanceo 0 35 9 0 0 £> 0 quad -rate 24 132 49 16 4 2 5 roun d 21 212 116 25 9 5 10 rect 13 230 225 138 53 15 8 ellips 40 394 272 80 20 11 9 ogi-val 19 279 126 55 13 6 8 oval 9 148 81 25 6 ill 5 (11) Shell Diameter PRHW\D <10 10-20 20-30 30-40 40-50 50-60 >60 <3 79 540 220 67 10 2 1 3-6 66 893 584 183 46 17 6 6-9 19 301 234 133 58 29 22 9-12 4 129 109 42 15 14 16 12-15 .0 45 41 18 6 3 8 >15 I 90 55 17 7 3 13 6. Rib Width Appendix 1 185 (1) Primary Rib Form RIBWIDTH \PFORM <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 straight 148 459 525 433 320 concave 16 45 57 46 17 convex 0 *P 0 1 4 1 projected 30 50 50 37 16 sinuous 141 382 286 131 48 falcoid 188 222 134 39 13 falcate 11 11 18 19 1 (2) Primary Rib Trend RIBWIDTH \PTREND <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 rursiradiate 4 20 18 33 11 grursiradiate 13 73 63 63 40 rectiradiate 347 791 760 469 296 gprorsiradiate 102 195 146 89 47 prorsiradiate 30 47 55 32 17 (3) Primary Rib Profile RIBWIDTHXPPROF <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 weak 74 81 39 16 3 round +weak 49 93 52 13 4 round 185 392 397 234 124 angular 37 159 119 49 20 round+ strong 6 39 74 77 73 strong 56 176 197 190 151 angular+ strong 9 8 5 3 3 (4) Rib Furcation RIBWIDTHXFURC <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 non 393 837 844 593 370 bundled 21 60 29 11 6 bi 95 217 171 82 31 intercalatory 5 16 5 4 IlllllllllII tri 18 39 15 16 8 multi 5 8 7 5 6 loop 15 3 3 2 1 $! Appendix 1 186 (5) Tuberculation RIBWIDTHMUBERC <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 non 454 924 824 507 261 uni 65 216 207 167 111 bi 29 21 30 30 45 bullate 4 19 12 9 3 clavate 0 s& 1 0 2 (6) Furcation Position RIBWIDTH\FURCPOS <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 non 392 837 844 593 369 <0.25 23 82 41 8 4 0.25-0.5 53 90 67 25 12 0.5-0.75 39 78 59 26 14 >0.75 28 83 57 55 21 (7) Unituberculate Position RLBWIDTH\UNITUBPOS <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 non 483 943 853 537 305 <0.25 13 60 34 7 3 0.25-0.5 10 21 19 12 8 0.5-0.75 20 50 40 27 32 >0.75 26 106 128 130 74 (8) Venter RIBWIDTHWENTER <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 plain 138 243 246 225 170 carinate 243 542 462 271 129 carinate-sulcate 60 193 188 99 53 sulcate 19 26 19 9 3 tricarinate 2 5 7 6 3 Appendix 1 187 (9) Whorl Shape RTBWTDTHX WHORL SHAPE <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 coro 2 10 14 19 8 trape 3 3 11 3 0 tri 42 32 7 3 0 lanceo * 17 20 5 ill!!* quad -rate 15 40 56 62 49 round 27 63 86 76 94 rect 117 230 166 99 33 ellips 55 222 241 148 92 ogi-val 87 164 134 78 21 oval 53 86 58 34 22 (10) Shell Diameter RTBWIDTHVD <0.1 0.1-0.15 0.15-0.2 0.2-0.25 >0.25 <3 57 205 254 220 149 3-6 191 561 492 309 181 6-9 162 234 184 103 61 9-12 68 99 80 41 16 12-15 32 36 20 12 6 >15 38 39 42 25 9 7. Primary Rib Form (1) Primary Rib Trend PFORMXPTREND straight concave convex projected sinuous falcoid falcate rursiradiate 56 3 0 11 11 1 5 grursiradiate 126 7 2 18 54 33 12 rectiradiate 1229 74 2 100 784 458 24 gprorsiradiate 336 42 f i 26 89 73 13 prorsiradiate 101 48 1 8 21 I 0 (2) Rib Profile PFORMX PPROF straight concave convex projected sinuous falcoid falcate weak 66 7 0 7 81 46 2 round+ weak 23 3 0 2 81 100 3 round 422 33 4 92 480 284 17 angular 239 52 0 14 62 19 0 round+ strong 91 4 , 11 90 54 19 strong 637 27 £ 15 60 12 12 angular+ strong 22 2 0 1 2 0 1 Appendix 1 188 (3) Rib Furcation PFORMXFURC straight concave convex projected sinuous falcoid falcate non 1362 163 5 162 744 540 56 bundled 12 &P 1 '"" 3 101 10 0 bi 408 11 1 4 120 39 5 intercalatory 9 3 * ..... 4 9 5 o" tri 78 4 1 • 4 7 3 multi 21 o 1 U 6 5 H loop 9 :0 : ; . V * : • : . > ; • : • : - : • . •••• ; • : • : • : • • : • ; ' : : • > 0 • • / -5 1 iO (4) Tuberculation (5) Furcation Position PFORMXFURCPOS straight concave convex projected sinuous falcoid falcate non 1361 163 5 162 743 540 56 <0.25 34 1 i 1 1 1 1 4 105 12 1 0.25-0.5 74 7 1 4 112 0.5-0.75 194 3 ^ 3 15 >0.75 226 6 0 7 5 E & ^ ^ H I ^ S S ^ E A ^ ^ H 3 1 0 (6) Unituberculate Position PFORMXUMTUBPOS straight concave convex projected sinuous falcoid falcate non 1285 164 5 170 821 589 60 <0.25 24 i : l j§§|f 0 86 5 11111 0.25-0.5 31 ro lilt 37 2 i ; i i l l l l l 0.5-0.75 152 | 1 3 14 • • I >0.75 407 16 1 10 33 iliiii Appendix 1 189 (7) Venter PFORMXVENTER straight concave convex projected sinuous falcoid plain 824 60 4 34 77 24 carinate 445 31 2 109 627 397 falcate | 36 carinate-sulcate 200 40 0 K£2i-:-:v:-:-Xv ' .:-:•:-:•::--'-'-:-'-' 167 154 23 sulcate 55 tricarinate 8 12 5 ft sp m *> IB l:o 1 8 1 * (8) Whorl Shape PFORMX WHORL SHAPE straight concave convex projected sinuous falcoid falcate coro 51 III 1 1 1 111111 11111 trape 18 0 0 iiii 2 111111 1111 tri 11 2 • 16 28 26 0 lanceo lllllll wzii 0 o 111! 4 39 1 quad -rate 146 10 • 1 5 43 9 4 round 283 40 1 4 16 2 lllllll rect 155 4 1 15 227 211 31 ellips 451 44 2 20 198 45 2 ogiva 1 94 4 1 58 227 95 6 oval 88 11 Ml 10 82 61 1 (9) Shell Diameter PFORMXD straight concave convex projected sinuous falcoid falcate <3 468 26 3 41 227 112 6 3-6 814 66 3 74 472 270 22 6-9 357 38 0 33 170 130 15 9-12 129 23 Q 20 76 48 7 12-15 48 4 : • : • • . : : • 10 18 21 3 >15 76 21 0 5 28 15 8 8. Primary Rib Trend Appendix 1 (1) Rib Profile PTRENDV PPROF rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate weak 3 9 144 27 5 rounds-weak III 5 173 23 1 round 22 85 981 171 50 angular 15 40 244 52 31 rounds-strong 19 40 182 19 4 strong 16 45 497 147 47 angular+ strong 111111 4 19 4 (2) Rib Furcation PTRENDVFURC rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate non 78 206 2071 409 146 bundled 1 4 111 9 0 bi 4 29 376 136 29 intercalatory 0 22 5 • l l l l l i i l l tri 2 9 64 12 5 multi 1 2 19 8 t> loop 0 . 1 12 2 1 (3) Tuberculation PTRENDYTUBERC rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate non 64 182 2021 423 132 uni 16 46 515 134 49 bi 4 19 102 18 0 bullate 2 4 35 6 i::iiiiiiii clavate 0 1 2 0 0 (4) Furcation Position PTREND\FURCPOS rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate non 78 206 2069 409 146 <0.25 3 16 112 19 1 0.25-0.5 2 8 167 43 8 0.5-0.75 1 1 145 56 12 >0.75 2 19 157 50 13 Appendix 1 191 (5) Unituberculate Position PTREND\UNITUBPOS rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate non 68 200 2120 441 132 <0.25 umM i i 90 12 i) 0.25-0.5 l l l l l l l 2 56 9 0.5-0.75 £.. 7 112 30 17 >0.75 12 32 297 89 32 (6) Venter PTRENDWENTER rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate plain 7 22 623 222 126 carinate 35 117 1235 198 23 carinate-sulcate 29 80 396 66 9 sulcate •0: 111111 lllllll 61 7 2 tricarinate 2 4 17 1 (7) Whorl Shape PTRENDVWHORL SHAPE rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate coro llllll lllll 27 16 10 trape 0 2 11 5 o ••": tri 0 2 59 11 11 lanceo 0 lllllll 41 10 o' 111 quad -rate 9 24 163 18 3 roun d 4 15 207 76 37 rect 20 55 473 85 4 ellips 15 34 520 119 65 ogival 9 34 364 58 6 oval 8 11 187 34 8 (8) Shell Diameter PTREND\D rursiradiate grursiradiate rectiradiate gprorsiradiate prorsiradiate <3 8 29 656 114 36 3-6 33 114 1179 265 76 6-9 22 56 479 120 42 9-12 12 28 187 48 20 12-15 5 10 57 14 5 >15 6 13 109 18 2 9. Primary Rib Profile Appendix 1 192 (1) Rib Furcation PPROFVFURC non weak round+weak round angular round+strong strong angular+strong non 230 215 184 1081 336 231 440 15 bundled (j "jjjg 8 6 79 5 5 6 l l * >': bi 0 23 17 133 34 29 253 13 intercalatoiy 0 W8M 4 3 5 |K„ >\ r , 3 3 • f tri 0 1 2 21 6 1 44 • t i l multi ill 0 b 10 4 U 14 loop 0 ,^: 1 WHH 6 1 0 10 W (2) Tuberculation PPROFYTUBERC non weak round+weak round angular round+strong strong angular+strong non 225 232 195 1046 312 237 21 uni 3 16 7 220 62 25 6 bi 1 3 7 54 3 5 $ bullate 1 1 3 15 9 2 wmmm clavate 10 0 '" » > ;0"'i 0 0 1 1 (3) Furcation Position (4) Unituberculate Position PPROFttJNITUBPOS non weak round+weak non 226 235 202 <0.25 §§§§; 6 9 0.25-0.5 0 • 4 1 0.5-0.75 3 0 Q ;:"." >0.75 1 • 7 Appendix 1 193 round angular round+strong strong angular+strong 1099 315 241 439 21 72 Illlll 7 7 0 28 3 3 13 1 30 10 8 100 3 106 57 10 211 3 (5) Venter PPROFWENTER non weak round+weak round angular round+strong strong angular+strong plain 85 59 16 235 82 29 444 9 carinate 50 124 161 787 114 136 130 6 carinate-sulcate 5 15 24 174 96 77 71 5 sulcate 3 0 6 43 0 3 3 tricarinate " 3 2 4 2 6 2 1 (6) Whorl Shape PPROFWVHORL SHAPE non weak round+weak round angular round+strong strong angular+strong coro 1 ill! 0 4 13 BB 31 |3 trape 2 1. 6 6 | | f 1 6 Illlll tri 46 22 11 27 3 jjjj 0 lance 0 7 5 2 29 0 5 0 quad -rate • 2 1 49 20 34 78 6 roun d 28 14 2 68 53 15 110 2 rect 13 29 41 251 68 81 74 5 ellips 33 47 46 259 64 59 171 5 ogival 28 46 53 265 29 15 44 Illlll! oval 10 31 32 96 25 14 20 1 (7) Shell Diameter PPROFXD non weak round+weak round angular round+strong strong angular+strong <3 53 64 46 286 76 42 171 2 3-6 82 110 98 550 194 118 355 13 6-9 37 35 39 274 62 61 160 5 9-12 21 20 16 128 24 25 46 3 12-15 11 11 5 42 7 11 14 1 >15 25 12 8 53 21 12 16 4 Appendix 1 194 10. Rib Furcation (1) Tuberculation FURC\TUBERC non bundled bi intercalatory tri multi loop non 3017 31 326 26 18 7 2 uni 386 85 243 1 67 18 7 bi 113 1 14 3 10 7 14 bullate 25 10 14 if*! 1 •0 0 clavate 2 B 0 1 (2) Unituberculate Position FURCUJNITUBPOS non bundled bi intercalatory tri multi loop non 3130 32 336 29 28 14 16 <0.25 11 68 37 111 6 111 0 0.25-0.5 2 27 27 0 10 5 o '"K 0.5-0.75 67 111 79 1 21 12 1 >0.75 333 Hfc 118 Q 31 ililllli! 7 (3) Venter Appendix 1 195 (4) Whorl Shape (5) Shell Diameter FURC\D non bundled bi intercalatory tri multi loop <3 802 8 147 4 13 9 0 3-6 1501 46 279 7 39 10 13 6-9 665 32 111 7 28 4 4 9-12 285 19 35 4 8 4 0 12-15 106 7 10 0 3 5 3 >15 174 15 9 8 5 0 4 11. Tuberculation (1) Furcation Position TUBERCVFURCPOS non uni bi bullate clavate non 3017 384 113 25 2 <0.25 57 82 5 14 illillll 0.25-0.5 163 70 6 9 o 0.5-0.75 110 97 8 2 0 >0.75 61 169 14 Illliill! (2) Venter TUBERCWENTER non uni bi bullate clavate plain 699 448 112 1 0 carinate 1647 219 31 10 0 carinate-sulcate 557 50 7 34 1 sulcate 91 2 0 0 0 tricarinate 19 15 174 37 14 10 0 12. Furcation Position (1) Unituberculate Position FURCPOS\UNITUBPOS non <0.25 0.25-0.5 0.5-0.75 >0.75 non 3130 59 168 118 75 <0.25 11 98 14 ill;;!: Bill 0.25-0.5 2 62 7 • 0.5-0.75 67 2 89 23 >0.75 331 1 2 3 146 (2) Venter FURCPOSWENTER plain carinate carinate-sulcate sulcate tricarinate non 761 1541 542 71 22 0 quad -rate 154 17 12 9 a ii ii im • round 358 3 7 28 31 rect 591 35 36 15 13 ellips 652 29 38 82 68 ogi-val 422 41 54 12 16 oval 222 10 37 4 10 (4) Shell Diameter FURCPOSVD non <0.25 0.25-0.5 0.5-0.75 >0.75 <3 801 10 46 71 50 3-6 1501 52 118 92 115 6-9 665 43 43 34 58 9-12 285 29 15 11 12 12-15 106 7 10 4 5 >15 173 16 13 3 4 13. Unituberculate Position (1) Venter UNITUBPOSWENTER non <0.25 0.25-0.5 0.5-0.75 >0.75 plain 811 1 14 141 293 carinate 1678 84 33 20 92 carinate-sulcate 561 34 19 5 30 sulcate 91 1 0 0 1 tricarinate 19 1 O :e:!lllllilllll 4 (2) Whorl Shape UNITUBPOS\ WHORL SHAPE non <0.25 0.25-0.5 0.5-0.75 >0.75 coro 8 111 4 16 35 trape 21 4 1 0 0 tri 135 4 1 fli 1 lanceo 54 111 o i> pSK; quad -rate 135 14 8 13 71 roun d 376 3 2 26 53 rect 622 25 9 16 59 ellips 719 19 13 65 100 ogi-val 479 41 9 6 28 oval 280 7 10 5 7 Appendix 1 198 (3) Shell Diameter UNITUBPOSU) non <0.25 0.25-0.5 0.5-0.75 >0.75 <3 836 4 14 53 104 3-6 1580 37 35 81 218 6-9 715 36 10 25 93 9-12 290 27 5 12 45 12-15 116 6 4 8 12 >15 188 14 3 5 25 14. Venter (1) Whorl Shape VENTER\ WHORL SHAPE plain carinate carinate-sulcate sulcate tricarinate coro 63 111111 0 ill! 111111 trape 13 11 2 III ill!! tri 26 50 i " ; 0 0 lanceo $< 48 11 0 0 quad -rate 92 60 75 1 10 round 279 96 56 17 3 rect 79 395 229 8 2 ellips 398 365 106 27 3 ogi-val 55 445 35 8 0 oval 71 179 19 24 5 (2) Shell Diameter VENTER\D plain carinate carinate-sulcate sulcate tricarinate <3 326 381 77 36 2 3-6 512 854 264 35 10 6-9 247 366 141 10 2 9-12 88 156 70 4 5 12-15 28 64 34 1 0 >15 58 85 63 5 5 15. Whorl Shape Appendix 1 199 (1) Shell Diameter WHORL SHAPEXD coro trape tri lanceo quadrate round rect ellips ogival oval <3 11 7 19 14 49 114 113 228 98 64 3-6 38 7 43 26 98 210 280 363 277 128 6-9 7 7 35 8 49 75 193 183 88 53 9-12 2 1 19 4 14 30 77 68 55 26 12-15 1 1 12 2 10 12 31 22 21 10 >15 4 3 13 0 21 19 37 52 23 28 Appendix 2 Source code for the user interface of Ammon 200 Appendix 2 Source code for the graphics interface of Ammon There are 13 files in this program: ammon.h, retrieve.h, retrieve.c, amenu.h, amenu.c, display.c, query.c, dbms.c, misc.c, utility.h, utility.c, win.h, win.c: 1. ammon.h: /* Header file for Ammon graphics interface * and interactive image measurement module. * * Author: Bo Liang * Department of Geological Sciences * The University of British Columbia * Date: September 1992 * Modifications: April 1994 * */ #include #include #include #include #include #include #include #include #include #include /* the maximum number of specimens allowed for each query return */ #define MAX_SP 1000 /* the maximum number of images allowed for each query return, since one specimen can have multiple images, MAXNUM+1000 gives extra room to accomondate images */ #define MAXJMAGE MAX_SP+1000 /* define the array index for descriptor_name */ #define IMAGE 35 #define SCALE 36 #define WHORLSHAPE 52 #define ONTOGENY 61 #define APPROX 68 /* active descriptors in Ammon */ Appendix 2 Source code for the user interface of Ammon 201 char* descriptor_narne[]={MSUPERFAMILY^"FAMILY","SUBFAMILY",,,GENUS,,, "SUBGENUS", "QUALIFIER", "SPECIES","SUBSPECIES", "TAXAUTHYEAR", "REFAUTHYEAR", "SYNONYMY", "SYNSPECIES","STAGE","SUBSTAGE","EURZONE", "EURSUBZONE","ZONE","SUBZONE", "HORIZON", "FORMATION", "MEMBER","SITU",,,ASSOCSPEC","AREA", "COUNTRY","PROVINCE","SECTNAME","SECTNO","LOCNO", "OTHERNO","REPOSITORY",,,TYPE", "GENERALOC", "SPECNO", "REMARKS 1", "IMAGE","SCALE", "DMAX", "D", "UD","U", "EXP","WH","WHD", "WW","WWD","WWWH", "PRHW", "SRHW","THW","BISPACE","CHWH,"WHORL_SHAPE", "UWALLHT", "UWALLANG","VENTER",,,PTREND","PFORM", "PPROF","FURC","TUBERC","ONTOGENY","MAXWH", "RIBWIDTH","FURCPOS0","UNITUBPOS0",HEXP0,,, "VOLUTION0", "APPROX"}; #define NUM_OF_DESCRIPTOR sizeof descriptor_name/sizeof descriptor_name[0] /* the field length of the above descriptors */ short len[]={ 19,17,22,20,20,15,30,20,30,40,22,30,25,40,30,30,30,20,25,30,20,2, 6,20,20,30,50,25,20,14,40,14,80,30,200,50,4,6,6,6,5,5,6,5,6,5,5, 4,4,4,5,4,30,4,8,16,14,30,16,12,10,4,3,3,5,3,4,3,40}; /* The following data arrays are used to initialize the menu */ /* ammanite family list in Ammon, new families may be added */ static char *farnily[]={"Psiloceratidae","Schlotheimiidae","Arietitidae", "Echioceratidae"," Oxynoticeratidae"," Cymbitidae", "Eoderoceratidae","Coeloceratidae","Phricodoceratidae", "Polymorphitidae","Liparoceratidae","Amaltheidae", "Dactylioceratidae", "Hildoceratidae", "Phymatoceratidae", " Graphoceratidae"," Sonniniidae"," Cardioceratidae", "Erycitidae","Kosmoceratidae","Otoitidae", "Sphaeroceratidae","Stephanoceratidae","Oppeliidae", "Perisphinctidae", "Reineckeiidae", "Discophyllitidae", "Phylloceratidae", "Lytoceratidae", "Family uncertain"}; /* genus list in Ammon, if add new genus, make sure you update num_of_j*enus_in_family which can be tedious, better way to do it ? */ static char *genus[]={"Alsatitoides","Badouxia","Caloceras", "Discamphiceras","Euphyllites","Laqueoceras","Mullerites", Appendix 2 Source code for the user interface of Amnion 202 "Paradiscamphiceras","Parapsiloceras","Psiloceras", "Psilophyllites","Saxoceras","Transipsiloceras", " Angulaticeras", "Kammerkaroceras"," Schlotheimia", "Sulciferites","Waehneroceras","Aegasteroceras", "Agassiceras","Alsatites","Arietites","Arnioceras", "Asteroceras","Caenisites","Canavarites","Coroniceras", "Defossiceras'V'Eparietites'V'Epophioceras'V'Euagassiceras", "Metarnioceras","Pompeckioceras","Pseudaetomoceras", "Pseudasteroceras", "Pseudotropites"," Sunrisites", "Tmaegoceras","Vermiceras,,5"Dubariceras","Echioceras", "Gagaticeras","Leptechioceras",',PalaeoechiocerasH, "Paltechioceras", "Protechioceras"," Tmaegophioceras", "Cheltonia", "Fanninoceras"," Gleviceras"," Oxynoticeras", "Paracymbites'V'Paroxynoticeras'V'Radstockiceras", HSlatterites","Cymbites","Bifericeras","Crucilobiceras", "Eoderoceras","Exomiltoceras","Metaderoceras", "Microderoceras"J"Miltoceras","Promicroceras", "Pseudoskirroceras", "Xipheroceras"," Apoderoceras", " Coeloceras", "Hyperderoceras", "Pimelites", "Praesphaeroceras", "Tetraspidoceras","Epideroceras","Phricodoceras", "Acanthopleuroceras","Dayiceras","Eoamaltheus", "Gemmellaroceras","Parinodiceras","Peripleuroceras", "Platypleuroceras","Polymorphites","Tropidoceras","Uptonia", "Aegoceras","Androgynoceras","Liparoceras","Amaltheus", "Amauroceras","Pleuroceras","Catacoeloceras","Collina", "Dactylioceras","Nodicoeloceras","Peronoceras","Porpoceras", "Preperonoceras","Prodactylioceras","Reynesoceras", "Reynesocoeloceras", "Zugodactylites"," Arctomercaticeras", "Arieticeras","Atacamiceras")"Bouleiceras","Canavarella", "Canavaria"," Cylicoceras", "Dumortieria", "Eleganticeras", "Fieldingiceras", "Fontanelliceras", "Frechiella", "Fuciniceras","Grammoceras","Harpoceras","Hildaites", "Hildoceras", "Hildaitoides", "Hudlestonia", "Leioceras", "Leptaleoceras", "Leukadiella", "Lioceratoides", "Mercaticeras", "Neolioceratoides"," Oregonites"," Onychoceras"," Ovaticeras", "Parahildaites","Paroniceras","Phlyseogrammoceras", "Pleydellia","Podagrosites","Polyplectus","Protogrammoceras", "Pseudogrammoceras","Pseudolioceras","Renziceras", "Sphenarpites","Staufenia","Taffertia")"Tiltoniceras", "Tmetoceras","Bredyia","Brodieia","Erycites","Erycitoides", "Esericeras","Eudmetoceras","Hammatoceras","Haplopleuroceras", "Haugia", "Nej dia", "Phymatoceras", "Planammatoceras", "Podagrosiceras", "Pseudomercaticeras", "Puchenquia", "Sphaerocoeloceras","Yakounia","Brasilia","Costileioceras", "Darellia"," Graphoceras", "Hyperlioceras", "Ludwigia", "Reynesella", "Dorsetensia", "Euhoploceras", "Fissilobiceras", Appendix 2 Source code for the user interface of Ammon 203 "Fontannesia">HGuhsania",MShirbuirnia","Sonninia", "Witchellia","Zurcheria","Arcticoceras,,,"Arctocephalites", "Cadoceras","Cardioceras","Paracadoceras","Pseudocadoceras", "Podagrosiceras", "Kepplerites", "Kosmoceras", "Docidoceras", "Emileia","Pseudotoites","Chondroceras","Eocephalites", "Eurycephalites","Iniskinites","Lilloettia","Loucheuxia", "Megasphaeroceras"," Stehnocephalites", "Xenocephalites", "Stephanoceras","Stemmatoceras","Oecotraustes","Oxycerites", "Prohecticoceras"," Choffatia", "Neuqueniceras", "Rehmannia", "Harpophylloceras","Juraphyllites","Tragophylloceras", " Adabofoloceras"," Calaiceras"," Calliphylloceras", "Fergusonites", "Holcophylloceras", "Nevadaphyllites", "Partschiceras","Phylloceras","Procliviceras","Sowerbyceras", "Zetoceras","Alocolytoceras","Audaxlytoceras","Derolytoceras", "Holcolytoceras", "Kallilytoceras", "Lytoceras", "Pleurolytoceras", "Pterolytoceras"," Asaphoceras", "Diplesioceras"}; short num_of^enus_in_family[]={13,5,21,8J8,l,10,6,2)10,3,3,ll,43,17,7,9,6,l, 2,3,9,2,3,1,2,3,11,8,2}; /* stage list for Lower Jurassic and part of Middle Jurassic */ static char *stage[]={"Hettangian","Sinemurian","Pliensbachian", "Toarcian"," Aalenian'V'Bajocian"}; /* European zones in the above stages */ static char *zone[]={"Planorbis,,,"Liasicus","Angulata","Bucklandi", "Semicostatum","Turneri","Obtusum","Oxynotum", "Raricostatum","Jamesoni","Ibex","Davoei","Margaritatus", "Spinatum","Tenuicostatuni","Falcifer","Bifrons", "Variabilis","Thouarsense","Levesquei","Opalinum", "Murchisonae","Concavum","Sowerbyi","Sauzei", "Humphriesianum"}; short num_of_zone_in_stage[]={3,6,5,6,3,3}; /* large geographic regions in the Ammon */ static char *area[]={"Western Pacific","Western Tethyan", "North American'V'South American","N.W Europe"}; /* all countries represented in the Ammon */ static char *country[]={"Argentina","Austria","Britain","Canada", "Chile","China","Ecuador","France","Germany","Greece", Appendix 2 Source code for the user interface of Ammon 204 "Hungary","Iran","Ireland","Italy","Japan","Malagasay", "Mexico","Peru,,,"Portugar,,"Russia","Saudi Arabia", "Switzerland","UnitedStatesH,"Turkey"}; /* rib form classification based on treatise */ static char *ribForm[]={"straight","concave","convex","sinuous", "falcoid","falcate","biconcave","projected"}; /* rib furcation terms following Smith 1986 */ static char *ribFurc[]-{"intercalatory","bi","tri","multiH,"poly", "loop2",,,loop3","loopn","bundled"}; /* tubercle classification following Smith 1986 */ static char *tubercie[]={"uni,,,"bi","tri,,,,,multi","bullate","clavate"}; /* whorl shape classification following Smith 1986 */ static char *whorlShape[]={"oval","ogivar',"ellipsoid","rounded", " lanceolate"," rectangular"," quadrate", "triangular", "trapezoid","coronate","wellipsoid","wrectangular", "wtriangular"}; /* umbilical wall height */ static char *wallHeight[]={"highM,"low"}; /* umbilical wall slope */ static char *wallAng[]={"shallow","steep","vertical","undercut"}; /* venter shape following Smith 1986 */ static char *venter[]={"plain","carinate","sulcate","carinate-sulcate", "bicarinate"}; /* source for the data in Ammon, should be reorganized in a more structured way, such as a two level menu system */ static char *reference[]={"Arkell Etc 1957","Arthur 1985", "Atlas Ed. By Repin 1968","Blasco 1978","Crickmay","Dagis", "Dean,Donovan,Howarth 1961","Erben 1956","Frebold", "Frebold and Mountjoy etc 1967","Gabb 1869","Gabilly 1976", "Geczy 1976","Geyer","Guex","Hall 1987", Appendix 2 Source code for the user interface of Ammon 205 Frame Frame Canvas Pixwin "Hall And Westerman 1980","Hall and Howarth 1983", "Hillebrandt","Hirano","Imlay 1968","Imlay 1981", "Jakobs 1992","Kalacheva 1980","Mclearn 1932","Meister 1986", "O'brien 1985","Palfy 1991","Poulton", "Poulton And Tipper 1991","Quinzio Sinn 1987","Repin 1974", "Schlatter 1991","Schlegelmilch ^ e y S m i t h 1976","Smith 1981", "Smith And Tipper","Stankevich 1964","Taylor 1988", "Thomson And Smith 1992","Tilmann 1917", "Tipper and Smith etc 1991","Wang And Smith 1986", "White 1889","Whiteaves 1884","Wiedenmayer 1977", "Wiedenmayer 1980","Others"}; command_frame; /* root frame to host menus and utilities*/ display_window; /* window for image display */ image_canvas; /* area in the display_window for image display */ *pw; /* text window for diplaying the textual information of the selected specimen */ Textsw text_win; Panel Panel command_win; /* left window hosting all menus and utilities */ info_panel; /* top window hosting query field and other textual information */ /* define sizes of the above windows, its location can be infered */ struct size { int width; int height; } screen_rect = {1152, 900}; struct size command_rect = {175, 900}; struct size info_rect = {980, 300}; struct point { int x; int y; }between[2]={{0,0},{0,0}}; struct point control_point[100]; Panel_item condition_text, show_num, wait_num; PaneMtem bright, contrast; Pixfont *font; unsigned char red [256], green [256], blue [256]; colormapt colormap = { RMTEQUALRGB, 256, red, green, blue }; Appendix 2 Source code for the user interface of Ammon 206 /* use the shell icon as the system icon */ static short icon_data[] = { #include }; static mpr_static(ammon_icon, 64, 64, 1, icon_data); static char interface_image = "/home/liang/interface.ras"; char *path; /* record which menu has been selected */ char *image_name[MAX_IMAGE]; char *query_statement, *search_condition[12]; int num_of_Items; /* number of specimens retrieved */ int choice; /* record which menu item has been selected */ int cs; /* base brightness of image */ int start_status=0;/* info panel is not initialized yet */ int In_sublist = 0; /* specimen is not in the sub (species) list instead it is in the main (genus) list */ int display_from, displayto; /* display status */ int from_menu; /* whether query is issued from menu */ int num_control_point; int rel[MAX_IMAGE]; /* index conversion between image_name and descriptor_value */ int displayed[MAX_IMAGE]; /* image hasn't been displayed (0);forward displayed (1); backward displayed (-1) */ int seq[MAX_IMAGE]; /* order images by height */ double image_scale; /* global functions */ void void void void void void void void void void void void void void 2. retrieve.h create_menu_button(); create_command_button(Frameframe_local); init menu(); init_info_panel(Frame frame local); menu_handler(); /* action upon menu item selection */ query_frorn_menu(); query_from_text(); execute_query(); sort_image_list(); build_full_name(); adjust_display_window(); display_images(); query_to_plain(char *buf) stop_op(); /* specific data declarations for retrieve.c, not shared by morph.c */ Appendix 2 Source code for the user interface of Ammon 207 /* define the array index for descriptor_name */ #define SYNSPECIES 11 /* image is in the main (genus) list instead of species sublist */ #define MAINLIST 2 /* after the first query, the display window splits into three subwindows */ from top to bottom, they are info panel, text subwindow and image canvas */ all three windows have the same width and their heights add up to screen height */ struct size int int { width; height; } text_rect = {980, 128}; struct size canvas_rect = {980, 720}; int Sublist[MAX_IMAGE]; /* whether the image is in species sublist */ int break_point_u\j*enus; /* point where program get into the species sublist */ /* functions not shared with morph module */ void main_list(); void gotospecimenO; void find_species(); void save_as(); 3. retrieve, c /* main program of the Ammon user interface */ #include main(argc, argv) int argc; char **argv; { Appendix 2 Source code for the user interface of Ammon 208 int i, j ; Scrollbar vertical_sb; /* create a frame to host the left command window */ command_frame = window_create(NULL, FRAME, FRAME_LABEL, "Ammon Image Database", FRAME_SHOW_LABEL, TRUE, WIN_WIDTH, command_rect.width, WINHEIGHT, command_rect.height, WIN_X,0, WTN_Y, 0, FRAMEJCON, icon_create(ICON_IMAGE, &ammon_icon, 0), 0); /* create the command window to host the menu and command buttons */ command_win = window_create(command_frame, PANEL, PANEL_LABEL_BOLD, TRUE, PANEL_SHOW_MENU, TRUE, o); /* load font to label menu and command buttons */ font=pf_open("/apps/sundesk/fonts/sunview/lucida-19. v"); create_menu_button(); create_command_button(); init_menu(); /* create a frame to host the info and canvas window at the right side of the command window */ display_window = window_create(NULL, FRAME, FRAME_LABEL, " Welcome Window", FRAME_SHOW_LABEL, TRUE, WIN_X, command_rect.width, WIN_Y, 0, WIN_SHOW,TRUE, WIN_WIDTH, screenrect.width-commandrect. width, WIN_HEIGHT,screen_rect.height, 0); Appendix 2 Source code for the user interface of Ammon 209 /* create the info panel giving an introduction to the system */ init_info_panel(display_windo w); vertical_sb = scrollbar_create(SCROLL_LINE_HEIGHT, 5, (char *)0); /* 5 is the width of the scrollbar */ image_canvas=windo w_create(display_windo w, CANVAS, WIN_VERTICAL_SCROLLBAR, vertical_sb, CANVAS_RETAINED, FALSE, CANVAS_AUTO_SHRTNK, FALSE, WIN_CONSUME_PICK_EVENT, MS_LEFT, WIN_EVENT_PROC, canvasjiandler, WIN_X, 0, WIN_Y, info_rect.height+5, /* canvas under info panel */ WTNWIDTH, screenrect.width-commandrect. width, WIN_HEIGHT, screen_rect. height-info_rect. height- 5, 0); /* make the image_canvas a color canvas with 253 colors */ pw=(Pixwin *) window^get(image_canvas, WINPIXWIN); pw_putcolormap(pw, 0, 253, red, green, blue); /* reserve 3 color entries for bg and fg */ window_set(image_canvas, CANVAS_RETAINED, TRUE, o); /* load the interface image into the canvas */ load_interface_image(); /* allocate memory for retrieval results of database query */ for (i=0; ipr_size.x; h=image->pr_size.y; red[252]=255; /* color entry 252 gives pure red */ green[252]=blue[252]=0; pw_setcmsname(pw, "image_cmp"); pw_putcolormap(pw, 0, 253, red, green, blue); cs=red[l]; /* as an indicator of the brightness */ /* display the image in the middle of the canvas */ if (h #define MENU_START_ROW 0 /* row where menu items start */ #define MENU_INCREMENT 2 /* increment in terms of number of rows */ /* trace which family has been selected, taxonomy starts with 'a' */ static char *family_path[]={"aa","ab","ac",,,ad,,,"ae",,,af,,"ag","ah", ,,ai,,,"aj,,,"akH,"al",,,am,,),,an,,)"ao",,,ap,,,,,aq",,,ar","as", "atVWVWVWVWVV/'azV'aAVaB'V'aCVaD"}; /* trace which stage has been selected, stratigraphy starts with 'b' */ static char *stage_path[]={ "ba","bb","be","bd","be","bf'}; /* five menu buttons */ static Panelitem button_Taxonomy,button_Stratigraphy,button_Geography; static Panelitem button_Morphology,button_Reference; /* five root-level menus associated with the buttons */ static Menu taxonomy_menu, stratigraphymenu, geographymenu; static Menu morphology_menu, referencemenu; /* two geography submenus */ static Menu area_menu, country_menu; /* nine morphology submenus */ static Menu rib_menu, ribformmenu, ribfurcjnenu; static Menu tubercle_menu, whorlshapemenu, wallmenu; static Menu wallheightmenu, wallangmenu, venter_menu; /* family menus under taxonomy, number of submenus is determined by the size of the family array */ #define numoffamily (sizeof family/sizeof family[0]) static Menu family_menu[num_of_family]; Appendix 2 Source code for the user interface of Amnion 212 /* stage menus under stratigraphy, number of submenus is determined by the size of the stage array */ #define numofstage (sizeof stage/sizeof stage[0]) static Menu stage_menu[num_of_stage]; / * The followings are menu related functions */ static void find_path(); 5. amenu.c ^include #include /* create the menu buttons for five root level menus */ extern void create_menu_button() { panel_create_item(command_win,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_Y,ATTR_ROW(MENU_START_ROW), PANEL_LABEL_STRING, "Retrieve by:", 0); buttonTaxonomy = panel_create_item(command_win,PANEL_BUTTON, PANELJTEMX, ATTRCOL(O), PANEL_ITEM_Y, ATTR_ROW(MENU_START_ROW+MENU_INCREMENT), PANEL_EVENT_PROC, menu_handler, PANELLABELJMAGE, panel_button_image(command_win," Taxonomy =>", 13,font), o); button_Stratigraphy = panel_create_item(command _win,PANEL_BUTTON, PANEL_ITEM_X, ATTR_COL(0), PANELJTEMY, ATTR_ROW(MENU_START_ROW+2*MENU_INCREMENT), PANEL_LABEL_FONT, font, PANEL_EVENT_PROC, menu_handler, PANEL_LABEL_IMAGE, panel_button_image(command_win," Stratigraphy =>", 13,font), o); Appendix 2 Source code for the user interface of Ammon 213 buttonGeography = panel_create_item(command_win,PANEL_BUTTON, PANEL_ITEM_X, ATTR_COL(0), PANEL_ITEM_Y, ATTR_ROW(MENU_START_ROW+3*MENU_INCREMENT), PANEL_EVENT_PROC, menu_handler, PANEL_LABEL_IMAGE, panel_button_image(command_win, "Geography =>", 13,font), 0); button_Morphology = panel_create_item(command_win,PANEL_BUTTON, PANEL_ITEM_X, ATTRCOL(O), PANEL_ITEM_Y, ATTR_ROW(MENU_START_ROW+4*MENU_INCREMENT), PANEL_EVENT_PROC, menu_handler, PANELLABELJMAGE, panel_button_image(command_win, "Morphology =>", 13,font), 0); button_Reference = panel_create_item(command_win,PANEL_BUTTON, PANEL_ITEM_Y, ATTR_ROW(MENU_START_ROW+5*MENU_INCREMENT), PANELEVENTPROC, menujiandler, PANEL_LABEL_IMAGE, panel_button_image(command_win, "Reference =>", 13, font), o); } extern void init_menu() { register int i, j , from, to; /* Create Taxonomy Menu */ from=to=0; for (i=0;i static int x, y; static int width[MAX_IMAGE], height[MAXJMAGE]; static int current_page[200]; /* conversion between index on the page and general image list */ static int num_in_page; /* number of images on the page */ /* initialize and display the first screen of the images */ extern void display_images() { register int i, j , k; char tmp[10]; FILE *fp; Pixrect * image; struct rasterfile rh; /* read width and height for all retrieved images */ for (i=0; iheight[seq[i]]) { k=seq[i]; seq[i]=seq[j]; seq[j]=k; } clear_canvas(); /* make ready for display */ /* if the height of the largest image > canvas height, increase the canvas height */ if (height[seq[ 1 ]]>screen_rect.height-info_rect.height-20) (void)window_set(image_canvas, CANVAS_HEIGHT, height[seq[l]]+20, 0); cs=rx=y=display_to=0; Appendix 2 Source code for the user interface of Amnion 222 display_from=l; num_in_page=0; displayto = num_of_Items; for (i=0; idisplay_to) /* following previous page operation */ k=display from=display_to=display from+1; else k=display_from=display_to; num_in_page=cs=:x=y=j=0; /* start of a new page */ displayto = numofltems; for (i=k; i= display from) k = num_of_Items-display_to-l; else if (displayto < display_from) k=display_to-l; } else k = 0; sprintf(tmp,"%d",k); panel_set(wauVnum, PANELJVALUE, tmp, 0); } else panel_set(wait_num, PANELVALUE, "No!", 0); } /* turn the page backwards */ static void previous_page() { int i, k; char tmp [10]; /* haven't reached the begining of the image list */ if (displayto && display_from) { clear_canvas(); /* record where it starts */ Appendix 2 Source code for the user interface of Ammon 224 if (display_to0; i - ) if (displayed[seq[i]] != -1) /* hasn't been displayed backwards */ if (!display_specimen(i, -1)) { /* -1 -> display backwards */ displayto = i; break; /* end of the page */ } modify_colormap(); /* adjust brightness based on all images of the page */ /* show the number of images still waiting to display */ if(displayto) k = display_to; else k = 0; sprintf(tmp,"%d",k); panel_set(wait_num, PANEL_VALUE, tmp, o); } else panel_set(wait_num, PANEL_VALUE, "No!", 0); } /* find all images of the speciemn sp and display them */ static int display_specimen(sp, direction) int sp, direction; { register int i, j , j 1, j 2, k, order[ 10]; FILE *fp; Pixrect * image; Appendix 2 Source code for the user interface of Ammon 225 /* images from the same specimen are sequential */ /* find the lower limit */ i=seq[sp]; while (rel[~i]==rel[seq[sp]]) ; ji=i+i; /* find the upper limit */ i=seq[sp]; while (rel[++i]=rel[seq[sp]]) ; J2=i-1; /* reorder the images of the specimen by height */ ifG2>jl) { for(i=jl;i<=j2;i++) order[i-jl]=i; for(i=0;iheight[order[i]]) { k=order[i]; order[i]=order[j]; order[j]=k; } } else order[0]=seq[sp]; /* display the images in order */ k=0; /* the current height reached by tiled images */ for(i=0;iwid) { x=0; y+=k; k = height[order[i]]; } if (y+height[order[i]]255) ? 255:cs+i-l; green[252]=blue[252]=0; panel_set_value(bright,0); panel_set_value(contrast, 10); pw_setcmsname(pw, "image_cmp"); pw_putcolormap(pw, 0, 253, red, green, blue); } /* locate the selected image in the image list * extern int image_index(xo, yo) int xo,yo; { register int i, k, x 1, y 1, j=-1; Appendix 2 Source code for the user interface of Ammon 227 xl=yl=0; k=height[current_page[0]]; for (i=0; iwid) { y l + = k ; k = height[current_page[i]]; x l = 0 ; } /* (xo, yo) falls within the range of image j */ if (xo>xl && xoyl && yoIMAGE && iONTOGENY && KAPPROX) && (f=atof(descriptor_value[i][rel[index_of_image]]))>0) /* quantitative parameters */ { /* data exists for this descriptor */ sprintf(tmp,"%s:%5.2f",descriptor_name[i],f); textsw_insert(text_win, tmp, strlen(tmp)); } elseif(descriptor_value[i][rel[index_of_image]][0] !=") { /* data exists for this descriptor */ k=len[i]-2; while (descriptor_value[i][rel[index_of_image]][k~] = ") ; descriptor_value[i][rel[index_of_image]][k+2]=^'; sprintf(tmp,"%s:%s. ",descriptor_name[i], descriptor_value[i][rel[index_of_image]]); textsw_insert(text_win, tmp, strlen(tmp)); } textsw_insert(text_win, "\n", 1); } 7. query.c #include /* construct a query statement from a selected menu item */ extern void query_from_menu() { register int i, j , depth, entry; char tmp[ 150]; depth = 1; while (path[depth] != M)') depth++; /* the depth of the menu item */ Appendix 2 Source code for the user interface of Ammon 229 j='A'-('z'-'a'+l); /* upper case conversion */ switch (path[0]) { case 'a': /* a menu item in taxonomy */ if (depth=2 && Ichoice) { /* select a family */ query_statement=" select * from OP S $liang. ammonjmage where family= :"; if (path[ 1 ]>'a'-1) /* lower case */ search_condition[0]=family[path[ 1 ]-'a']; else /* upper case */ search_condition[0]=family[path[l]-j]; } else if (depth=2 && choice) { /* select a genus */ query_statement=" select * from OPS$liang.ammon_image where synonymy= :"; if (path[ 1 ]>'a'-1) /* lower case */ depth=path[l]-'a'; else depth=path[l]-j; /* upper case */ entry=0; for (i=0; Kdepth; i++) entry += num_of_^enus_in_family[i]; entry += choice-1; /* genus at entry is selected */ search_condition[0]=genus[entry]; • } break; case V: I* a menu item in stratigraphy */ if (depth=2 && Ichoice) {/* select a stage */ querystatement-'select * from OPS$liang. ammon_image where stage=:"; search_condition[0]=stage[path[l]-'a']; } else if (depth=2 && choice) { /* select a zone */ query_statement-'select * from OPS$liang. ammonjmage where eurzone= :"; depth=path[l]-'a'; /* lower case */ entry=0; for (i=0; i=2) { switch (path[l]) { case 'a': /* rib */ if (path[2]-'a') { query_statement=" select * from OPS $liang. ammonimage where fiirc like:"; search_condition[0]= (char *)strdup(ribFurc[choice-1 ]); elseif(path[2]-'a'-l) { query_statement=" select * from OP S $liang. ammonjmage where pform like :"; search_condition[0]= (char *)strdup(ribForm[choice-l]); } break; case 'b': querystatement-' select * from OP S $liang. ammonimage where tuberc like:"; search_condition[0]= (char *)strdup(tubercle[choice-1 ]); break; case 'c': querystatement-'select * from Appendix 2 Source code for the user interface of Ammon 231 case 'd': break; case 'e': OPS $liang. ammonjmage where whorlshape like :"; search_condition[0]= (char *)strdup(whorlShape[choice-1 ]); break; if (path[2]-'a') { querystatement-' select * from OPS$liang.ammon_image where uwallang like :"; search_condition[0]= (char *)strdup(wallAng[choice-l]); } else if (path[2]-'a'-l) { query_statement="select * from OPS$liang.ammon_image where uwallht like :"; search_condition[0]= (char *)strdup(wallHeight[choice-1 ]); query_statement="select * from OP S $liang. ammon_image where venter like :"; search_condition[0]= (char *)strdup(venter[choice-1 ]); break; } tmp[0]=0; /* bd is the bind variable in Oracle dynamic SQL statement */ sprintf(tmp, "%s bd",query_statement); query_statement=(char *)strdup(tmp); /* SQL 'like' operator needs % to indicate containing */ sprintf(tmp,"%s%s%s","%",search_condition[0],"%"); search_condition[0]=(char *)strdup(tmp); } break; case 'e': /* a menu item in reference */ if (choice) { query_statement=" select * from OP S Sliang. ammonjmage Appendix 2 Source code for the user interface of Ammon 232 where refauthyear like :"; search_condition[0]=(char *)strdup(reference[choice-1 ]); i=strlen(search_condition[0]); search_condition[0] [i]='%'; search_condition[0] [i+1 ]=*\0'; tmp[0]=0; sprintfXtmp,"%sbd",query_statement); query_statement=(char *)strdup(tmp); } break; } if (!strstr(query_statement, "like :")) { tmp[0]=0; sprintf(tmp, "%s bd",query_statement); query_statement=(char *)strdup(tmp); } } /* construct a query statement from the text field */ extern void query_from_text() { int register i, j , k, ind, nl=0; char *buf, *replace(), tmp[200],tmpl[200]; if(lstartstatus) { adjust_display_window(); return; } ln_sublist=0; /* construct the query statement from condition field */ buf=panel_get_value(condition_text); buf=substitute(buf,,,= :",,,="); buf=substitate(buf, "like: "/'like''); buf=substitute(buf, »>;»;•>»); buf=substitute(buf,"< :","<"); /* replace the bind variable value with bdl, bd2, */ sprintfftmp 1 ,"%s",replace(buf)); sprintf(tmp,"select * from OPS$liang.ammon_image where %s",tmpl); Appendix 2 Source code for the user interface of Ammon 233 query_statement=(char *)strdup(tmp); sprintf(tmp, "%s",buf); i=0; if (buf=(char *)strtok(tmp,":")) { ifCstrstrCbuClike")) nl=l; else nl=0; while (buf=(char *)strtok(NULL,":")) { j=k=0; if(nl) trnplU-t+l^/o'; else tmpl[j]=0; ind=l; while (ind || (buf[k] \="&& buf[k] !=')' && buflk] !=*\0')) if (buflk] !="){ tmpl[j-H-]=buf[k-H-]; ind=0; } else k++; if(nl) trnplD-H+^/o'; tmp iDH; if(strstr(buf)"like")) nl=l; else nl=0; search_condition[i++]=(char *)strdup(tmp 1); } execute_query(); if (num_of_Items) { from_menu=0; sort_image_list(); build_full_nameO; display_images(); } else { panel_set_value(show_num,"None !"); panel_set_value(wait_num,"0"); } } else panel_set_value(condition_text,"Invalid Search Statement!"); } /* replace ': bind variable value1 in s with bdl, bd2,.. */ Appendix 2 Source code for the user interface of Ammon 234 extern char * replace(s) char *s; { register int i, j , k, ind; char tmp[200], tp[10], *buf; i=strlen(s); tmp[0]=0; while (buf=(char *)strstr(s,":")) { strncat(tmp, s,i-strlen(buf)); sprintfCtp," : bd%d"j++); strcat(tmp,tp); k=ind=l; /* skip bind variable value */ while (ind || (buf[k] !='' && buf[k] !='\0' && buf[k] !=')')) { if(buf[k]!=M) ind=0; k++; } s=&buf[k]; i=strlen(s); } strcat(tmp,s); s=(char *)strdup(tmp); return s; } 8. dbms.pc /* all database related operations are in this file which need to be compiled by Oracle precompiler before proceeding with cc and combine with other source code */ #include #include EXEC SQL BEGIN DECLARE SECTION; extern char *query_statement; extern char *search_condition[12]; char oracleid = V; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; Appendix 2 Source code for the user interface of Ammon 235 EXEC SQL INCLUDE SQLDA; /* Declare the bind and select descriptors. */ SQLDA *bind_dp; SQLDA *select_dp; extern SQLDA *sqlald(); extern void sqlprc(); extern void sqlnul(); int nullok; extern void execute_query() { register int i j ,k ; int precision, scale; float tmp; double atof(); /* Automatic log on to ORACLE */ EXEC SQL CONNECT :oracleid; /* Set up ORACLE error handling. */ EXEC SQL WHENEVER SQLERROR GOTO sqlerror; bind_dp = sqlald(12, 30,0); bind_dp->N = 12; /* the maximum number of binding variables */ select_dp = sqlald (NUM_OF_DESCRIPTOR, 15, 0); select_dp->N = NUMOFDESCRIPTOR; /* Prepare the statement and declare a cusor. */ EXEC SQL PREPARE S FROM :query_statement; EXEC SQL DECLARE C CURSOR FOR S; EXEC SQL DESCRIBE BIND VARIABLES FOR S INTO bind_dp; /* If F is negative, there were more bind variables than originally Appendix 2 Source code for the user interface of Amnion 236 allocated by sqlald(). */ if(bind_dp->F<0) { printf("\nToo many bind variables for descriptor."); goto sqlerror; } /* Set the maximum number of array elements in the descriptor to the number found. bind_dp->N = bind_dp->F; for (i=0; iF; i++) { bind_dp->L[i] = strlen(search_condition[i]); bind_dp->V[i] = search_condition[i]; bind_dp->I[i] = 0; bind_dp->T[i]=l; /* Open the cursor and define the active set. */ EXEC SQL OPEN C USING DESCRIPTOR bind_dp; EXEC SQL DESCRIBE SELECT LIST FOR S INTO select_dp; /* If F is negative, there were more select-list items than originally allocated by sqlald(). */ if (select_dp->F <0) { printf("\nToo many select-list items for : %d", -(select_dp->F)); goto sqlerror; } /* Set the maximum number of array elements in the descriptor to the number found. */ select_dp->N = select_dp->F; /* Allocate storage for each select-list item. */ printf("\n\n"); for (i=0; iF; i++) { /* Turn off high-order bit of datatype. */ sqlnul (&(select_dp->T[i]), &(select_dp->T[i]), &null_ok); Appendix 2 Source code for the user interface of Ammon 237 switch (select_dp->T[i]) { case 1: /* CHAR datatype: no change in length needed. */ break; case 2: /* NUMBER datatype: use sqlprc() to extract precision and scale. */ sqlprc (&(select_dp->L[i]), &precision, &scale); /* Allow for maximum size of NUMBER. */ if (precision == 0) precision = 40; /* Also allow for decimal point and possible sign. */ select_dp->L[i] = precision + 2; /* Allow for a negative scale. */ if(scale<0) select_dp->L[i] += -scale; break; } /* Allocate space for the select-list data values. */ select_dp->V[i] = (char *)malloc(select_dp->L[i]); /* Coerce all datatypes to character. */ select_dp->T[i] = 1; } printf("\n\nM); /* Fetch each row selected */ EXEC SQL WHENEVER NOT FOUND GOTO end_query; j=MAX_SP-l; for(;;) { EXEC SQL FETCH C USING DESCRIPTOR select_dp; for (i=0; iF; i++) sprintf(descriptor_value[i] [j ],"%-.* s", select_dp->L[i]+1, select_dp->V[i]); j - - ; if G<0) { printf("\n Warning:Too many images meet the the search conditionVn The rest of images skipped.W); break; } } endquery: printf("\nNumber of rows processed: %d\n",sqlca.sqlerrd[2]); num_of_Items=sqlca.sqlerrd[2]; /* Free space used by descriptors. */ for (i=0; iF; i++) free (select_dp->V[i]); Appendix 2 Source code for the user interface of Ammon 238 /* Free space used by the descriptors themselves. */ sqlclu (binddp); sqlclu (select_dp); EXEC SQL CLOSE C; EXEC SQL COMMIT WORK; puts(" HAVE A GOOD DAY!\n"); /* disconnect from Oracle database engine */ EXEC SQL COMMIT RELEASE; return; /* ORACLE error handler */ sqlerror: printf("\n\n%. 70s\n",sqlca. sqlerrm. sqlerrmc); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK; EXEC SQL COMMIT RELEASE; } 9. misc.c /* functions specific for user interface */ #include #include /* go back to main (genus) list from species sublist */ extern void main_list() { register int i, j ; char tmp[10]; i=display_from=num_control_point=0; j=seq[break_point_in_genus]; Sublist[break_pointjn_genus]=displayed|j]-0; for (i=break_point_in_genus+l; ibetween[0] .x && between[ 1 ] .y>between[0] .y) { xO=between[0].x; yO=between[0].y; image_out=mem_create(between[ 1 ] .x-xO,between[ 1 ] .y-y0,8); pw_read(image_out,0,0,between[ 1 ] .x-xO,between[ 1 ] .y-yO,PIX_SRC,pw,xO,yO); } else {/* save the whole image canvas */ image_out=mem_create(canvas_rect.width, canvas_rect.height,8); pw_read(image_out,0,0,canvas_rect.width,canvas_rect.height,PIX_SRC,pw,0,0); } pr_dump(image_out,fp,colormap, RTSTANDARD, 1); pr_close(image_out); fclose(fp); } else printf("Please Choose a File Name!"); } 10. utility.h /* this is a list of image file directories, data sources with a few plates are lumped into directory'others' */ static char *imageDir[] = {"andrew", "crickmay", "dagis", "donovan", "erben", "frebold","gabilly","geczy","guex","hall",,'hiUebrandt", "hirano", "howarth", "imlay", "jakob", "jaworski", "Jennifer", "jozsef, "kalacheva", "meister", "poulton", "quinzio", "repin", "riccardi", "robert", "Schlatter", "schleg", "smith", "stankevich", "taylor", "tilmann", "treatise", "westermann", "whiteaves", "white", Appendix 2 Source code for the user interface of Ammon 242 "wiedenmayer", "zeiss", "McLearn"}; 11. utility.c #include #include /* specimen may have multiple images which need to be separated before displaying */ extern void sort_image_list() { register int i, k, connect, j=0; char *buf, *bufl; char bufy[30], tmp[30]; /* image list starts with MAX NUM-1 */ for (i=MAX_SP-num_of_Items; KMAXSP; i++) { bufl=(char *)strdup(descriptor_value[35][i]); ifO>MAX_IMAGE-5) break; if (strchr(bufl,'|') != NULL) {/* multiple images in bufl separated by '|' */ buf=(char *)strtok(bufl,T); /* save the first image into the sorted image list */ sprintf(image_name|j++],"%s",buf); relD-l]=i; sprintf(bufy,M%s",buf); /* find the base of the image file name */ if(strchr(bufy,'-,)!=NULL) { /* there is a'-' in the image name */ connect=l; truncate(bufy,"-"); } else { /* there is no'-' in the image name */ Appendix 2 Source code for the user interface of Ammon 243 connect=0; k=strlen(bufy)-l; while (isdigit(bufy[k]) || bufy[k]=M) k-; bufy[k+l]^0'; } /* repeat the above process */ while ((buf=(char *)strtok(NULL,"|")) != NULL) { if (connect) { if (isdigit(buf[0]) && strchrCbuf,'-') !=NULL) { k=strlen(bufy)-l; while (isdigit(bufy[k])) k--; strncpy(tmp,bufy,k+1); tmpfk+lHO"; sprintf(image_name[j-H-],"%s%s",tmp,buf); rel[j-l]=i; sprintf(bufy,"%s",image_name[j-l]); truncate(bufy,"-"); } elseif(isdigit(buf[0])){ sprintf(image_name[j++],"%s-%s",bufy,buf); relD-l]=i; } else { k=strlen(bufy)-l; while (isdigit(bufy[k])) k--; if(bufy[k]==1p•) k~; strncpy(tmp,bufy,k+1); tmp[k+l]=A0'; sprintf(image_nameO++],"%s%s",tmp,buf); rel[j-l]=i; if (strchr(buf/-') != NULL) { sprintf(bufy,"%s",image_name[j-l]); truncate(bufy,"-"); } else { connect=0; bufy[++k]='f; bufy[++k]=*\0'; } } } /* end of if (connect) */ else { Appendix 2 Source code for the user interface of Ammon 244 } if (isdigit(buf[0]) && strchr(buf,'-') !=NULL) { sprintf(image_name[j-H-]j"%s-%s",bufy,buf); rel[j-l]=i; connect=l; sprintf(bufyJ"%s",image_name[j-l]); truncate(bufy,"-"); } else if (isdigit(buf[0]» { sprintf(image_name[j-H-],ll%s%s",bufy,buf); rel[j-l]=i; } else { k=strlen(bufy)-l; if(bufy[k]='p') k-S strncpy(tmp,bufy,k+1); tmp[k+l]=^'; sprintf(image_name[j-H-],"%s%s",tmp,buf); rel[j-l]=i; if (strchr(buf,'-') != NULL) { connect=l; sprintf(bufy,"%s",image_name[j-l]); truncate(bufy,"-"); } else \ if (bufy[k]='p') { bufy[++k]='f; bufy[++k]=,\0';} } } k=0; while (image_name[j-l][k] != ") ++k; image_name[j-1 ] [k]=I\0'; } else { /* single image in the name */ k=0; while ((image_name[j][k]=bufl[k]) !=' ') ++k; image_name[j ] [k]=l\0'; rel[j]=i; } } /* end of for loop */ Appendix 2 Source code for the user interface of Ammon 245 num_pf_Items=j; /* prepare for show_descriptor */ for (i=0; i0 && j<256) /* cs is the brightness of color entry 1 */ red[i]=green[i]=blue[i]=j; elseif(j<0) red[i]=green[i]=blue[i]=0; elseif(j>255) red[i]=green[i]=blue[i]=255; pw_setcmsname(pw, "image_cmp"); pw_putcolormap(pw, 0, 253, red, green, blue); } /* adjust the image brightness by modifying colormap */ extern void adjust_contrast() { register int i, j , k; k=(int) panel_j*et_value(contrast); for(i=l;i<252;i++) if ((j=cs+k*i/10)>0 && j<256) /* cs is the brightness of entry 1 */ red[i]=green[i]=blue[i]=j; elseifO<0) red[i]=green[i]=blue[i]=0; elseifG>255) red[i]=green[i]=blue[i]=25 5; pw_setcmsname(pw, "imagecmp"); pw_putcolormap(pw, 0, 253, red, green, blue); } /* produce negative of the image */ extern void reverse() { register int i; for(i=l;i<252;i-H-) red[i]=green[i]=blue[i]=255-red[i]; pw_setcmsname(pw, "imagecmp"); pw_putcolormap(pw, 0, 253, red, green, blue); Appendix 2 Source code for the user interface of Ammon 247 } extern void quit(item, event) { /* quit without user confirmation */ if(textwin) textsw_reset(text_win, 0,0); (void)window_set(command_frame, FRAME_NO_CONFIRM, TRUE, 0); (void)window_destroy(command_frame); (void)window_set(display_window, FRAME_NO_CONFIRM, TRUE, 0); (void)window_destroy(display_window); } extern void help(client, event) Notify_client client; Event *event; { alert_prompt( (Frame)client, NULL, ALERT_MESSAGE_STRINGS, "To be implemented", 0, ALERTBUTTONNO, "Cancel", ALERT_OPTIONAL, 1, ALERT_NO_BEEPING, 1, o); } /* convert query statement into plain text */ extern query_to_plain(buf) char *buf; { buf=substitute(buf,"=","= :"); buf=substitute(buf, "like","like :"); buf=substitute(buf,"> ","> :"); buf=substitute(buf,"< ","< :"); buf=substitute(buf,"","%"); Appendix 2 Source code for the user interface of Ammon 248 } /* replace string pattern s2 with si in s */ static char * substitute^, sl,s2) char *s, *sl, *s2; { register int i, j ; char tmp[200], *buf, *bufy; buf=s; i=strlen(buf); j=strlen(s2); tmp[0]=0; while (bufy=(char *)strstr(buf,s2)) { strncat(tmp,buf,i-strlen(bufy)); strcat(tmp,sl); buf=&bufy[j]; i=strlen(buf); } strcat(tmp,buf); s=strdup(tmp); return s; } static char * truncate(sl,s2) char *sl, *s2; { register int i; i=0; while (si[i++] != s2[0]) sl[--i]=:\0'; return si; } /* if lots of specimens meet the search condition, it will take a long time to complete the query, if you want to quit before it finishes simply press the STOP key */ extern void * stop_op() Appendix 2 Source code for the user interface of Ammon 249 { exit (0); } 12. win.h /* button locations */ #define COMMAND_START_ROW 12 #define COMMANDINCREMENT 2 /* introductory text locations */ #define X_START 140 #define Y_START 90 #define YJNCREMENT 25 static void adjust_info_panel(Panel local_panel); 13. win.c /* windows, buttons related functions */ #include #include #include /* introductory text locations */ #define X_START 140 #define Y_START 90 #defme Y INCREMENT 25 extern void create_command_button(frame_local) Frame framelocal; { panel_create_item(frame_local,PANEL_BUTTON, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW), PANEL_ITEM_X, ATTR_COL(0), PANEL_NOTEFY_PROC, queryfromjext, PANEL_LABEL_IMAGE, panel_button_image (frame_local,"Combination",13,font), Appendix 2 Source code for the user interface of Amnion 250 0); panel_create_item(frame_local,PANEL_MESSAGE, PANELJTEMY, ATTR_ROW(COMMAND_START_ROW+COMMAND_INCREMENT), PANEL_LABEL_FONT, font, PANEL_LABEL_STRING,"Some Utility:", 0); panelcreate item(frameJocal,PANEL_BUTTON, PANELJTEMY, ATTR_ROW(COMMAND_START_ROW +2*COMMAND_INCREMENT), PANEL_ITEM_X, ATTR_COL(0), PANELJsTOTIFYPROC, next_page, PANEL_LABEL_IMAGE, panelbuttonjmage (frame_local,"Next Page", 13,font), o); panel_create_item(frame_local,PANEL_BUTTON, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW +3 *COMMAND_INCREMENT), PANEL_ITEM_X, ATTR_COL(0), PANEL JsTOTIFYPROC, previous_page, PANEL_LABEL_IMAGE, panel_button_image (frame_local, "Previous Page",13,font), o); panel_create_item(frame_local,PANEL_BUTTON, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW +4*COMMAND_INCREMENT), PANEL_ITEM_X, ATTR_COL(0), PANEL_NOTIFY_PROC, goto_specimen, PANELLABELIMAGE, panelbuttonimage (frame_local,"Goto Specimen", 13,font), o); panel_create_item(frame_local,PANEL_TEXT, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW +5*COMMAND_INCREMENT), PANEL_LABEL_STRING, "Brightness:", 0); bright=panel_create_item(frame_local,PANEL_SLIDER, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW +6*COMMAND_INCREMENT+l), PANEL_SHOW_VALUE, FALSE, Appendix 2 Source code for the user interface of Ammon 251 PANEL_VALUE, 0, PANEL_MIN_VALUE, -50, PANEL_MAX_VALUE, 50, PANELSLIDERJWIDTH, 94, PANEL_NOTIFY_PROC, adjustbrightness, 0); panel_create_item(frame_local,PANEL_TEXT, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW +7*COMMAND_INCREMENT+l), PANEL_LABEL_STRING, "Contrast:", 0); contrast=panel_create_item(frame_local,PANEL_SLIDER, PANELJTEMY, ATTRJlOW(COMMAND_START_ROW +8 *COMMAND_INCREMENT), PANEL_SHOW_VALUE, FALSE, PANEL_VALUE, 10, PANEL_MTN_VALUE, 1, PANEL_MAX_VALUE, 20, PANEL_SLIDER_WIDTH, 94, PANEL_NOTIFY_PROC, adjust_contrast, 0); panel_create_item(frame_local,PANEL_BUTTON, PANELJTEMY, ATTR_ROW(COMMAND_START_ROW +9*COMMAND_INCREMENT+1), PANEL_ITEM_X, ATTR_COL(0), PANEL_NOTIFY_PROC, mainjist, PANEL_LABEL_IMAGE, panel_button_image (frame_local,"MainList",13,font), 0); panel_create_item(ftame_local, PANEL_TEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANELJTEMY, ATTR_ROW(COMMAND_START_ROW +10*COMMAND_INCREMENT+1), PANEL ITEMX, ATTRCOL(O), PANELNOTEFY JROC, find_species, PANELLAJBELIMAGE, paneljutton image (frameJocal,"Speci Sublist", 13,font). 0); panel_create item(frame local,PANEL_BUTTON, Appendix 2 Source code for the user interface of Amnion 252 PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW + 11 *COMMAND_INCREMENT), PANEL J T E M X , ATTR_COL(0), PANEL_NOTIFY_PROC, reverse, PANEL_LABEL_IMAGE, panel_button_image (frameJocal, "Reverse Image", 13,font), 0); panel_create_item(frame_local,PANEL_BUTTON, PANEL ITEMY, ATTR_ROW(COMMAND STARTROW +12 *COMMAND_INCREMENT), PANELJTEMX, ATTR_COL(0), PANELNOTIFY PROC, saveas, PANELLABEL IMAGE, panelbuttonimage (frame_local,"Save Image As", 13,font), 0); file_name=panel_create_item(frame_local,PANEL_TEXT, PANEL_ITEM_Y,ATTR_ROW(COMMAND_START_ROW +13 *COMMAND_INCREMENT), PANELLABELFONT, font, PANELJLABEL_STPJNG, "File:", o); panel_create_item(frame_local,PANEL_BUTTON, PANELITEMY, ATTR_ROW(COMMAND_START_ROW +14*COMMAND_rNCREMENT), PANEL J T E M X , ATTRCOL(O), PANEL NOTIFYPROC, help, P ANEL_L ABEL_IMAGE,panel_button_image(frame_local, "Help" ,4,font), 0); buttonQuit = panel_create_item(frame_local,PANEL_BUTTON, / PANELITEMY, ATTR_ROW(COMMAND_START_ROW +14 * COMMANDINCREMENT), PANELJTEMX, ATTR_COL(12), PANEL NOTIFYJROC, quit, PANEL_LABEL_IMAGE,panel_button_image(frameJocal,"Quit",4,font), 0); extern void initJnfo_panel(frame_local) Frame frame local; Appendix 2 Source code for the user interface of Ammon 253 /* font for displaying title */ font=pf_open("/apps/sundesk/fonts/sunpaint/R.24"); /* create info window to display the introduction text */ info_panel=window_create(frame_local, PANEL, PANEL_LABEL_BOLD, FALSE, WIN_X, 0, WIN_Y, 0, WIN_WH)TH, screen_rect.width-command_rect.width, WIN_HEIGHT, info_rect.height, 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_X, X_START-20, PANEL_ITEM_Y, Y_START-40, PANEL_LABEL_STRING, "WELCOME AMMONITE o); /* font for displaying introductory text */ font=pf_open("/apps/sundesk/fonts/sunview/lucida-19.v"); panel_create_item(info_panel,PANEL_MESSAGE, PANELJLABELFONT, font, PANEL_ITEM_X, X_START+80, PANEL_ITEM_Y, Y_START, PANELLABELSTRING, "You can retrieve Jurassic ammonites by", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELJTEMX, X_START, PANELITEMY, YSTART+YINCREMENT, PANEL_LABEL_STRING, "1. Taxonomy: Family, Genus, and Species", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELJTEM_X, X_START, PANEL ITEM_Y, Y_START+2*Y_INCREMENT, PANEL_LABEL_STRING, "2. Stratigraphy: Stage and Standard Zone", TO JURASSIC IMAGE DATABASE", Appendix 2 Source code for the user interface of Ammon 254 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELITEMX, XSTART, PANEL_ITEM_Y, YSTART+3 * YINCREMENT, PANEL_LABEL_STRING, "3. Geography: Geographic Area and Country.", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELITEMX, XSTART, PANELJTEMY, Y_START+4*YJNCREMENT, PANEL_LABEL_STRING, "4. Morphology: Volution, Expansion Rate, Whorl Shape, and Rib Form", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_X, X_START, PANEL_ITEM_Y, Y_START+5*YJNCREMENT, PANELLABELSTRING, "5. Reference: in which the figure of the specimen appears.", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELITEMX, XSTART+40, PANELJTEMY, Y_START+6*YJNCREMENT, PANELLABELSTRING, "You can also retrieve by combining the above criteria. ", o); } static void adjust_info_panel(local_panel) Panel local_panel { int i; char tmp[40], *buf; Panelitem item; /* destroy all old panel items in the info panel */ panel_each_item(local_panel, item) Appendix 2 Source code for the user interface of Amnion 255 panel_destroy_item(item); panel_end_each inforect. height = screen_rect.height-text_rect.height-canvas_rect.height; info_rect.width = screenrect.width-commandrect. width; window_set(local_panel, WINJHEIGHT, info_rect.height, WINWIDTH, info_rect. width, 0); /* display the query statement of the menu selection */ if(num_of_Items) { /* translate from SQL query to plain text, eliminate':' */ /* skip 'select * from OPS$liang.ammon_image where' in query statement */ buf=&query_statement[42]; query_to_plain(buf); i=strlen(buf); buf[i-2]=0; tmp[0]=0; sprintf(tmp,"%s%s",buf,search_condition[0]); } else tmp[0]=0; /* condition_text is the text field for query text display or input, you can type in a query and press the Combination button to search the database */ condition_text = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 180, PANEL_VALUE_DISPLAY_LENGTH, 200, PANEL_LABEL_X, ATTRCOL(O), PANELJLABELY, ATTRROW(O), PANEL_LABEL_STRING, "Search :", PANEL_VALUE, tmp, o); /* display number of images retrieved */ if (num_of_Items) sprintf(tmp,"%4d",num_of_Items); shownum = panel_create_item(local_panel, PANELTEXT, Appendix 2 Source code for the user interface of Ammon 256 PANEL_VALUE_DISPLAY_LENGTH, 5, PANEL_LABEL_X, ATTR_COL(0), PANELLABELY, ATTR_ROW(l), PANEL_LABEL_STRTNG, "Images Returned", PANEL_VALUE, tmp, 0); /* number of images wait to be displayed */ wait_num = panel_create_item(local_panel, PANEL TEXT, PANEL_VALUE_DISPLAY_LENGTH, 5, PANEL_LABEL_X, ATTR_COL(22), PANEL_LABEL_Y, ATTR_ROW(l), PANEL_LABEL_STRING, "Remained:", o); panel_paint(local_panel, PANEL_CLEAR); } extern void adjust_display_window(local_panel) Panel local_panel; { start_status=l;/* now the system has gone through at least one query */ adjust_info_panel(); /* adjust imagecanvas size due to the creation of a new text window */ window_set(image_canvas, WIN_X, 0, WINY, screen_rect.height-canvas_rect.height, WIN_WIDTH, canvas_rect.width, WINHEIGHT, canvas_rect.height, 0); text_win=window_create(display_window, TEXTSW, WINX, 0, WINY, screen_rect. height-canvas_rect. height-textrect. height, WINWIDTH, text_rect.width, WINHEIGHT, text_rect.height, 0); Appendix 2 Source code for the user interface of Ammon 257 } extern void canvas_handler(event) Event * event; { register int i, j ; if (event_is_up(event)) return; switch (event_action(event)) { case MS_LEFT: /* locate the image and display related info */ i=image_index(event_x(event),event_y(event)); if(i>=0) sho w_descriptors(i); break; case MSMIDDLE: /* mark the point with color 252 and determine the image scale */ pw_put(p w, event_x(event), event_y(event), 25 2); control_point[num_control_point].x=event_x(event); control_point[num_control_point].y=event_y(event); if(!num_control_point) { image_scale-atof(descriptor_value[SCALE][rel[image_index (event_x(event),event_y(event))]]); if (!image_scale) image_scale=1.0; } num_control_point++; case MS_RIGHT: /* mark two points for ploting brightness profile */ if(between[l].x || between[l].y) { i=between[l].x; j=between[l].y; between[ 1 ] .x=event_x(event); between[ 1 ] .y=event_y(event); between[0].x=i; between[0].y=j; } else if (between[0].x || between[0].y) { between[l].x=event_x(event); between[l].y=event_y(event); } else { between[0] .x=event_x(event); between[0]. y=event_y( event);} break; default: break; } Appendix 2 Source code for the user interface of Ammon 258 extern void clear_canvas() { (void)pw_writeback:ground(pw,0,OXint)(LINT_CAST(window_get(image_canvas, CANVAS_WIDTH)))J (int)(LINTj:AST(window^et(image_canvas, CANVAS_HEIGHT))), PIX_CLR); } Appendix 3 Source code for program imageEdit 259 Appendix 3 Source code for program imageEdit There are 5 files in this program: imagedit.h, main.c, utility.c, file.c, modify.c. 1. imagedit.h /* header file for imageEdit * * Author: Bo Liang * Department of Geological Sciences * The University of British Columbia * Date: May 1991 * Modifications: April 1994 */ #include #include #include #include #include #include #include #include ^include #include #include ^include #include #include #include /* maximum number of characters in the file path name */ #define MAXJPATHLEN 1024 #definePi 3.14159 #define MIN_WIDTH 700 /* minimum width of the window */ #define MAX_IMAGE 3000 /* maximum size of the image */ #define LOCATE 0 /* locate the area of interest */ #define CLEAN 1 /* clean the image */ Frame base_frame, Canvas canvas; Pixwin *pw; /* indicate the amount of change wanted */ Appendix 3 Source code for program imageEdit 260 Panelitem rotate, bright, contrast; /* clean or locate the image of interest */ Panelitem status; /* color used to erase noise or mark the border of the image */ Panel_item bordercolor, erasercolor, eraser_width; /* file name and directory */ Panelitem dirjtem, fnameitem; int w, h, bpp; /* image width, height and depth */ /* size of the base frame and canvas */ struct size { int width; int height; } frame_size = { 700, 900}; struct size canvas_size= {800, 1000}; unsigned char red [256], green [256], blue [256]; colormap_t colormap = { RMTEQUALRGB, 256, red, green, blue}; int x[2], y[2]; /* corner coords */ int edge[4][MAX_IMAGE]; /* buffer for old data of the four sides */ float aver, var, fct[2]; float *a; /* array to hold raw data of the image */ /* panel notify procs */ void load_image(); void save_image(); void quit(); void rotate_proc(); void rightness_proc(); void contrast_proc(); void image_edit(Event*, short, short, short); void init_data(); void reset_image(); /* canvas procs */ Appendix 3 Source code for program imageEdit 261 void modify_canvas(); void clear_canvas(); void handle_event(); 2. main.c /* main entry for imageEdit */ #include "imagedit.h" main(argc, argv) int argc; char **argv; { int i; void init_panel(), init_canvas(); /* create a base frame to hold the panel and image canvas. */ baseframe = window_create((Window) 0, FRAME, FRAME_LABEL, "INTERACTIVE IMAGE EDITOR", WIN_WIDTH, frame_size.width, WIN_HEIGHT, frame_size. height, FRAMEJCON, icon_create(ICON_IMAGE, &canvas_demo_pr, 0), FRAME_NO_CONFIRM, TRUE, FRAMEARGS, argc, argv, 0); /* initialize the info and command panel. */ init_panel(); init_canvas(); window_main_loop(base frame); exit(0); } static void init_panel() { Appendix 3 Source code for program imageEdit 262 Panel panel; char current_dir[MAX_PATH_LEN]; panel = window_create(base_frame, PANEL, PANELLABELBOLD, TRUE, 0); bright = panel_create_item(panel, PANELSLIDER, PANEL_LABEL_STRING, "Brightness Adjustment: ", PANEL_SLIDER_WIDTH, 100, PANEL_VALUE, 50, PANELMINVALUE, 0, PANEL_MAX_VALUE, 100, PANEL_NOTIFY_PROC, brightness_proc, o); contrast = panel_create_item(panel, PANELSLIDER, PANELLABELSTRING, "Contrast Adjustment: ", PANELSLIDERWIDTH, 100, PANEL_VALUE, 50, PANELMINVALUE, 0, PANELMAXVALUE, 100, PANELNOTIFYPROC, contrast_proc, o); rotate = panel_create_item(panel, PANELSLIDER, PANELLABELSTRING, "Rotate image: ", PANELSLIDERWIDTH, 100, PANELVALUE, 0, PANEL_MIN_VALUE, -90, PANEL_MAX_VALUE, 90, PANELNOTIFYPROC, rotate_proc, o); status = panel_create_item(panel, PANELCHOICE, PANEL_LABEL_X, ATTRCOL(O), PANELLABELY, ATTR_ROW(3), PANEL_LABEL_STRING, "Edit Options:", PANELCHOICESTRINGS, "Locate image", "Erase noise", 0, o); bordercolor = panel_create_item(panel, PANELTEXT, PANELLABELX, ATTR_COL(0), PANELLABELY, ATTR_ROW(4), Appendix 3 Source code for program imageEdit 263 PANEL_VALUE_DISPLAY_LENGTH, 3, PANELLABELSTRING, "Border color:", 0); eraser_color = panel_create_item(panel, PANELTEXT, PANEL_LABEL_X, ATTR_COL(19), PANEL_LABEL_Y, ATTR_ROW(4), PANEL_VALUE_DISPLAY_LENGTH, 3, PANEL_LABEL_STRING, "Eraser color:", 0); eraser_width = panel_create_item(panel, PANELTEXT, PANEL_LABEL_X, ATTR_COL(36), PANEL_LABEL_Y, ATTR_ROW(4), PANEL_VALUE_DISPLAY_LENGTH, 3, PANEL_LABEL_STRING, "Eraser width:", 0); diritem = panel_create_item(panel, PANEL_TEXT, PANEL_LABEL_X, ATTR_COL(55), PANEL_LABEL_Y, ATTR_ROW(0), PANEL_VALUE_DISPLAY_LENGTH, 23, PANEL_VALUE, getwd(current_dir), PANEL_LABEL_STRING, "Dir: ", 0); fhame_item = panel_create_item(panel, PANELTEXT, PANEL_LABEL_X, ATTR_COL(55), PANEL_LABEL_Y, ATTR_ROW(l), PANEL_VALUE_DISPLAY_LENGTH, 23, PANEL_LABEL_STRING, "File:", 0); (void) panel_create_item(panel, PANELBUTTON, PANELLABELX, ATTR_COL(55), PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE, panel_button_image(panel, "Load", 0, 0), PANEL_NOTIFY_PROC, load_image, 0); (void) panel_create_item(panel, PANELBUTTON, PANEL_LABEL_X, ATTR_COL(62), Appendix 3 Source code for program imageEdit 264 PANEL_LABEL_Y, ATTR_ROW(2), PANELLABELJMAGE, panel_button_image(panel, "Save", 0, 0), PANEL_NOTIFY_PROC, save_image, 0); (void) panel_create_item(panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(69), PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE, panel_button_image(panel, "Quit", 0, 0), PANEL_NOTIFY_PROC, quit, 0); (void) panel_create_item(panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(55), PANEL_LABEL_Y, ATTR_ROW(4), PANELLABELJMAGE, panel_button_image(panel, "Reset", 0, 0), PANEL_NOTIFY_PROC, reset_image, 0); (void) panel_create_item(panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(69), PANEL_LABEL_Y, ATTR_ROW(4), PANEL_LABEL_IMAGE, panel_button_image(panel, "Clear", 0, 0), PANEL_NOTIFY_PROC, clear_canvas, o); window_set(panel, PANELCARETITEM, fhameitem, 0); (void) window_fit_height(panel); } static void init_canvas() { Scrollbar verticalsb, horizontalsb; /* loaded image may be larger than the window size, need a scrollable canvas. */ vertical_sb = scrollbar_create(SCROLL_LINE_HEIGHT, 5, (char *) 0); horizontal_sb = scrollbar_create(SCROLL_LINE_HEIGHT, 5, (char *) 0); canvas = window_create(base frame, CANVAS, WIN_VERTICAL_SCROLLBAR, vertical_sb, WIN_HORIZONTAL_SCROLLBAR, horizontal_sb, Appendix 3 Source code for program imageEdit 265 CANVAS_RETAINED, FALSE, /* necessary for the following * modification */ CANVAS_AUTO_SHRINK, FALSE, WIN_EVENT_PROC, handle_event, CANVAS_FIXED_IMAGE, FALSE, CANVAS_WIDTH, canvas_size.width, CANVAS_HEIGHT, canvas_size. height, 0); window_set(canvas, WIN_CONSUME_PICK_EVENT, LOC_TRAJECTORY, 0); /* declare the canvas has 256 colors */ pw = (Pixwin *) windowj>et(canvas, WINPIXWIN); pw_setcmsname(pw, "rainbow"); pw_putcolormap(pw, 0, 256, red, green, blue); /* make it a color, retained canvas. */ window_set(canvas, CANVAS_RETATNED, TRUE, CANVAS_AUTO_CLEAR, TRUE, WIN_VERTICAL_SCROLLBAR, vertical_sb, WIN_HORIZONTAL_SCROLLBAR, horizontal_sb, 0); } 3. utility.c /* responses to mouse event */ #include "imagedit.h" extern void handle_event(canvas_local, event) Canvas canvaslocal; Event *event; { short upper_corner = FALSE; short lower_corner = FALSE; short erase = FALSE; if (event_is_up(event)) return; switch (event_action(event)) { case MS LEFT: Appendix 3 Source code for program imageEdit 266 upper_corner = TRUE; break; case MS_MIDDLE: erase = TRUE; break; case MS_RIGHT: lowercorner = TRUE; break; case LOCTRAJECTORY: if (window_get(canvas_local, WIN_EVENT_STATE,MS_MIDDLE)) erase = TRUE; break; default: break; } image_edit(event, lower_corner, upper_corner, erase); } extern void modify_canvas(width, height) int width, height; { if (widthpr_size.x; h=image_orig->pr_size. y; bpp=image_orig->pr_depth; Appendix 3 Source code for program imageEdit 268 modify_canvas(w,h); /* adjust canvas size */ panel_set_value(status,0); /* default status: locate area of interest */ /* let color entry 255 be green, easily visible in a grey scale image */ */ green[255]=255; red[255]=blue[255]=0; pw_setcmsname(pw, "rainbow"); pw_putcolormap(pw, 0, 256, red, green, blue); /* copy the image to window pw */ pw_rop(pw, 10,10,w,h,PIX_SRC,image_orig,0,0); pr_close(image_orig); fclose(fp); } /* save the specified area of pw as an image file */ static void save_image() { Pixrect *image_mody; int i, j , k; char *filename; FILE *fp; filename = panel_get_value(fname_item); /* get the file name */ if((fp=fopen(filename, "w")) = NULL) { printfC'Can't open this file !"); return; } if (!x[l] && !y[l]) /* if no specified area of interest, save the whole pw */ { x[0]=y[0]=0; x[l]=w; y[l]=h; } w=x[l]-x[0]-l; h=y[i]-y[0]-l; Appendix 3 Source code for program imageEdit 269 image_mody=mem_create(w,h,bpp); /* change the color map back to normal, entry 255 is white now */ red[255]=green[255]=blue[255]=255; if(bpp>l) { /* x[0]+l,y[0]+l help to skip the color border */ pw_read(image_mody,0,0, w,h,PIX_SRC,pw,x[0]+1 ,y[0]+1); pr_dump(image_mody,fp,&colormap, RT_BYTE_ENCODED, 1); } else /* black and white image */ { for (i=0; i xmax) xmax = xx[i]; if(yy[i] ymax) ymax = yy[i]; } wl = xmax - xmin + 1; /* width of the rotated image */ hi = ymax - ymin + 1; /* height of the rotated image */ wO = wl / 2; h0 = h l / 2 ; image_mody = mem_create(wl, hi, bpp); /* locate the coord, in the orig. image for each point in the new one */ fbr(i = 0 ; i= 0 && xx[5] < w && yy[5] >= 0 && yy[5] < h) k = pw_get(pw, xx[5], yy[5]); else k = 254; pr_put(image_mody, i, j , k); } w = wl; h = hl; } else { /* exactly 90 degree */ i = h; h = w; w = i; image_mody = mem_create(w, h, bpp); for (i = 0; i < w; i++) for(j = 0;j254) k = 254; /* entry 255 is reserved */ e lse i f (k254) k = 254; e lse i f (kwidth = atoi(panel_get_value(eraser_width)); if (brush->width < 0 || brush->width > w) brush->width = w /10; /* actually it is the height of the brush */ brush_wid = w / 20; /* real width of the brush, fixed for each image */ } else color_index = atoi(panel_get_value(eraser_color)); colorindex = atoi(panel^get_value(border_color)); if (colorindex < 0) color_index = 0; else if (colorjndex > 255) color_index = 255; if (bpp > 1) Appendix 3 Source code for program imageEdit 274 op = PIX_SRC | PIX_COLOR(color_index); else op = PIX_SRC | PIX_COLOR(0); /* use bg color */ /* take proper action based on mouse event */ if (status = CLEAN && erase) (void) pw_line(pw, eventx(event) - brush_wid, event_y(event), event_x(event) + brush_wid, event_y(event), brush, NULL, op); else if (status = LOCATE && uppercorner) { if (!x[0] && !y[0]) { /* the first time */ x[0] = event_x(event); y[0] = event_y(event); /* save original border data in edge */ for(i = 0 ; i < h -y[0];i++) edge[0][i] = pw^e t^w, x[0], y[0] + i); for(i = 0 ; i < w -x[0];i++) edge[l][i] = pw_get(pw, x[0] + i, y[0]); /* draw the upper border using the color of color_index */ (void) pw_vector(pw, x[0], y[0], x[0], h, op, 1); (void) pw_vector(pw, x[0], y[0], w, y[0], op, 1); } else { /* undo the old border before drawing a new one */ for (i = 0; i < h - y[0]; i++) pw_put(pw, x[0], y[0] + i, edge[0][i]); for (i = 0; i < w - x[0]; i++) pw_put(pw, x[0] + i, y[0], edge[l][i]); x[0] = event_x(event); y[0] = event_y(event); for (i = 0; i < h - y[0]; i++) edge[0][i] = pw_jget(pw, x[0], y[0] + i); for (i = 0; i < w - x[0]; i++) edge[l][i] = pw_get(pw, x[0] + i, y[0]); /* draw a new upper border using the color of colorindex */ (void) pw_vector(pw, x[0], y[0], x[0], h, op, 1); (void) pw_vector(pw, x[0], y[0], w, y[0], op, 1); Appendix 3 Source code for program imageEdit 275 } } else if (status = LOCATE && lowercorner) { if (!x[l] && !y[l]) { /* the first time */ x[l] = eventx(event); y[l] = event_y(event); /* save original border data in edge */ for(i = 0;i main(argc, argv) int argc; char **argv; { int Scrollbar vertical sb: /* create a frame to host the left command window */ command_frame = window_create(NULL, FRAME, FRAME_LABEL, "Ammon Image Database - Measurement module", FRAME_SHOW_LABEL, TRUE, WINWIDTH, command_rect.width, WINHEIGHT, command_rect. height, WINX, 0, WINY, 0, Appendix 4 Source code for interactive module 279 FRAMEJCON, icon_create(ICON_IMAGE, &ammon_icon, 0), 0); /* create the command window to host the menu and command buttons */ command_win = window_create(command_frame, PANEL, PANEL_LABEL_BOLD, TRUE, PANEL_SHOW_MENU, TRUE, 0); /* load font to label menu and command buttons */ font=pf_open(7apps/sundesk/fonts/sunview/lucida-19. v"); create_menu_button(); create_command_button(command_win); init_menu(); /* create a frame to host the info and canvas window at the right side of the command window */ display_window = window_create(NULL, FRAME, FRAME_LABEL, " Welcome Window", FRAME_SHOW_LABEL, TRUE, WIN_X, command_rect.width, WTN_Y, 0, WIN_SHOW,TRUE, WIN_WIDTH, screen_rect.width-command_rect.width, WIN_HEIGHT, screen_rect.height, 0); /* create the info panel giving an introduction to the system */ init_info_panel(display_window); vertical_sb = scrollbar_create(SCROLL_LINE_HEIGHT, 5, (char *)0); /* 5 is the width of the scrollbar */ image_canvas=window_create(display_window, CANVAS, WIN_VERTICAL_SCROLLBAR, vertical_sb, CANVAS_RETAINED, FALSE, CANVAS_AUTO_SHRINK, FALSE, WIN_CONSUME_PICK_EVENT, MS_LEFT, Appendix 4 Source code for interactive module 280 WIN_EVENT_PROC, canvasjiandler, WIN_X, 0, WIN_Y, info_rect.height+5, /* canvas under info panel */ WINWIDTH, screen_rect.width-command_rect. width, WIN_HEIGHT, screen_rect.height-info_rect.height-5, 0); /* make the imagecanvas a color canvas with 253 colors */ pw=(Pixwin *) window^etOmage^anvas, WIN_PIXWIN); pw_putcolormap(pw, 0, 253, red, green, blue); /* reserve 3 color entries for bg and fg */ window_set(image_canvas, CANVAS_RETAINED, TRUE, 0); /* load the interface image into the canvas */ load_interface_image(); /* allocate memory for retrieval results of database query */ for (i=0; ipr_size. x; h=image->pr_size.y; red[252]=255; /* color entry 252 gives pure red */ green[252]=blue[252]=0; pw_setcmsname(pw, "image_cmp"); pw_putcolormap(pw, 0, 253, red, green, blue); cs=red[l]; /* as an indicator of the brightness */ /* display the image in the middle of the canvas */ if (h #include "ammon.h" #include "morph.h" /* the following functions are used to measure images */ /* compute BISPACE in Amnion */ extern void bi_space() { char tmp[10]; float tp; tp=ratio(); /* use the points in the buffer */ if (tp) { sprintf(tmp,M%4.2f,,tp); sprintf(descriptor_value[BISPACE][0], "%s", tmp); } } /* measure the maximum diameter for the specimen */ extern void dmaxO { float tp; tp = distance(control_point[num_control_point-1 ],control_point[num_control_point-2]); sprintf(descriptor_value[DMAX][0], "%5.2f', tp/(image_scale*PIXEL_CM)); } /* compute number of secondary ribs per half whorl */ Appendix 4 Source code for interactive module 289 extern void sr_hw() { panel_set_value(text_item[5],density()); } /* compute number of tubercles per half whorl */ extern void t_hwO { panel_set_value(text_item[6],density0); } /* compute number of primary ribs per half whorl */ extern void rib_densityO { panel_set_value(text_item[4],density()); } /* use the number of control points in the buffer and their angular distance to calculate the density */ static char * density() { register int i; double sigma 1, sigma2, sigma; char tmp[10]; /* angles in terms of coiling axis */ if (!control_point[0].x || !control_point[0].y) { panel_set_value(parameter_info, "Please mark coiling axis!"); num_control_point=0; } else { tmp[0]=0; sigma 1 =atan2((double)(control_point[ 1 ].y-control_point[0] .y), (double)(control_point[ 1 ].x-control_point[0].x)); sigma2=atan2((double)(control_point[num_control_point-1 ].y-control_point[0]. y), (double)(control_point[num_control _point- l].x-control_point[0].x)); sigma=fabs(sigma2-sigma 1); sigma=(sigma>Pi) ? 2*Pi-sigma:sigma; Appendix 4 Source code for interactive module 290 i=(num_control_point-2) *Pi/sigma; sprintf(tmp,"%d",i); num_control_point=l;/* reserve the coiling axis, reset other points */ } return tmp; } /* measure the maximum whorl height */ extern void max_wh() { char tmp[10]; double tp, u, w; tp=distance(control_point[num_control_point-1 ], control_point[num_control_point-2]); sprintf(tmp,"%4.2f,,tp/(PIXEL_CM*image_scale)); panel_set_value(text_item[3],tmp); /* extrapolate the max diameter of the specimen */ u=atof(panel_get_value(text_item[2])); /* read the volution from info panel */ w=atof(panel^get_value(text_item[0])); /* read expansion rate from info panel */ i f (u&&w) { tp/=(1.0-u); tp*=(1.0+1.0/sqrt(w)); tp /= (image_scale*PIXEL_CM); sprintf(descriptor_value[DMAX][0],"%5.2f,,tp); } /* click 4 points to mark the rib width and length, compute rib width / rib length */ extern void rib_width() { char tmp[10]; float tp; tp=ratio(); if (tp) { sprintf(tmp,"%4.2f',tp); panel_set_value(text_item[7], tmp); /* show it in the relevant text field */ } Appendix 4 Source code for interactive module 291 } /* mark rib start, furcation and end points, compute the relative rib furcation position */ extern void furc_pos() { char tmp[10]; float tp; tp=ratio_of_three(); if (tp) { sprintf(tmp, "%4.2f',tp); panel_set_value(text_item[9], tmp); /* show it in the relevant text field */ } } /* mark the umbilical seam, tubercle and venter, compute the relative uni-tuberculate position */ extern void unitub_pos() { char tmp [10]; float tp; tp=ratio_of_three(); if (tp) { sprintf(tmp,"%4.2f',tp); panel_set_value(text_item[ 10], tmp); } } extern void finess_ratio() { char tmp[10]; double w_out, r[2], distl, dist2, sigma; point p; w_out=atof(panel_jget_value(text_item[0])); /* compute the distance between C and D' (see fig. 3-1) */ Appendix 4 Source code for interactive module 292 distl=distance(control_point[num_control_point-1 ], control_point[num_control_point-2]); r[l] = distl/(l+sqrt(l/w_out); /* radius with diameter distl */ /* if p is the middle point between A' and B' */ p.x = (control_point[num_control_point-3].x+ control_point[num_control_point-4].x)/2; p.y = (control_point[num_control_point-3].y+ control_point[num_control_point-4].y)/2; /* compute the distance between D' and p (see fig. 3-1) */ dist2=distance(control_point[num_control_point-1 ], p); /* align OP3 with axis y */ sigma=0.0; /* starting point with radius r[l] */ r[0]=r[l]; y[0] = r[l] -dist2; /* P3Y on page 26*/ while (sigma > -Pi) { sigma-= 1.0/r[0]; r[0]=r[ 1 ] *pow(w_out, sigma/(2*Pi)); y[ 1 ]=r[0] *cos(sigma); if (y[l]5) { panel_set_value(parameter_info,"Too many control points !"); num_control_point=0;} else { sprintf(tmp,"%s", panel_get_value(num_of_whorls)); num_whorls=atoi(tmp); /* PI and P2 are separated by numwhorls */ tmp[0]=0; if (Inumwhorls) { panel_set_value(parameter_info, "Please give number of whorls !"); Appendix 4 Source code for interactive module 295 goto end; } /* coiling axis */ x[0]=control_point[0].x; y [0]=control_point [0]. y; /* calculate distance between each control point and coiling axis */ for (i=l; i0 && sigma2-sigmalPi) /* angle between OP3 and OP4 must be less than Pi */ sigma = 2*Pi-sigma; /* compute expansion rate and volution */ u=r[2]/r[3]; /* U in Ammon */ /* expansion rate from inner coiling curve */ w_in=pow(r[2]/r[ 1 ], 1.0/(double)num_whorls); w_out=pow(r[3]/r[4],2*Pi/sigma); /* expansion rate from outer coiling curve */ /* display expansion rate and volution in the relevant text field */ sprintf(tmp,"%4.2f',w_out); panel_set_yalue(text_item[0],tmp); Appendix 4 Source code for interactive module end: } sprintf(tmp, "%4.2f >_in) ; panel_set_value(text_item[ 1 ],tmp); sprintf(tmp,"%4.2f,,u); panel_set_value(text_item[2],tmp); /* compute shell diameter */ tpO=r[3]*(l+1.0/sqrt(w_out))/(PIXEL_CM*image_scale); sprintftdescriptor_value[D][0],"%5.2f',tpO); /* compute whorl height/diameter */ tpO=tp/tpO; sprintftdescripto^valuefWHDJtOJ/ToS^f^tpO); /* compute quantitative volution */ tpO=(r[3]/w_out-r[2])/(PIXEL_CM*image_scale); if(tpCKO.O) tp=0.0; else tp=tpO/tp; sprintfCdescriptor_value[VOLUTION0][0],"%5.2f',tp); /* compute umbilical diameter */ tp0=r[2] * (1+1.0/sqrt(w_in))/(PIXEL_CM*image_scale); sprintf(descriptor_value[UD][0],"o/o5.2f*,tp0); panel_set_value(num_of_whorls,""); } /* superimpose the simulated coiling cure on top of the image */ static void plot_coiling(x, clock_wise, win, wout , r, sigmal) int x[], clockwise; float w_in, wou t ; double r[], sigmal; { register int x[3], y[3]; double tp; Appendix 4 Source code for interactive module 297 num_point=0; /* number of points on the coiling curve */ x[2]=y[2]=0; /* plot the outer coiling curve */ sigma=1.0/r[3]; /* starting point */ while (sigma<2*Pi) { tp=sigma 1 +clock_wise* sigma; r[0]=r[3]*pow(w_put,-sigma/(2*Pi)); x[l]=x[0]+r[0]*cos(tp); y[l]=y[0]+r[0]*sin(tp); if(x[l]!=x[2] | |y[l]!=y[2]){ x[2]=curve_points[num_point].x=x[ 1 ]; y[2]=curve_points[num_point].y=y[l]; /* curve_points can be used to restore the original image */ curve_points[num_point].z=pw_jget(pw,x[ 1 ],y[ 1 ]); pw_put(pw,x[l],y[l],252); /* color entry 252 - red */ num_point++; } sigma += 1.0/r[0]; /* angular increment step */ } /* plot the inner coiling curve */ sigmal=atan2((double)(control_point[2].y-y[0]),(double)(controlj5oint[2].x-x[0])); x[2]=y[2]=0; sigma=1.0/r[2]; r[0]=r[2]; r[l]=(r[l]<6)?r[l]:6; while (r[0]>r[ 1 ] && num_point< 10000) { tp=sigma 1 +clock_wise*sigma; r[0]=r[2]*pow(w_in,-sigma/(2*Pi)); x[l]=x[0]+r[0]*cos(tp); y[l]=y[0]+r[0]*sin(tp);' i f (x[l]!=x[2] | |y[ l]!=y[2]){ x[2]=curve_points[num_point] .x=x[ 1 ]; y [2]=curve_points[num_point] .y=y[ 1 ]; curve_points[num_point] .z=pwjget(pw,x[ l],y[ 1 ]); pw_put(pw,x[l],y[l],252); num_point++; } sigma += 1.0/r[0]; } } /* plot brightness profile between two points */ Appendix 4 Source code for interactive module 298 static void plotO { register int i, k, dist, x, y; struct size profile_rect; struct point profile_start; if (betweenf 1 ] .x 11 between[ 1 ] .y) { dist= distance(between[0], between[l]); profile_rect. width = dist; profile_rect.height = 256; profile_start.x = screen_rect.width-command_rect.width-profile_rect. width; profile_start.y = screen_rect.height-info_rect.height-profile_rect.height; (void)pw_writebackground(pw, profile_start.x, profilestart.y, profile_rect.width, profile_rect.height, PIX_CLR); for (i=0; i #include EXEC SQL BEGIN DECLARE SECTION; extern char *query_statement; extern char * search_condition[ 12]; char oracleid = V; Appendix 4 Source code for interactive module 299 VARCHAR modiry_statement[500]; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; EXEC SQL INCLUDE SQLDA; /* Declare the bind and select descriptors. */ SQLDA *bind_dp; SQLDA *select_dp; extern SQLDA *sqlald(); extern void sqlprcO; extern void sqlnulO; int nullok; extern void execute_query() { same as the one in Appendix 2 } extern void modify_database() { register int i, j , k; /* Automatic log on to ORACLE */ EXEC SQL CONNECT :oracleid; /* Set up ORACLE error handling. */ EXEC SQL WHENEVER SQLERROR GOTO sqlerror; bind_dp = sqlald (40, 20, 0); bind_dp->N = 40; /* Prepare the statement. */ EXEC SQL PREPARE S FROM :modify_statement; EXEC SQL DESCRIBE BIND VARIABLES FOR S INTO bind_dp; Appendix 4 Source code for interactive module 300 /* If F is negative, there were more bind variables than originally allocated by sqlaldQ. if(bind_dp->F<0) { printf("\nToo many bind variables for descriptor."); goto sqlerror; } /* Set the maximum number of array elements in the descriptor to the number found. bind_dp->N = bind_dp->F; j=0; /* copy only morph paramters which have been changed */ for (i=DMAX; iL[j] = strlen(descriptor_value[i][0]); bind_dp->V[j] = malloc(bind_dp->L[j]+l); strcpy (bind_dp->V[j], descriptor_value[i][0]); bind_dp->I[j] = 0; bind_dp->T[j++] = 1; } /* figure out the name of the selected image */ k=rel[image_index(control_point [0]. x, control_point [0]. y)]; i=0; while (image_name[k][i++] != ") ; bind_dp->L[j] = i-1; /* image name as condition. */ bind_dp->V[j] = malloc(bind_dp->LO]+l); strcpy (bind_dp->V[j], image_name[k]); bind_dp->I[j] = 0; bind_dp->T[j] = l; EXEC SQL EXECUTE S USING DESCRIPTOR bind_dp; printf("\nNumber of rows processed: %d\n",sqlca.sqlerrd[2]); /* Free space used by descriptors. */ for (i=0; iF; i++) free (bind_dp->V[i]j; /* Free space used by the descriptors themselves. */ Appendix 4 Source code for interactive module 301 sqlclu (binddp); EXEC SQL COMMIT WORK; /* disconnect from Oracle database engine */ EXEC SQL COMMIT RELEASE; return; /* ORACLE error handler */ sqlerror: printf("\n\n%. 70s\n", sqlca. sqlerrm. sqlerrmc); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK; EXEC SQL COMMIT RELEASE; } 13. misc.c /* miscellaneous functions used for updating database */ #include #include /* save new data into the database */ extern void save() { /* find the morphological information from icon palette. */ record_info_icon(); /* find the morphological information from text items associated with button */ recordinfotextO; /* build database update statement based on descriptors available. */ build_modify_statement(); Appendix 4 Source code for interactive module 302 modify_database(); /* Reset */ reset_panel(); } /* scan the icon panel, copy new data */ static void record_info_icon() { register int i; for (i=0; iutton image (frame_local,"Reverse Image", 13,font), 0); panelcreate item(frameJocal,PANELJBUTTON, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW+ 13 *COMMAND_INCREMENT), PANEL_ITEM_X, ATTRCOL(O), PANELNOTIFYPROC, save, PANELLABEL IMAGE, paneljiutton image (framejocal, "Save", 13,font), 0); panel_create_item(frame_local,PANEL_BUTTON, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW+ 14*COMMAND_INCREMENT), PANELITEMX, ATTRCOL(O), PANELNOTIFYPROC, help, PANEL_LABEL_IMAGE,panel_button_image (framejocal, "Help",4,font), 0); button_Quit = panel_create_item(frame_local,PANEL_BUTTON, PANEL_ITEM_Y, ATTR_ROW(COMMAND_START_ROW+ 14*COMMAND_INCREMENT), PANEL_ITEM_X, ATTR_COL(12), PANEL_NOTIFY_PROC, quit, PANEL_LABEL_IMAGE,panel_button_image(frameJocal,"Quit",4,font), 0); } extern void init_info_panel(frame_local) Frame framejocal; { Panel info_panel; /* font for displaying title */ font=pf_open("/apps/sundesk/fonts/sunpaint/R.24"); /* create info window to display the introduction text */ info_panel=window_create(frameJocal, PANEL, Appendix 4 Source code for interactive module 309 PANEL_LABEL_BOLD, FALSE, WIN_X, 0, WIN_Y, 0, WINWIDTH, screen_rect.width-command_rect. width, WTN_HEIGHT, info_rect. height, 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELJTEMX, X_START-30, PANEL_ITEM_Y, YSTART-30, PANEL_LABEL_STRING, " Interactive Ammonite Image Measurement Module", o); /* font for displaying introductory text */ font=pf_open("/apps/sundesk/fonts/sunview/lucida-19. v"); panel_create_item(infoj3anel,PANEL_MESSAGE, PANELLABELFONT, font, PANEL_ITEM_X, X_START+40, PANEL_ITEM_Y, Y_START, PANELLABELSTRJNG, "First, retrieve the ammonites that you want to measure by:", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_X, X_START, PANEL_ITEM_Y, Y_START+Y_INCREMENT, PANEL_LABEL_STRTNG, "1. Taxonomy: Family, Genus, and Species.", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_X, XSTART, PANEL_ITEM_Y, Y_START+2*Y_INCREMENT, PANEL_LABEL_STRING, "2. Stratigraphy: Stage and Standard Zone.", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_X, X_START, P ANELITEMY, YSTART+3 * YJNCREMENT, PANELLABELSTRING, "3. Geography: Geographic Area and Country", Appendix 4 Source code for interactive module 310 0); panel_create_item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANELJTEMX, XSTART, PANEL_ITEM_Y, Y_START+4*Y_INCREMENT, PANELLABELSTRING, "4. Morphology: Volution, Expansion Rate, Whorl Shape, and Rib Form", 0); panelcreate item(info_panel,PANEL_MESSAGE, PANEL_LABEL_FONT, font, PANEL_ITEM_X, X_START, PANEL_ITEM_Y, Y_START+5*Y_INCREMENT, PANEL_LABEL_STRING, "5. Reference: in which the figure of the specimen appears.", 0); panel_create_item(info_panel,PANEL_MESSAGE, PANELJ.ABELJONT, font, PANELJTEMX, X_START+40, PANEL_ITEM_Y, Y_START+6*Y INCREMENT, PANEL_LABEL_STPJNG, "Second, select the image and do the measurement. ", o); } extern void adjust info_panel(local_panel) Panel local_panel { int i; char tmp[40], *buf; Panel item item; /* destroy all old panel items in the info panel */ panel_each item(local_panel, item) panel_destroy item(item); panel_end_each inforect. height = textrect. height; /* increase height to accomondate icon panel */ inforect. width = screen_rect.width-command_rect.width-text_rect. width; window_set(local_panel, WIN_HEIGHT, info_rect.height, Appendix 4 Source code for interactive module 311 WINJWIDTH, info_rect.width, 0); /* display the query statement of the menu selection */ if (num_of_Items) { /* translate from SQL query to plain text, eliminate':' */ /* skip 'select * from OPSSliang.ammonimage where' in query statement */ buf=&query_statement[42]; query_to_plain(buf); i=strlen(buf); buf[i-2]=0; tmp[0]=0; sprintf(tmp,"%s%s",buf,search_condition[0]); } else tmp[0]=0; /* condition_text is the text field for query text display or input, you can type in a query and press the Combination button to search the database */ conditiontext = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 180, PANEL_VALUE_DISPLAY_LENGTH, 200, PANEL_LABEL_X, ATTRCOL(O), PANEL_LABEL_Y, ATTR_ROW(0), PANEL_LABEL_STRING, "Search :", PANEL_VALUE, tmp, 0); /* display number of images retrieved */ if (num_of_Items) sprintf(tmp,"%4d",num_of_Items); shownum = panel_create_item(local_panel, PANEL_TEXT, PANEL_VALUE_DISPLAY_LENGTH, 5, PANEL_LABEL_X, ATTR_COL(0), PANEL_LABEL_Y, ATTRROW(l), PANEL_LABEL_STRING, "Images Returned:", PANEL_VALUE, tmp, 0); Appendix 4 Source code for interactive module 312 /* number of images wait to be displayed */ wait_num = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 5, PANEL_LABEL_X, ATTR_COL(22), PANEL_LABEL_Y, ATTR_ROW(l), PANEL_LABEL_STRTNG, "Remained:", 0); /* when simulate the inner coiling curve, the user need to specify the number of whorls which seperate the two control points (PI & P2) */ num_of_whorls = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 2, PANEL_LABEL_X, ATTR_COL(pos[0].x), PANEL_LABEL_Y, ATTR_ROW(pos[0].y), PANEL_LABEL_STRING, "Whorls", 0); /* text field for displaying some parameter info */ parameterjnfo = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 25, PANELLABELX, ATTR_COL(pos[l].x), PANEL_LABEL_Y, ATTR_ROW(pos[l].y), o); /* create buttons and text fields for image measurement and result display */ panel_create_item(local_panel, PANEL_BUTTON, PANELLABELX, ATTR_COL(pos[2].x), PANELLABELY, ATTR_ROW(pos[2].y), PANELLABELIMAGE, panelbuttonimage (local_panel,"W (out) =",0, NULL), PANEL_NOTIFY_PROC, simulate_coiling, 0); text_item[0] = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[3].x), PANELLABELY, ATTR_ROW(pos[3].y), 0); Appendix 4 Source code for interactive module 313 panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[4].x), PANEL_LABEL_Y, ATTR_ROW(pos[4].y), PANELLABELJMAGE, panel_button_image (local_panel,"W (in) =",0, NULL), PANEL_NOTIFY_PROC, simulate_coiling, 0); text_item[ 1 ]=panel_create_item(local_panel, P ANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[5].x), PANEL_LABEL_Y, ATTR_ROW(pos[5].y), 0); panel_create_item(localj)anel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[6].x), PANEL_LABEL_Y, ATTR_ROW(pos[6].y), PANEL_LABEL_IMAGE, panel_button_image(local_panel,"U-',(), NULL), PANEL_NOTIFY_PROC, simulate_coiling, o); text_item[2] = panel_create_item(local_panel, PANEL_TEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[7].x), PANEL_LABEL_Y, ATTR_ROW(pos[7].y), 0); panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[8].x), PANEL_LABEL_Y, ATTR_ROW(pos[8].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"MaxWH=",0, NULL), PANEL_NOTIFY_PROC, maxwh, 0); text_item[3] = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 5, PANEL_LABEL_X, ATTR_COL(pos[9].x), PANEL_LABEL_Y, ATTR_ROW(pos[9].y), 0); panel_create_item(local_panel, PANEL_BUTTON, PANELLABELX, ATTR_COL(pos[10].x), PANEL_LABEL_Y, ATTR_ROW(pos[10].y), PANEL_LABEL_IMAGE; panelbuttonimage (local_panel,"PRHW=",0, NULL), Appendix 4 Source code for interactive module 314 PANEL NOTIFYPROC, rib_density, 0); text_item[4] = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[ll].x), PANEL_LABEL_Y, ATTR_ROW(pos[ll].y), o); panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[12].x), PANEL_LABEL_Y, ATTR_ROW(pos[12].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"SRHW=",0, NULL), PANELNOTIFYPROC, srhw, 0); text_item[5] = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[13].x), PANEL_LABEL_Y, ATTR_ROW(pos[13].y), 0); panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[14].x), PANELLABELY, ATTR_ROW(pos[14].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"THW=",0, NULL), PANELNOTIFYPROC, t_hw, o); text_item[6] = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[ 15] x), PANEL_LABEL_Y, ATTR_ROW(pos[15].y), o); panel_create_item(local_panel, PANELBUTTON, PANELLABELX, ATTR_COL(pos[16].x), PANEL_LABEL_Y, ATTR_ROW(pos[16].y), PANELLABELIMAGE, panel_button_image (local_panel,"Rib Width=",0, NULL), PANEL_NOTIFY_PROC, ribwidth, o); text_item[7] = panel_create_item(local_panel, PANELTEXT, Appendix 4 Source code for interactive module 315 PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[17].x), PANEL_LABEL_Y, ATTR_ROW(pos[17].y), 0); panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[18].x), PANEL_LABEL_Y, ATTR_ROW(pos[18].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"WWAVH",0, NULL), PANEL_NOTIFY_PROC, bi_space, 0); text_item[8] = panel_create_item(local_panel, PANEL_TEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[19].x), PANEL_LABEL_Y, ATTR_ROW(pos[19].y), o); panel_create_item(local_panel, PANELBUTTON, PANEL_LABEL_X, ATTR_COL(pos[20].x), PANEL_LABEL_Y, ATTR_ROW(pos[20].y), PANEL_LABEL_IMAGE, panelbuttonimage (local__panel,"Furcpos=",0, NULL), PANEL_NOTIFY_PROC, furc_pos, 0); text_item[9] = panel_create_item(local_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[21].x), PANEL_LABEL_Y, ATTR_ROW(pos[21].y), o); panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[22].x), PANEL_LABEL_Y, ATTR_ROW(pos[22].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"Unitubpos=",0, NULL), PANEL_NOTIFY_PROC, unitub_pos, 0); text_item[10] = panel_create_item(locaI_panel, PANELTEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[23].x), PANEL_LABEL_Y, ATTR_ROW(pos[23].y), 0); Appendix 4 Source code for interactive module 316 panel_create_item(local_panel, PANELBUTTON, PANEL_LABEL_X, ATTR_COL(pos[24].x), PANEL_LABEL_Y, ATTR_ROW(pos[24].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"WWD=",0, NULL), PANEL_NOTIFY_PROC, finess_ratio, 0); textitemfll] = panel_create_item(local_panel, PANEL_TEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[25].x), PANEL_LABEL_Y, ATTR_ROW(pos[25].y), 0); panel_create_item(local_panel, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(pos[26].x), PANEL_LABEL_Y, ATTR_ROW(pos[26].y), PANEL_LABEL_IMAGE, panel_button_image (local_panel,"CHW=",0, NULL), PANEL_NOTIFY_PROC, c_hw, 0); text_item[12] = panel_create_item(local_panel, PANEL_TEXT, PANEL_VALUE_DISPLAY_LENGTH, 4, PANEL_LABEL_X, ATTR_COL(pos[27].x), PANELLABELY, ATTR_ROW(pos[27].y), 0); create_icon_panel(); panel_paint(local_panel, PANELCLEAR); } static void create_icon_panel(local_panel) Panel local_panel { /* create an icon panel to facilitate the input of morph data */ inputIcon_panel = panel_create_item(local_panel, PANELTOGGLE, PANELCHOICEIMAGES, «&rib_biconcave, «&rib_concave, &rib_sinuous, &rib_falcate, «&rib_projected, «&rib_straight, &rib_bundled, Appendix 4 Source code for interactive module 317 &rib_faIcoid, &rib_zigzag, &rib_intercalatory, &furc_bi, &furc_tri, &furc_multi, &furc_poly,&furc_loop2, &furc_loop3, &furc_loopn,&profangular, &prof_round, &prof_strong, &prof_weak,&prorsiradiate, &gprorsiradiate, &rectiradiate, &grursiradiate, &rursiradiate, &tuberc_uni, &tuberc_bi, &tuberc_tri, &tuberc_multi, &tuberc_clavate, &tuberc_bullate, &uwallht_high, &uwallht_low, &shallow, &steep, &vertical, &undercut, &ontogeny, &whorl_rounded, &whorl_ellipsoid, &whorl_wellipsoid, &whorl_oval, &whorl_lanceolate, &whorl_ogival, &whorl_rectangular, &whorl_wrectangular, &whorl_quadrate, &whorl_triangular, &whorl_wtriangular, &whorl_trapezoid, &whorl_coronate, &venter_plain, &venter_carinate, &venter_sulcate, &carinate_sulcate, &bicarinate, &bicarinate_sulcate, &approx, 0, PANEL_CHOICE_XS, 76,140,204,268,332,396,460,524,588,652,76,140,204, 268,332,396,460,524,588,652,1,140,204,268,332,396,524,588,652,1, 65, 129, 268,332,396,460,524,588,652,76,140,204,268,332,396,460, 524, 588,652,1, 65,129,268,332,396,460,524,588,652,0, PANEL_CHOICE_YS, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 152,152,152, 152,152,152,152,152,152,152,216,216, 216, 216, 216, 216,216, 216, 216, 280, 280, 280, 280, 280, 280,280, 280, 280,280, 344, 3445 344, 344, 344, 344, 344, 344, 344, 344, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 0, 0); /* label the icon panel */ panel_create_item(local_panel, PANEL_MESSAGE, PANEL_LABEL_X, label_pos[0].x, PANEL_LABEL_Y, label_pos[0].y, PANEL_LABEL_STRING, "RIB FORM", 0); panel_create_item(local_panel, PANEL_MESSAGE, PANEL_LABEL_X, label_pos[l].x, PANEL_LABEL_Y, label_pos[l].y, PANEL_LABEL_STRING, "RIB FURC", 0); panel_create_item(local_panel, PANEL_MESSAGE, PANEL_LABEL_X, label_pos[2].x, PANEL_LABEL_Y, label_pos[2].y, PANELLABELSTRING, "RIB TREND", 0); panel_create_item(local_panel, PANELMESSAGE, Appendix 4 Source code for interactive module 318 PANEL_LABEL_X, label_pos[3].x, PANELLABEL_Y, label_pos[3].y, PANELLABELSTRTNG, "TUBERCLE", o); panel_create_item(local_panel, PANEL_MESSAGE, PANEL_LABEL_X, label_pos[4].x, PANEL_LABEL_Y, label_pos[4].y, PANELLABELSTRTNG, "UWALL", 0); panel_create_item(local_panel, PANEL_MESSAGE, PANEL_LABEL_X, label_pos[5].x, PANEL_LABEL_Y, label_pos[5].y, PANEL_LABEL_STPJNG, "WHORL", o); panel_create_item(local_panel, PANEL_MES SAGE, PANELLABELX, label_pos[6].x, PANEL_LABEL_Y, label_pos[6].y, PANELLABELSTRTNG, "VENTER", 0); } extern void adjust_display_window(local_panel) Panel local_panel; { start_status=l;/* now the system has gone through at least one query */ adjust_info_panel(); /* adjust image_canvas size due to the creation of a new text window */ window_set(image_canvas, WINWIDTH, screen_rect.width-command_rect.width-8, WIN_HEIGHT, screen_rect.height-info_rect.height, WTN_Y, info_rect.height, 0); text_win=window_create(display_window, TEXTSW, WIN_X, screenrect. width-text_rect. width, WTN_Y, 0, WIN WIDTH, text rect.width. Appendix 4 Source code for interactive module 319 WTNHEIGHT, text_rect. height, 0); panel_set(local_panel, PANELCARETITEM, num_of_whorls, 0); } extern void canvas_handler(event) Event * event; { register int i, j ; if (event_is_up(event)) return; switch (eventaction(event)) { case MS_LEFT: /* locate the image and display related info */ i=image_index(event_x(event),event_y(event)); if(i>=0) show_descriptors(i); break; case MS_MIDDLE: /* mark the point with color 252 and determine the image scale */ pw_put(pw,event_x(event),event_y(event),252); control_point[num_control_point].x:=event_x(event); control jointfnumcontroljointj.y^event^event); if (! num_control_point) { image_scale=atof(descriptor_value[SCALE][rel[image_index (event_x(event), event_y(event))]]); if(!image_scale) image_scale=1.0; } num_control_point++; case MS_RIGHT: /* mark two points for ploting brightness profile */ if (between[l].x || between[l].y) { i^betweenflj.x; j=between[l].y; between[ 1 ] .x=event_x(event); between[ 1 ] .y=event_y(event); between[0].x=i; between[0].y=j; } else if (between[0].x || between[0].y) { between[ 1 ] .x=event_x(event); betweenflj.y^event^event); } else { between[0] .x=event_x(event); between[0].y=event_y(event);} Appendix 4 Source code for interactive module 320 break; default: break; } } extern void clear_canvas() { (void)pw_writebackground(pw,0,0,(int)(LINT_CAST(window_get(image_canvas, CANVAS_WIDTH))), (int)(LINT_CAST(window_get(image_canvas, CANVAS_HEIGHT))), PIXJXR); } Appendix 5 Source code for automated module 321 Appendix 5 Source code for automated image measurement module There are 9 files in this program: auto.h, main.c, canny.c, thin.c, trace.h, trace.c, utility.c, smooth_form.c, ribbed_form.c. 1. auto.h /* * Header file for automated image measurement module. * * Author: Bo Liang * Department of Geological Sciences * The University of British Columbia * Date: May 1991 * Modifications: April 1994 */ #include #include #include #define MAXNUM 6000 /* maxium number of segments in the image */ #define MAXWDTH 2048 #defme MINLEN 10 /* minimum number of points in segment */ #definePi 3.1416 #define RIBANG Pi/12 /* radial */ #define COILANG 2*Pi/5 /* spiral */ /* label for line segments */ #define RIB 1 #define COILING 2 #define UNKNOWN 3 #define N 0 #define NE 1 #define E 2 #define SE 3 #define S 4 #define SW 5 #define W 6 #define NW 7 #define O 8 #define MAX(x, y) ( x > y ) ? x : y #define MIN(x, y) (x < y) ? x: y Appendix 5 Source code for automated module 322 #define SQR(i) i*i #define D(xO,yO,xl,yl) sqrt(SQR(xl-xO)+SQR(yl-yO)) #define CLOSE(xO,yO,xl,yl) (abs(x0-xl)<2 && abs(y0-yl)<2) /* angle conversion macro */ #define POSITIVE(alpha) (alpha < 0) ? 2*Pi+alpha:alpha #define LESSPI(alpha) (alpha > Pi) ? 2*Pi-alpha:alpha #define TWOPI(alpha) (alpha > 2*Pi) ? alpha-2*Pi:alpha #define HALFPI(alpha) (alpha > Pi/2) ? Pi-alpha:alpha #define LARGER(alpha, belta) (alpha > belta) ? alpha-belta : 2*Pi+alpha-belta #define TRUEDIF(alpha, belta) (belta>0) ? alpha-belta : alpha+belta #define ANGLE(xO, yO, xl, yl) (xO = xl) ? Pi/2 : atan((yl-yO)/(xl-xO)) int imageSize; int num_of_seg; /* number of line segments in the image */ int *seq; short int neighbor[2][MAXNUM]; float yo, xo; /* coordinates of the coiling axis */ float threshold; float *theta; float ox[MAXNUM], oyfMAXNUM], r[MAXNUM]; float rep[MAXNUM], label[MAXNUM]; int *num_of_point; /* number of points in the line segment */ struct points { short int x; short int y; short int z; } *segment[MAXNUM] struct point *newseg[MAXNUM], *buf; Pixrect *new_image; 2. main.c #include #include "auto.h" main(argc, argv) int argc; char *argv[]; { FILE *fpi, *fpo; Appendix 5 Source code for automated module 323 char *image_in, *image_out; Pixrect *orig_image, *screen[2]; colormap_t *colormap; register argn; int nrows, ncols,; if (argn = getarg("i", argc, argv)) image_in = argv[++argn]; if (argn = getarg("o", argc, argv)) image_out = argv[++argn]; /* load original ammon image */ fpi = fopen(image_in, "r"); orig_image = pr_load(fpi, colormap); if (origimage = NULL) { fprintf(stderr, "Can't open %s as image file\n", image_in); exit(l); } ncols = orig_image->pr_size.x; nrows = orig_image->pr_size.y; imageSize = MAX(nrows, ncols); if ((fpo = fopen(image_out, "w")) = NULL); fprintf(stderr, "Can't open %s as output fileVn", imageout); exit(l); /* create a memory pixrect to host the processed image of origimage */ new_image = mem_create(ncols, nrows, 1); if (new_image = NULL) { fprintf(stderr, "2: can't open new_image as image fileVn"); exit(l); } /* prepare screen for display */ screen[0] = pr_open("/dev/fb"); screenfl] = pr_open("/dev/fb"); /* remove some of the background noise */ remove_noise(orig_image); /* use Canny operator to detect edges */ Appendix 5 Source code for automated module 324 edge_detector(orig_image, newimage); /* skeletonize edges potentially wider than one pixel */ edge_thinning(new_image); /* group edge points into line segment */ trace_segment(ncols, nrows); /* after all the changes on orig_image, restore it to original state */ pr_close(orig_image); orig_image = pr_load(fpi, colormap); /* connect short line segments based on distance and colinearity */ connect(); /* order segments according to number of points in segment */ order_segment(); /* * remove redundant segments based on complete overlap along x & y as * well as closeness of end-points */ remove_redundant_segs(); /* * use the underlying pattern of ribs and coiling curves to locate * coiling axis */ locate_coiling_axis(ncols, nrows); /* * assign segments to one of the following classes : Rib, coiling * curve and Unknown V if (label_seg() = RIB) /* ribbed form */ process_ribbed_form(); Appendix 5 Source code for automated module 325 else /* smooth form */ process_smooth formO; exit(O); 3. canny.c provided by the Department of Computer Science, UBC. 4. thin.c provided by the Department of Computer Science, UBC. 5. trace, h static int xx, yy; struct point { int x; int y; }; /* orientation data array in terms of {delta x, delta y} for trace_from */ struct point main_O[]={{0,l},{l,0},{l)l},{l,-l}}; struct point main_SE[]={{l,l},{l,0},{l,l}}; struct point main_S[]={{l,0},{l,-l},{l,l}}; struct point main_SW[]={{l,-l},{l,0},{0,-l}}; struct point main_W[]={{0,-l},{l,-l},{-l,-l}}; struct point main_NW[]={{-l,-l},{0,-l},(-l,0}}; struct point main_N[]={{-l,0},{-l,l},{-l,-l}}; struct point main_NE[]={{-l,l},{0,l},{-l,0}}; struct point main_E[]={{0,l},{l,l},{-l,l}}; /* orientation data array for further */ struct point further_SE[]={{2,2},{l,2},{2,l},{0,2},{2,0},{3,3},{2,3},{3,2},{l,3},{3,l}, {0,3},{3,0}}; struct point further_S[]={{2,0},{2,l},{2,-l},{2,2},{2,-2},{l,2},{l,-2},{3,0},{3,l}, {3,-l},{3,2},{3,-2}}; struct point further_SW[]={{2,-2},{2,-l},{l,-2},{2,0},{0,-2},{3,-3},{3,-2},{2,-3},{3,-l}, {l,-3},{3,0},{0,-3}}; struct point further_N[]={{-2,0},{-2,l},{-2,-l},{-2,2},{-2,-2},{-l,2},{-l,-2},{0,2},{0,-2}, {-3,0},{-3,l},{-3,-l}}; Appendix 5 Source code for automated module 326 struct point further_NE[]={{-2,2},{-l,2},{-2,l},{0,2},{-2,0},{-3,3},{-3,2},{-2,3},{-3,l}, {-l,3},{0,3},{-3,0}}; struct point further_NW[]={{-2,-2},{-2,-l},{-l,-2},{-2,0},{0,-2},{-3,-3},{-2,-3},{-3,-2}, {-l,-3},{-3,-l},{0,-3},{-3,0}}; struct point fiirther_Ea={{0,2},{l,2},{-l,2},{2,2},{-2,2},{2,l},{2,0},{0>3},{l,3},{-l,3}, {2,3},{-2,3}}; struct point further_W[]={{0,-2},{l,-2},'{-l!-2},{2,-2},{-2,-2},{2,-l},{-2,-l},{2,0},{0,-3}, {-l,-3},{l,-3},{2,-3}}; static void trace_from(int*, int*, int); static void fiirther(int*, int*, int); static int any_direction(int*, int*); static void update_seg(int*, int*, int, int, int); static void round_up(int*, int*); static int convert(double); 6. traccc * This Program is used to trace line segments from output image of Canny * Operator. */ #include "auto.h" #include "trace, h" void trace_segment(h, w) int h, w; { int i, j , k, orientation; segment[0] = (struct point *) malloc(imageSize * sizeof(points)); buf = segment[0]; for( i= l ; ix = i; segment[0]->y =j ; segment[0]->z = k; ++segment[0]; pr_put(new_image, i, j , 0); orientation = O; num_of_point[num_of_seg] = 0; trace_from(&i, &j, orientation); Appendix 5 Source code for automated module 327 } } } /* start tracing from point (i, j) along orientation */ static void trace_from(i, j , orientation) int *i, *j , orientation; { register int k, m, n; xx = yy = 0.0; switch (orientation) { case O: n = sizeof main_0 / sizeof main_O[0]; for (m = 0; m < n; m++) if ((k = prj>et(new_image, *i + mainO.x, *j + main_0.y)) > 0) { update_seg(i, j , k, mainO.x, main_0.y); further(i, j , orientation); round_up(i,j); break; } break; case SE: n = sizeof main_SE / sizeof main_SE[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + main_SE.x, *j + main_SE.y)) > 0) { update_seg(i, j , k, mainSE.x, mainSE.y); break; } break; case S: n = sizeof main_S / sizeof main_S[0]; for (m = 0; m < n; m++) if ((k = pr^get(new_image, *i + mainS.x, *j + mainS.y)) > 0) { update_seg(i, j , k, mainS.x, main_S.y); break; } break; case SW: n = sizeof mainSW / sizeof main_SW[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + mainSW.x, *j + mainSW.y)) > 0) { update_seg(i, j , k, main_SW.x, mainSW.y); Appendix 5 Source code for automated module 328 break; } break; case W: n = sizeof main_W / sizeof main_W[0]; for (m = 0; m < n; m++) if ((k = prj5et(new_image, *i + mainW.x, *j + main_W.y)) > 0) { update_seg(i, j , k, main_W.x, mainW.y); break; } break; case NW: n = sizeof main_NW / sizeof main_NW[0]; for (m = 0; m < n; m++) if ((k = prjjetfaewjmage, *i + main_NW.x, *j + main_NW.y)) > 0) { update_seg(i, j , k, main_NW.x, main_NW.y); break; } break; case N: n = sizeof main_N / sizeof main_N[0]; for (m = 0; m < n; m++) if ((k = pr_get(newjm&ge, *i + main_N.x, *j + main_N.y)) > 0) { update_seg(i, j , k, main_N.x, main_N.y); break; } break; case NE: n = sizeof mainNE / sizeof main_NE[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + main_NE.x, *j + main_NE.y)) > 0) { update_seg(i, j , k, main_NE.x, main_NE.y); break; } break; case E: n = sizeof mainE / sizeof main_E[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + main_E.x, *j + main_E.y)) > 0) { update_seg(i, j , k, main_E.x, main_E.y); break; } } /* for switch */ } /* for the function */ Appendix 5 Source code for automated module 329 /* find point 2-5 pixels away along the prefered direction */ static void further(i, j , orientation) int *i, * j , orientation; { register int k, m, n; /* fine tuned for each direction, don't try to generalize it */ switch (orientation) { case SE: n = sizeof furtherSE / sizeof further_SE[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + further_SE[m].x, *j + further_SE[m].y)) > 0) { update_seg(i, j , k, further_SE[m].x, further_SE[m].y); break; } break; case S: n = sizeof further_S / sizeof further_S[0]; for (m = 0; m < n; m++) if((k = prjjetOiewjmage, *i + further_S[m].x, *j + further_S[m].y)) > 0) { update_seg(i, j , k, further_S[m].x, further_S[m].y); break; } break; case SW: n = sizeof further_SW / sizeof further_SW[0]; for (m = 0; m < n; m++) if((k = prj»et(new_image, *i + further_SW[m].x, *j + further_SW[m].y)) > 0) { update_seg(i, j , k, further_SW[m].x, further_SW[m].y); break; } break; case N: n = sizeof furtherN / sizeof further_N[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + further_N[m].x, *j + further_N[m].y)) > 0){ update_seg(i, j , k, further_N[m].x, further_N[m].y); break; } Appendix 5 Source code for automated module 330 break; case NE: n = sizeof further_NE / sizeof further_NE[0]; for (m = 0; m < n; m++) if ((k = pr_j>et(new_image, *i + further_NE[m].x, *j + further_NE[m].y)) > 0) { update_seg(i, j , k, further_NE[m].x, further_NE[m].y); break; } break; case NW: n = sizeof further_NW / sizeof further_NW[0]; for (m = 0; m < n; m++) if((k = prj*et(new_image, *i + further_NW[m].x, *j + further_NW[m].y)) > 0) { update_seg(i, j , k, further_NW[m].x, further_NW[m].y); break; } break; case E: n = sizeof further_E / sizeof further_E[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + further_E[m].x, *j + fiirther_E[m].y)) > update_seg(i, j , k, further_E[m].x, further_E[m].y); break; } break; case W: n = sizeof furtherW / sizeof further_W[0]; for (m = 0; m < n; m++) if ((k = pr_get(new_image, *i + further_W[m].x, *j + further_W[m].y)) > 0) { update_seg(i, j , k, further_W[m].x, further_W[m].y); break; } } /* for the switch */ /* for the function */ * * trace along all directions if the number of points in the current segment * is small */ / Appendix 5 Source code for automated module 331 int any_direction(i, j) int *i, *j ; { int k, ii, jj; for(ii = - l ; i i<=l ; i i++) for(iJ = -l;jj<=l;jj-H-) if ((k = pr_get(new_image, *i + ii, *j + jj))) { update_seg(i, j , k, ii, jj); return 1; } /* succeed in finding a bridge */ return 0: /* search along direction (ii, jj) */ static void update_seg(i, j , k, ii, jj) int *i, *j, k, ii, jj { double sigma; *i = *i + ii; *j = *j +jj; segment[0]->x = *i; segment [0]->y = *j; segment[0]->z = k; ++segment[0]; pr_put(new_image, *i, *j, 0); xx += ii; yy+=ij; sigma = atan2(yy, xx); orientation - convert(sigma); ++num_of_point[num_of_seg]; linetrace(i, j , orientation); return; } /* explore all directions and store selected path in a new segment */ static void round_up(i, j) Appendix 5 Source code for automated module 332 int *i, * j ; register int k; k = l ; while (k && num_ofj>oint[num_of_seg] < 5) /* less than 5 pixels * away */ k = any_direction(i, j); segment[num_of_seg] = (struct point *) malloc(num_of_point[num_of_seg] * sizeof(points)); for (k = 0; k <= num_of_point[num_of_seg]; k++) { *segment[num_of_seg] = *(segment[0] - num_of_point[num_of_seg] - 1 + k); ++segment[num_of_seg]; } theta[num_of_seg] = atan(yy / xx); num_of_seg++; segment[0] = buf; /* convert angle to orientation */ int convert(sigma) double sigma; { register int orientation; switch (nint((4 * sigma) / Pi)) { case 0: orientation = S; break; case 1: orientation = SE; break; case 2: orientation = E; break; case 3: orientation = NE; break; case 4: case -4: orientation = N; break; Appendix 5 Source code for automated module 333 case -1: orientation = SW; break, case -2: orientation = W; break; case -3: orientation = NW; break; } return orientation; 7. utility.c /* * remove background noise based on the average and standard deviation of the * backgroud brightness intensity which are estimated from a three-pixel wide * margin of the image */ extern void removenoise(origimage) Pixrect *orig_image; { register int i, j , num; double sum, sum_sqr, mean, std; sum = sum_sqr = 0.0; for (i = 0; i < ncols; i++) { forG = 0 ; j<3; j++){ sum += pr^get(orig_image, i, j); sum_sqr += sqr(pr_get(orig_image, i, j)); num++; } for (j = nrows - 3; j < nrows; j++) { sum += pr_get(orig_image, i, j); sum_sqr += sqr(pr_get(orig_image, i, j)); num++; } } for (j = 0; j < nrows; j++) { for(i = 0 ; i < 3 ; i++) { sum += pr_get(origjmage, i, j); Appendix 5 Source code for automated module 334 } sum_sqr += sqr(prj*et(orig_image, i, j)); num-H-; } for (i = ncols - 3; i < ncols; i++) { sum += prj>et(orig_image, i, j); sum_sqr += sqr(pr_get(orig_image, i, j)); num++; } mean = sum / num; std = sumsqr - num * SQR(mean); std = sqrt(std / (num - 1.0)); /* if mean<128 (black background) and z < mean+std then z =0 */ if (mean < 128) { for (i = 0; i < ncols; i++) for (j = 0; j < nrows; j++) if (pr_get(orig_image, i, j) < mean + std) pr_set(orig_image, i, j , 0); } else { for (i = 0; i < ncols; i++) for (j = 0; j < nrows; j++) if (pr_jget(orig_image, i, j) > mean - std) pr_set(orig_image, i, j , 0); } /* compute portion of overlap between segment zO-zl and z2-z3 */ float overlap(z0, zl, z2, z3) float zO, zl , z2, z3; { int i j ; float ovlp, lap[2]; i f ( z0>z l ){ lap[0] = zl ; zl = zO; zO = lap[0]; } i f (z2>z3){ lap[0] = z3; Appendix 5 Source code for automated module 335 z3 = z2; z2 = lap[0]; } if (z3 > zl) lap[0] = zl - z2; /* the length of the overlap */ else lap[0] = z3 - zO; lap[l] = (zl - zO < z3 - z2) ? zl - zO : z3 - z2; /* the length of the * shortest segment */ if (tmp < 0) ovlp = 0.0; else if (!lap[l]) ovlp =1.0; else ovlp = lap[0]/lap[l]; return ovlp; } /* * remove redundant segments based on complete overlap along x & y as well as * closeness of end-points */ static void removeredundantsegsO { register int i,j, k , j l , j2; float x[5], y[5]; for (i = 2; i < num_of_seg; i++) { x[l] = (newseg[seq[i]j - l)->x; yfl] = (newseg[seq[i]j - l)->y; x[2] = (newseg[seq[i]J - num_of_point[seq[i]] - l)->x; y[2] = (newseg[seq[i]] - num_of_point[seq[i]] - l)->y; for(j = i ; j< i ; j++){ x[3] = (newseg[seq(j]] - l)->x; y[3] = (newseg[seq[j]] - l)->y; x[4] = (newseg[seq(j]] - num_of_point[seq(j]] - l)->x; y[4] = (newseg[seq[j]] - num_of_point[seq[j]] - l)->y; if (overlap(x[l], x[2], x[3], x[4]) > 0.99 && overlap(y[l], y[2], y[3], y[4]) > 0.99) { j l = j 2 = 0; for (il = 0; il <= num_of_point[seq[j]]; il++) { Appendix 5 Source code for automated module 336 } } } return; } /* connect short segments based on distance and colinearity */ void connect() { register int i, j , k, x[5], y[5]; double tmp, sigma; /* allocate space for new segment array */ newseg[0] = (struct point *) malloc(imageSize * sizeof(points)); buf = newseg[0]; /* record where it starts */ k = 0; for (i = 1; i < num_of_seg; i++) if(num_of_point[i]) { k++; x[0] = (segment[i] - l)->x; y[0] = (segmentfij - l)->y; x[l] = (segment[i] - num_of_point[i] - l)->x; y[l] = (segment[i] - num_of_point[i] - l)->y; for (j = 0; j <= num_of_point[i]; j++) { *newseg[0] = *(segment[i] - num_of_point[i] - 1 + j); ++newseg[0]; } x[0] = (newseg[seqOJ] - il - l)->x; y[0] = (newseg[seq[j]] - il - l)->y; if(D(x[l],y[l],x[0],y[0])<3.0) j i = i; if(D(x[2],y[2],x[0],y[0])<3.0) j 2 = l ; if 01 &&J2) break; } if 01 &&J2) { num_of_point[seq[i]] = 0; break; } /* end of j loop */ /* end of i loop */ Appendix 5 Source code for automated module 337 -for (j = i + 1; j < num_of_seg; j++) if (num_of_point[j]) { tmp = fabs(theta[i] - theta[j]); sigma = HALFPI(tmp); x[2] = (segment[j] - l)->x; y[2] = (segmentrjj - l)->y; x[3] = (segment[j] - num_of_point[j] - l)->x; y[3] = (segment[j] - num_of_point[j] - l)->y; if(fabs(theta[i]) 2 && num_of_point[i] > 2 && sigma < Pi / 9.0 && tmp < 0.1 || num_of_point[i] < 3 || num_of_point[j] < 3) { /* * check the four end points * of the two segments, * determine how to connect * them */ if (CLOSE(x[0], y[0], x[2], y[2])) { join_segment(j, 1); /* 1 - start from front */ } else if (CLOSE(x[0], y[0], x[3], y[3])) { join_segment(j, -1); /* 1 - start from back */ x[0] = x[2]; y[0] = y[2]; } else if (CLOSE(x[l], y[l], x[2], y[2])) { reverse_segment(i); join_segment(j, 1); x[l]=x[0]; y[i] = y[0]; x[0]=x[3]; y[0] = y[3]; } else if (CLOSE(x[l], y[l], x[3], y[3])) { reverse_segment(i); join_segment(j, -1); Appendix 5 Source code for automated module 338 x[ l ]=x[0]; y[i] = y[0]; x[0] = x[2]; y[0] = y[2]; } theta[i] = ANGLE(x[0], y[0], x[l] , y[l]); j = »; } } newseg[k] = (struct point *) malloc(num_of_point[i] * sizeof(points)); for (j = 0; j <= num_of_point[i]; j++) { *newseg[k] = *(newseg[0] - num_of_point[i] - 1 + j); ++newseg[k]; } newseg[0] = buf; /* reset the memory location * for newseg[0] */ num_of_point[k] = num_of_point[i]; theta[k] = theta[i]; } num_of_seg = k + 1; } /* join segment j to newseg[0] from direction k */ static void join_segment(j, k) int j , k; { register int i; i f (k>0) for (i = 0; i <= num_of_point[j]; i++) { *newseg[0] = *(segment[j] - i - 1); ++newseg[0]; } else for (i = num_of_point[j]; i >= 0; i~) { *newseg[0] = *(segment[j] - i - 1); ++newseg[0]; } num_of_point[i] += num_of_point[j] + 1; num_of_point[j] = 0; } /* reverse the order of points in segment */ Appendix 5 Source code for automated module 339 static void reversesegment(i) int i; { register int j ; for (j = 0; j < (num_of_point[i] + 1) / 2; j++) { *(newseg[0] - j) = *(newseg[0] - num_of_point[i] - 1 + j); *(newseg[0] - num_of_point[i] - 1 + j) = *(newseg[0] - j - 1); } for (j = 0; j < (num_of_point[i] + 1) / 2; j++) *(newseg[0] - (num_of_point[i] + l ) / 2 + j ) = *(newseg[0] - (num_of_point[i] + 1) / 2 + 1 + j); } /* * order segments based on number of points in the segment, eliminate the one * with less than MINLEN points and save order information in seq[] */ static void order_segment() { register int i, j , k; for (i = 1; i < num_of_seg; i++) seq[i] = i; for (i = 1; i < numofseg ; i++) for (j = i + 1; j < num_of_seg; j++) if (num_of_point[seq[i]] < num_of_point[seq[j]]) { k = seq[i]; seq[i] = seqO]; seqjj] = k; } for (i = 1; i < num_of_seg; i++) if (num_of_point[seq[i]] < MINLEN) numofseg--; } /* * locate coiling axis according to support from rib and coiling curve * candidates */ Appendix 5 Source code for automated module 340 static void locate_coiling_axis(ncols, nrows) int ncols, nrows; { register int i, j , k, x[5], y[5]; double sigma[2], contrib[2]; contrib[l] = 0; for (i = x[0] - ncols / 4; i < x[0] + ncols / 4; i += 5) /* 5 - scanning * resolution */ for (j = y[0] - nrows / 4; j < y[0] + nrows / 4; j += 5) i f ( i > 0 & & j > 0 ) { contrib[0] = 0; for (k = 1; k < numofseg; k++) { x[l] = (newseg[seq[k]] - num_of_point[seq[k]] / 2)->x - i; y[l] = (newseg[seq[k]] - num_of_point[seq[k]] / 2)->y - j ; if (x[l]) { sigma[0] = atan((double) y[l] / x[l]); sigma[l] = fabs(theta[seq[k]] - sigma[0]); sigma[0] = HALFPI(sigma[l]); } else { /* middle point vector * is in vertical * position */ sigma[0] = POSITIVE(theta[seq[k]]); } if (sigma[0] < Pi /12.0) /* a rib candidate */ contrib[0] += num_of_point[seq[k]]; else if (num_of_point[seq[k]] < imageSize / 6) { if (sigma[0] > 0.4 * Pi) /* short coiling curve * segment */ contrib[0] += num_of_point[seq[k]]; } else { /* get a short segment * of the long coiling * curve candidate */ x[l] = (newseg[seq[k]] - num_of_point[seq[k]] / 2 + imageSize / 20)->x - (newseg[seq[k]] -num_of_point[seq[k]] / 2 - imageSize / 20)->x; y[l] = (newseg[seq[k]] - num_of_point[seq[k]] / 2 + imageSize / 20)->y - (newseg[seq[k]] -num_of_point[seq[k]] / 2 - imageSize / 20)->y; if (x[l]) { sigma[l] = fabs(Pi / 2 - atan((double) y[l] / x[l])); sigma[0] = HALFPI(sigma[l]); } else sigma[0] = 0; Appendix 5 Source code for automated module 341 if(sigma[0] >0.4 * Pi) contrib[0] += num_of_point[seq[k]]; } } if (contrib[0] > contrib[l]) { /* the location geting * the largest support * is coiling axis */ contrib[l] = contrib[0]; xo = i; yo=j; } } } int label_seg() { register int i, k, x[5], y[5]; double sigma; for (i = 1; i < numofseg ; i++) label[i] = 0; for (i = 1; i < num_of_seg; i++) { x[l] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->x - xo; y[l] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->y - yo; if (x[l]) { sigma = fabs(theta[seq[i]] - atan(y[l] / x[l])); sigma = HALFPI(sigma); } else sigma = TRUEDIF(Pi / 2, theta[seq[i]]); theta[seq[i]] = POSITIVE(atan2(y[l], x[l])); if(sigma COILANG) label[i] = COILING; else labelp] = UNKNOWN; } k = 0; for (i = 1; i < num_of_seg; i++) if(label[i]=RIB) k++; if (k > 0.3 * num_of_seg) return RIB; /* ribbed form */ else Appendix 5 Source code for automated module 342 return COILING; /* smooth shell */ } bright_between(iO, jO, xO, yO, rO, rl) int iO, jO, xO, yO; float rO, rl; { register int i, j , il = 0, j l , x[5], y[5], f[400][100], count[400]; float s[5], n[5]; for (i = 0; i < 5; i++) n[i] = 0.0; for (i = 0; i <= num_of_point[seq[iO]]; i++) { x[l] = (newseg[seq[iO]] - i - l)->x; y[l] = (newseg[seq[iO]] - i - l)->y; s[l] = D(xO,yO,x[l],y[l]); i f ( s [ l ]>=rO&&s[l ]<=r l ){ for (j = 0; j <= num_of_point[seq[jO]]; j++) { x[2] = (newseg[seq[jO]] - j - l)->x; y[2] = (newseg[seq[j0]] - j - l)->y; s[2] = D(xO,yO,x[2],y[2]); if(fabs(s[2]-s[l])<1.0) break; } s[3] = atan2((double) y[l] - yO, (double) x[l] - xO); s[4] - atan2((double) y[2] - yO, (double) x[2] - xO); if(fabs(s[3]-s[4])s[4]){ s[0] = s[3]; s[3] = s[4]; s[4] = s[0]; } } else { if(s[3]<0.0){ s[0] = s[4]; s[4] = 2 * Pi + s[3]; s[3] = s[4]; } else if(s[4]< 0.0) s[4] += 2 * Pi; } il++; for (s[0] = s[3]; s[0] <= s[4]; s[0] 4= 0.5 / s[l]) { x[3]=x0 + s[l]*cos(s[0]); y[3] = y0 + s[l]*sin(s[0]); Appendix 5 Source code for automated module 343 if (!(x[3] = x[4] && y[3] = y[4])) { x[4] = x[3]; y[4] = y[3]; f[il]Dl++] = prjget(x[3],y[3]); } } count[il] = j l ; } } for(i= l ; i<=i l ; i++) { n[0] = count[i] / 2; nil] += f[i][(int) n[0]]; n[2] += SQR(f[i][(int) n[0]]); } if (il) { n[3] = n [ l ] / i l ; s[0] = n[2] + il * SQR(n[3]) - 2 * n[3] * n[l]; n[4] = 2 * sqrt(s[0] / il); n[l] = n[2] = n[0] = 0.0; for(i= l ; i<=i l ; i++){ j l = 0 ; for 0 = 1; j <= countfi] / 2; j++) if (jl II m\j] < Ont) n[3] + n[4] && f[i][j] > (int) n[3] - n[4]) { ji = i; n[l] += f[i]D]; n[2] += SQR(f[i]D]); n[0]+=1.0; } } for(i= l ; i<=i l ; i++) { j l = 0 ; for (j = count[i] - 1; j > count[i] / 2; j--) if (jl II f[i][)] < Ont) n[3] + n[4] && f[i]D] > (int) n[3] - n[4]) { ji = i; n[i]+=f[i]D]; n[2] += SQR(f[i][j]); n[0]+=1.0; } } if(n[0]>4.0) n[3]=n[l]/n[0]; else return -2; s[0] = n[2] + n[0] * SQR(n[3]) - 2 * n[3] * n[l]; s[0] = sqrt(s[0]/n[0]); if(s[0]< threshold) Appendix 5 Source code for automated module 344 return (int) n[3]; else return-1; } else return -2; } bright_nearby(iO, jO, xO, yO, rO, i2) int iO, jO, i2, xO, yO; float rO; { register int i, j , il = 0, j l , x[5], y[5], f[400][100], count[400]; float s[5], n[5]; for (i = 0; i < 5; i++) n[i] = 0.0; s[2] = 0.0; for (i = 0; i <= num_of_point[seq[iO]]; i++) { x[l] = (newseg[seq[iO]] - i - l)->x; y[l] = (newseg[seq[iO]j - i - l)->y; s[l] = D(xO,yO,x[l],y[l]); if(fabs(s[l]-s[2])>0.5){ s[2] = s[l]; s[3] = atan2((double) y[l] - yO, (double) x[l] - xO); j i = i; il++; if (jO < 0) for (s[0] = s[3]; s[0] <= s[3] + rO; s[0] += 0.5 / s[l]) { x[3] = x0 + s[l] *cos(s[0]); y[3] = y0 + s[l] *sin(s[0]); if(!(x[3] = x[4]&&y[3] = y[4])){ x[4] = x[3]; y[4]=y[3]; f[il][jl++] = pr_get(orig_image, x[3], y[3]); } } else for (s[0] = s[3]; s[0] >= s[3] - rO; s[0] -= 0.5 / s[l]) { x[3] = x0 + s[l]*cos(s[0]); y[3] = y0 + s[l]*sin(s[0]); if(!(x[3] = x[4]&&y[3] = y[4])){ x[4]=x[3]; y[4] = y[3]; f[il][jl++] = pr_get(orig_image, x[3], y[3]); } } count[il] =j l ; Appendix 5 Source code for automated module 345 } } f o r ( i = l ; i < = i l ; i + + ) { n[0] = count[i] / 2; n[l]+=f[i][(int)n[0]]; n[2]+=SQR(f[i][(int)n[0]]); } if (il) { n[3] = n [ l ] / i l ; s[0] = n[2] + il * SQR(n[3]) - 2 * n[3] * n[l]; n[4] = 2*sqrt(s[0]/il); n[l] = n[2] = n[0] = 0; for(i= l ; i<=i l ; i++){ j l = 0; for 0 = 1; j <= countfi] / 2; j++) if (jl || f[i]D] < (int) n[3] + n[4] && f[i]D] > (int) n[3] - n[4]) { j i = i; n[i]+=f[i]D]; n[2] += SQR(fTi]D]); n[0] += 1.0; } } for(i= l ; i<= i l ; i++){ j l = 0; for (j = count[i] - 1 ; j >.count[i] / 2; j--) if 01 || mm < (mt) n[3] + n[4] && f[i]0] > (int) n[3] - n[4]) { ji = i; n[l]+=f[i][j]; n[2] += SQR(f[i]G]); n[0]+=1.0; } } if(n[0]>4.0) n[3] = n[l]/n[0]; else return -2; s[0] = n[2] + n[0] * SQR(n[3]) - 2 * n[3] * n[l]; s[0] = sqrt(s[0]/n[0]); if (i2 || s[0] < threshold) return (int) n[3]; else return -1; } else return -2: Appendix 5 Source code for automated module 346 countpoints_between(iO, jO) int iO, jO; { register int i, j , j 1, n = 0, x[5], y[5]; if (theta[seq[iO]] > 0.25 * Pi && theta[seq[iO]] < 0.75 * Pi || theta[seq[iO]] > 1.25 * Pi &&theta[seq[iO]]<1.75*Pi) for (i = 0; i <= num_of_point[seq[iO]]; i++) { x[l] = (newseg[seq[iO]] - i - l)->x; y[l] = (newseg[seq[iO]] - i - l)->y; x[2] = 0; for (j = 0; j <= num_pf_point[seq[j0]]; j++) if (y[l] = (newseg[seq[j0]] - j - l)->y) { x[2] = (newseg[seq[j0]] - j - l)->x; break; } if (x[2]) { if(x[l]>x[2]){ x[3]=x[2]; x[2] = x[l]; x[l] = x[3]; } for (x[3] = x[l] + 3; x[3] < x[2] - 2; x[3]++) if(pr_j>et(x[3],y[l])){ j i = i; for (j = 0; j <= num_of_point[seq[i0]]; j++) if (x[3] = (newseg[seq[i0]] - j - l)->x && y[l] = (newseg[seq[i0]] - j - l)->y) { j l = 0 ; break; } if(jl) for (j = 0; j <= num_of_point[seq[j0]]; j++) if (x[3] = (newseg[seq[j0]] - j - l)->x && y[l] = (newseg[seq[j0]] - j -i)->y) { j l = 0 ; break; } ifOl) n++; } } } else for (i = 0; i <= num_of_point[seq[iO]]; i++) { Appendix 5 Source code for automated module 347 x[l] = (newseg[seq[iO]] - i - l)->x; y[l] = (newseg[seq[iO]j - i - l)->y; y[2] = 0; for (j = 0; j <= num_of_point[seq[jO]]; j++) if (x[l] = (newseg[seq[jO]] - j - l)->x) { y[2] = (newseg[seq[J0]] - j - l)->y; break; } if y[2]){ y[3] = y[2]; y[2] = y[i]; y[i] = y[3]; } for (y[3] = y[l] + 3; y[3] < y[2] - 2; y[3]++) if (pr_j>et(x[l], y[3])) { j i = i; for (j = 0; j <= num_of_point[seq[iO]]; j++) if (x[l] = (newseg[seq[iO]] - j - l)->x && y[3] = (newseg[seq[iO]] - j - l)->y) { j l = 0 ; break; } ifOi) for (j = 0; j <= num_of_point[seq[jO]]; j++) if (x[l] = (newseg[seq[jO]] - j - l)->x && y[3] = (newsegfseqOO]] - j -i)->y) { j l - O ; break; } ifOi) n++; } } } return n; } getarg(desig, argc, argv) int argc; char *desig, *argv[]; { int argn; char minus[2], lookfor[12]; Appendix 5 Source code for automated module 348 strcpy(minus, "-"); strcpy(lookfor, minus); strcat(lookfor, desig); for (argn = 1; argn < argc; argn++) if (!strcmp(argv[argn], lookfor)) return (argn); return (0); } 8. smoothform.c /* This program processes ammonites with few ribs. It was written several years ago and was in poor shape. It is a typical example of bad coding practice, difficult to read and maintain */ #include "auto.h" process_smooth_form() { register int i ,j , k, x[110], y[110]; float tmp[6], x[l] = xx[l][pos[i2]]; int ORIENTATION; y[i] = yy[i][pos[i2]]; x[2] = xx[l][pos[i2] + n[i2] - 1]; y[2]=yy[l][pos[i2]+n[i2]-l]; r[0]=D(xo,yo,x[l],y[l]); r[100]=D(xo,yo,x[2],y[2]); if(r[100]>r[0]) ORIENTATION = 0; else ORIENTATION = 1; n[201] = n[100]/20; if(n[i2]>n[201]){ x[2] = xx[l][pos[i2] + n[201]]; y[2] = yy[l][pos[i2] + n[201]]; r[100]=D(xo,yo,x[2],y[2]); } if(x[l]-xo) tmp[l] = atan2((float) (y[l] - yo), (float) (x[l] - xo)); else tmp[l] = (y[l] > yo) ? Pi / 2.0 : -Pi / 2.0; if(x[2]-xo) tmp[2] = atan2((float) (y[2] - yo), (float) (x[2] - xo)); Appendix 5 Source code for automated module 349 else tmp[2] = (y[2] > yo) ? Pi / 2.0 : -Pi / 2.0; if(tmp[l]*tmp[2]>0.0) tmp[0] = fabs(tmp[2] - tmp[l]); else tmp[0] - LESSPI(fabs(tmp[2] - tmp[l])); tmp[3] = fabs(log(r[100] / r[0]) / tmp[0]); for (i = 1; i <= num_of_point[0]; i++) if(j&&len[i]>pos[i2]-2){ n[101]=i; j = 0; } else if (!j && len[i] > pos[i2] + n[i2] - 3) { n[102] = i; break; } for (i = 0; i <= 72; i++) ox[i] = oy[i] = -1.0; n[201] = num_of_point[0] / 20; ox[80]= 10.0; for(j = 0; jx; y[l] = (segmentfO] - nflOl] - 1 - j)->y; r[0]=D(xo,yo,x[l],y[l]); if(n[i2]>n[201]) n[202]=n[101] + n[201]-j; else n[202]=n[102]-j; x[2] = (segment[0] - n[202])->x; y[2] = (segmentfO] - n[202])->y; r[l]=D(xo,yo,x[2],y[2]); i f(x[l]-xo) tmp[l] = atan2((float) (y[l] - yo), (float) (x[l] - xo)); else tmp[l] = (y[l] > yo) ? Pi / 2.0 : -Pi / 2.0; if(x[2]-xo) tmp[2] = atan2((float) (y[2] - yo), (float) (x[2] - xo)); else tmp[2] = (y[2] > yo) ? Pi / 2.0 : -Pi / 2.0; if(tmp[l] *tmp[2]>0.0) tmp[0] = fabs(tmp[2] - tmpfl]); else tmp[0] - LESSPI(fabs(tmp[2] - tmp[l])); if (ORIENTATION && r[l] < r[0]) { ox[0] = log(r[0]/r[l])/tmp[0]; if (fabs(ox[0] - tmp[3]) < ox[80]) { Appendix 5 Source code for automated module 350 ox[36] = ox[0]; oy[36] = -tmp[0]; ox[80] = fabs(ox[0] - tmp[3]); } } else if (!ORIENTATION && r[l] > r[0]) { ox[0] = log(r[l]/r[0])/tmp[0]; if (fabs(ox[0] - tmp[3]) < ox[80]) { ox[36] = ox[0]; oy[36] = tmp[0]; ox[80] = fabs(ox[0] - tmp[3]); } } } a[0] = r[0]; n[202]+=n[201]; i2 = 37; x[3]=x[2]; y[3] = y[2]; r[3]=r[l] ; tmp[3] = tmp[2]; j0 = 0; for (i = n[202]; i < num_of_point[0]; i += n[201]) { ox[80] = ox[i2 - 1]; for(j = 0;jx; y[4] = (segment[0] - i + j)->y; r[4] = D(xo,yo,x[4],y[4]); if (x[4] - xo) tmp[4] = atan2((float) (y[4] - yo), (float) (x[4] - xo)); else tmp[4] = (y[4] > yo) ? Pi / 2.0 : -Pi / 2.0; if (tmp[3] * tmp[4] > 0.0) tmp[0] = fabs(tmp[4] - tmp[3]); else tmp[0] = LESSPI(fabs(tmp[4] - tmp[3])); if (ORIENTATION && r[4] < r[3]) { ox[0] = log(r[3]/r[4])/tmp[0]; if (fabs(ox[0] - ox[i2 - 1]) < ox[80]) { ox[80] = fabs(ox[0] - ox[i2 - 1J); ox[i2] = ox[0]; oy[i2] = -tmp[0]; x[6]=x[4]; y[6] = y[4]; r[6] = r[4]; Appendix 5 Source code for automated module 351tmp[5] = tmp[4];}} else if (!ORIENTATION && r[4] > r[3]) {ox[O] = log(r[41 / r[3]) I tmp[0];if(fabs(ox[0] - ox[i2 - 1]) < ox[80]) {ox[801 = fabs(ox[0] - ox[i2 - 1]);ox[i2] = ox[0];oy[i2] = tmp[O];x[6] = x[4];y[6]=y[4];r[61 = r{4j;tmp[5] = tmp[4];})}if(ox[80] 0.0) {x[99] = x[2j;y[99j=y[2];c[0j = tmp[2];} else {x[98] = x[21;y[98j=y[2];}} else {if(oy[36] > 0.0) {x[99] = x[3];y[991 = y[31;c[0] =tmp[3];} else {x[98] x[3];y[98j=y[3j;}}n[202] = n[101] +jl - n[201];35;x[3] = x[1];y[3]=y[l];Appendix 5 Source code for automated module 352 tmp[3] = tmp[l]; r[3] = r[0]; for (i = n[202]; i > 0; i -= n[201]) { ox[80] = ox[il + 1]; for(j = 0;jx; y[4] = (segmentfoj - i - j)->y; r[4] = D(xo,yo,x[4],y[4]); cl = l; if(x[4]-xo) tmp[4] = atan2((float) (y[4] - yo), (float) (x[4] - xo)); else tmp[4] = (y[4] > yo) ? Pi / 2.0 : -Pi / 2.0; if (tmp[3] * tmp[4] > 0.0) tmp[0] = fabs(tmp[4] - tmp[3]); else tmp[0] = LESSPI(fabs(tmp[4] - tmp[3])); if (ORIENTATION && r[4] > r[3]) { ox[0] = log(r[4]/r[3])/tmp[0]; if (fabs(ox[0] - ox[il + 1]) < ox[80]) { ox[80] = fabs(ox[0] - ox[il + 1]); ox[il] = ox[0]; oy[il]=tmp[0]; x[6] = x[4]; y[6] = y[4]; r[6] = r[4]; tmp[5] = tmp[4]; } } else if (IORIENTATION && r[4] < r[3]) { ox[0] = log(r[3]/r[4])/tmp[0]; if (fabs(ox[0] - ox[il + 1]) < ox[80]) { ox[80] = fabs(ox[0] - ox[il + 1]); ox[il] = ox[0]; oy[il] = -tmp[0]; x[6] = x[4]; y[6]=y[4]; r[6] = r[4]; tmp[5] = tmp[4]; } } } if(ox[80]x; y[21] = (newsegfseqfij] - l)->y; x[22] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->x; y[22] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->y; r[l] = D(xo,yo,x[21],y[21]); Appendix 5 Source code for automated module 354 i f ( r[ l ] Pi) { tmp[3] = 2 * Pi - tmp[3]; if (ORIENTATION > 0 && (tmp[l] > tmp[2] && r[200] > r[l] || tmp[l] < tmp[2] && r[200] < r[l])) j i = i; else if (ORIENTATION < 0 && (tmp[l] > tmp[2] && r[200] < r[l] || tmp[l] < tmp[2] && r[200] > r[l])) j i = i; } else { if (ORIENTATION > 0 && (tmp[l] > tmp[2] && r[200] < r[l] || tmp[l] < tmp[2] && r[200] > r[l])) j i = i; else if (ORIENTATION < 0 && (tmp[l] > tmp[2] && r[200] > r[l] || tmp[l] < tmp[2] && r[200] < r[l])) j i = i; } tmp[4] = fabs(log(r[200] / r[l])) / tmp[3]; i f ( j l&&tmp[4]<3*a[0]){ label[i] = -2; x[i2] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->x; y[i2] = (newseg[seq[i]J - num_of_point[seq[i]] / 2)->y; tmp[l] = x[i2] -xo; tmp[2] = y[i2]-yo; tmp[2] = atan2(tmp[2], tmp[l]); theta[seq[i]] = POSITIVE(tmp[2]); i2++; if(i2> 10) break; } } } f o r ( i = l ; i < i l ; i + + ) if (label[i] > 0) label[i] = 0; tmp[0] = 0.0; f o r ( i = l ; i < i 2 - l ; i + + ) f o r ( j = i + l ; j < i 2 ; j + + ) { r[200] = D(xo,yo,x[j])yO]); r[201]=D(xo,yo,x[i],y[i]); Appendix 5 Source code for automated module 355 tmp[l] = atan2((double) y[j] - yo, (double) x[j] - xo); tmp[l] = POSITIVE(tmp[l]); tmp[2] = atan2((double) y[i] - yo, (double) x[i] - xo); tmp[2] = POSITIVE(tmp[2]); tmp[4] = 0.0; if (r[201] > r[200]) { for(j0 = 0;j0<5;j0++){ if (ORIENTATION > 0 && (tmp[0] = 2 * jO * Pi + tmp[2] tmp[l])>Pi/3) tmp[4] = log(r[201] / r[200]) / tmp[0]; else if (ORIENTATION < 0 && (tmp[0] = 2 * jO * Pi + tmp[l]- tmp[2])>Pi/3) tmp[4] = log(r[201] / r[200]) / tmp; if (tmp[4] > a[0] / 3 && tmp[4] < 1.5 * a[0]) { c[l] = tmp[4]; d[l] = log(r[201])/c[l]; tmp[4] = log(r[100]) / c[l] + Pi / 2.0; tmp[3] = tmp[2]; j l = 0 ; for (iO = (tmp[4] - d[l]) / (2 * Pi) - 2; iO <= (tmp[4] - d [ l ] ) / ( 2 * P i ) + 2;iO++){ r[4] = exp(c[l] * (d[l] + 2 * Pi * iO + ORIENTATION * (angle - tmp[3]))); if (r[4] < r[100] + (r[100] - r[0]) / 2 && r[4]>(r[100] + r [0] ) /2){ j i = i; break; } } if 01) { tmp[l]=tmp[2] = 0.0; for(ji = l ; j l < i i ; j i + + ) if(label[jl] = - l ) { x[190] = (newseg[seq{jl]] - l)->x; y[190] = (newseg[seq[jl]] - l)->y; x[191] = (newseg[seq[jl]] -num_of_point[seq[jl]] - l)->x; y[191] = (newseg[seq[jl]] -num_of_point[seq[jl]] - l)->y; r[190] = D(xo, yo, x[190], y[190]); r[191] = D(xo, yo, x[191], y[191]); if(r[190]>r[191]){ r[192] = r[191]; r[191] = r[190]; r[190] = r[192]; } Appendix 5 Source code for automated module 356 for (iO = -d[l] / (2 * Pi) - 1.0; iO <= (tmp[4] - d[l]) / (2 * Pi) + 1; i0++) { r[2] = exp(c[l] * (d[l] + 2 * Pi * iO + ORIENTATION *(theta[seq[jl]] - tmp[3]))); if (r[2] < r[0] && r[2] > r[190] && r[2] < r[191]) { tmp[2] += num_of_point[seq[jl]]; break; } } }dseif(label01] = -2){ x[190] = (newseg[seq[jl]] -num_of_point[seq(jl]] / 2)->x; y[ 190] = (newseg[seq[j 1 ]] -num_of_point[seq[jl]] / 2)->y; r[190] = D(xo, yo, x[190], y[190]); for (iO = -d[ 1 ] / (2 * Pi) - 1; iO <= (tmp[4] -d[ l ] ) / (2*Pi )+1.0 ; iO++){ r[2] = exp(c[l] * (d[l] + 2 * Pi * iO + ORIENTATION * (theta[seq[jl]]-tmp[3]))); if (r[2] < r[0] && fabs(r[2] - r[190]) < 5.0) { tmp[l] += num_of_point[seq[jl]]; break; } } } if (tmp[l] / tmp[2] > tmp[0]) { tmp[0] = tmp[l] / tmp[2]; c[0] = c[l]; d[0] = d[l]; sigma = tmp[3]; } } } } } else { for(j0 = 0;j0<5;j0++){ if (ORIENTATION > 0 && (tmp[0] = 2 * jO * Pi + tmp[l] - tmp[2]) > Pi / 3) tmp[4] = log(r[200] / r[201]) / tmp[0]; else if (ORIENTATION < 0 && (tmp[0] = 2 * jO * Pi + tmp[2] - tmp[l]) > Pi 13) tmp[4] = log(r[200] / r[201]) / tmp[0]; if (tmp[4] > a[0] / 3 && tmp[4] < 1.5 * a[0]) { c[l] = tmp[4]; d[l] = log(r[200])/c[l]; Appendix 5 Source code for automated module 357 tmp[4] = log(r[100]) / c[l] + Pi / 2.0; tmp[3] = tmp[l]; for (iO = (tmp[4] - d[l]) / (2 * Pi) - 2; iO <= (tmp[4] - d[l]) / (2 * Pi) + 2; i0++) { r[4] = exp(c[l] * (d[l] + 2 * Pi * iO + ORIENTATION * (angle - tmp[3]))); if (r[4] < r[100] + (r[100] - r[0]) / 2 && r[4] > (r[100] + r[0]) / 2) { j i = i; break; } } if GO { tmp[l]=tmp[2] = 0.0; forOi = i ; j i< i i ; j i++) if(label[jl] = - l ) { x[190] = (newseg[seq[jl]] - l)->x; y[190] = (newseg[seq[jl]] - l)->y; x[191] = (newseg[seq[jl]] - num_of_point[seq[jl]] - l)->x; y[191] = (newseg[seq[jl]] - num_of_point[seq[jl]] - l)->y; r[190] = D(xo, yo, x[190], y[190]); r[191]=D(xo,yo,x[191],y[191]); if(r[190]>r[191]){ r[192] = r[191]; r[191] = r[190]; r[190] = r[192]; } for (iO = -d[l] / (2 * Pi) - 1.0; iO <= (tmp[4] - d[l]) / (2 * Pi)+1.0;i0++){ r[2] = exp(c[l] * (d[l] + 2 * Pi * iO + ORIENTATION * (theta[seq[jl]] - tmp[3]))); if (r[2] < r[0] && r[2] > r[190] && r[2] < r[191]) { tmp[2] += num_of_point[seq[jl]]; break; } } } else if (label[jl] = -2) { x[190] = (newseg[seq[jl]] - num_of_point[seq[jl]] / 2)->x; y[190] = (newseg[seq[jl]] - num_of_point[seq[jl]] / 2)->y; r[190] = D(xo, yo, x[190], y[190]); for (iO = -d[l] / (2 * Pi) -1.0; iO <= (tmp[4] - d[l]) / (2 * Pi)+1.0;i0++){ r[2] = exp(c[l] * (d[l] + 2 * Pi * iO + ORIENTATION * (theta[seq[jl]] - tmp[3]))); if (r[2] < r[0] && fabs(r[2] - r[190]) < 5.0) { tmp[l] += num_of_point[seq[jl]]; break; } Appendix 5 Source code for automated module 358 } } if (tmp[l] / tmp[2] > tmp[0]) { tmp[0] = tmp[l] / tmp[2]; c[0] = c[l]; d[0] = d[l]; sigma = tmp[3]; } } } } } } tmp[4] = log(r[100]) / c[0] + Pi; tmp[0] = r[100]; for (tmp[0] = 0.0; tmp[0] < tmp[4]; tmp[0] += 0.5 / r[l]) { r[l] = exp(c[0]*tmp[0]); il = xo + r[l] * cos(sigma + ORIENTATION * (tmp[0] - d[0])); j l = yo + r[l] * sin(sigma + ORIENTATION * (tmp[0] - d[0])); pr_put(new_image, il, j 1, 1); } pr_dump(new_image, fpo, NULL, RT_STANDARD, 1); prclose(origimage); pr_close(new_image); pr_close(screen[0]); pr_close(screen[ 1 ]); system("stime"); } 9. ribbedform.c #include "auto.h" void process_ribbed_form() { register int i, j , k; /* coiling curves are nearly normal to radius vectors */ confirm_coiling_curve(); /* adjacent ribs should have large overlap along x or y direction */ confirmribbyoverlapQ; Appendix 5 Source code for automated module 359 /* divide into 12 sectors around coiling axis */ analysis_by_sector(); /* remove small ribs located within Pi/10 of big ribs */ remove_small_rib(); confine_coiling_curveO; simulate_morph(); } /* coiling curves are nearly normal to radius vectors (<75) */ static void confirm_coiling_curve(); { register int i, j , x[5], y[5]; double r[5], sigma[2], w; for (i = 1; i < num_of_seg; i++) if(label[i]!=RIB){ j = 0; x[l] = (newseg[seq[i]] - l)->x; y[l] = (newsegfseqfijj - l)->y; x[2] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->x; y[2] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->y; r[l]=D(xo,yo,x[l],y[l]); r[2]=D(xo,yo,x[2],y[2]); sigma[0] = atan2((doubIe) y[l] - yo, (double) x[l] - xo); sigma[0] = POSITIVE(sigma[0]); sigma[l] = atan2((double) y[2] - yo, (double) x[2] - xo); sigma[l] = POSITIVE(sigma[l]); sigma[0] = fabs(sigma[l] - sigma[0]); sigma[0] = LESSPI(sigma[0]); w = fabs(log(r[2] / r[l])) / sigma[0]; /* expansion rate */ i f (wx; y[2] = (newseg[seq[i]J - num_of_point[seq[i]] / 2)->y; sigma[0] = atan2((double) y[2] - yo, (double) x[2] - xo); theta[seq[i]] = POSITIVE(sigma[0]); } } Appendix 5 Source code for automated module 360 /* adjacent ribs should have large overlap along x or y direction */ static void confirm_rib_by_overlap(); { register int i, j , x[5], y[5]; register int numlap;/* number of ribs that overlap with the * current rib */ double delta; double d[100];/* distance between ribs */ for (i = 1; i < num_of_seg; i++) if(label[i] = RIB){ x[l] = (newseg[seq[i]] - l)->x; y[l] = (newseg[seq[f|] - l)->y; x[2] = (newseg[seq[i]] - num_of_point[seq[i]] - l)->x; y[2] = (newseg[seq[i]] - num_of_point[seq[i]] - l)->y; num_lap= 1; /* * the length of each rib should be consistent with * its neighboring ribs */ for (j = i + 1; j < num_of_seg; j++) if (num_of_point[seqO]] > 0.4 * num_of_point[seq[i]] && labelfj] = RTB){ delta = fabs(theta[seq[i]] - theta[seq[j]]); delta = LESSPI(delta); if (delta < Pi / 10) { x[3] = (newseg[seq[j]] - l)->x; y[3] = (newseg[seq[flj - l)->y; x[4] = (newseg[seq[j]] - num_of_point[seq[j]] - l)->x; y[4] = (newseg[seq(j]] - num_of_point[seq[j]] - l)->y; if (abs(y[4] - y[3]) <= abs(x[4] - x[3]) / 10) d[num_lap] = y[l] - y[3]; /* distance between *the two ribs */ else d[num_lap] = (x[l] - x[3] - (x[4] - x[3]) * (y[l] -y[3]) / (y[4] - y[3])) * (y[2] - y[l]) / D(x[l], y[l], x[2], y[2]); if (abs(d[num_lap]) < 2 * num_of_point[seq[j]]) { if (abs(y[2] - y[l]) > abs(x[2] - x[l]) && overlap(y[l], y[2], y[3], y[4]) > 0.4) num_lap-H-; Appendix 5 Source code for automated module 361 else if (abs(y[2] - y[l]) <= abs(x[2] - x[l]) && overlap(x[l], x[2], x[3], x[4]) > 0.4) num_lap++; } } } if (numlap < 4) /* doesn't get enough support */ label[i] = UNKNOWN; } } /* find the farthest and the second farthest ribs in each of the 12 sectors */ static void analysis_by_sector() { register int i, j , x[5], y[5]; double tmp[2]; for (i = 1; i < num_of_seg; i++) if (labelfi] = RIB || labelfi] = UNKNOWN) { x[0] = (newseg[seq[i]] - l)->x; y[0] = (newseg[seq[i]j - l)->y; x[l] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->x; y[l] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->y; tmp[0]=D(xo,yo,x[0],y[0]); tmp[l]=D(xo,yo,x[l],y[l]); if (tmp[0] > tmp[l]) { r[2*i]=tmp[0]; r [ 2 * i - l ] = tmp[l]; } else { r[2*i]=tmp[0]; r [ 2 * i - l ] = tmp[l]; } } for(i = 0 ; i< 100;i++){ repp] = 0; ox[i] = 0.0; } j = 0; for (i = 1; i < num_of_seg; i++) if(label[i] = -l || label[i] > 0) { tmp[0] += num_of_point[seq[i]]; t m p [ l ] + = r [ 2 * i - l ] ; if(j>6) Appendix 5 Source code for automated module 362 break; } tmp[0] /= j ; /* tha average length of the six longest rib * segments */ ribToaxis /= j ; /* tha average distance of the six longest * rib segments from coiling axis */ j = tmp[0]/4; tmp[0] = Pi /6.0; for (i = 1; i < num_of_seg; i++) if «label[i] == RIB || label[i] = UNKNOWN) && num_ofjpoint[seq[i]] > j) { k = theta[seq[i]] / tmp[0] + 1; if (r[2 * i] > ox[k]) ox[k] = r[2 * i]; } for (i = 1; i < num_of_seg; i++) if ((label[i] = -1 || label[i] > 0) && num_of_point[seq[i]] > j) { k = theta[seq[i]] / tmp[0]; if (r[2 * i] > ox[20 + k] && r[2 * i] < ox[k]) { ox[20 + k] = r[2 * i]; rep[k] = i; } } } static void remove_small_rib() { register int i, j , k, big, rt, It; double tmp[2]; for (i = 0; i < 12; i++) if (ox[20 + i] > 0.0) { k = (i + 1< 12) ? i + 1 : i + 1 - 12; if (ox[20 + big] > 0.0) { tmp[l] = fabs(theta[seq[rep[i]]] - theta[seq[rep[big]]]); if (tmp[l] < Pi / 10.0 || tmp[l] > 2 * Pi - Pi / 12.0) { if (ox[20 + i] < ox[20 + big]) ox[20 + i] = 0.0; else ox[20 + big] = 0.0; } } } tmp[l] = ox[20 + 0]; big = 0; for( i= l ; i < 12; i++) Appendix 5 Source code for automated module 363 if(ox[20 + i]>tmp[l]){ tmp[l] = ox[20 + i]; big = i; } /* big is Big rib */ f o r ( i = l ; i < 12;i++){ rt = (big + i < 12) ? big + i: big + i - 12; if(rep[rt]) break; } /* Big rib's right neighbour */ for(i=l;i<12;i++){ It = (big - i < 0) ? 12 + big - i : big - i; if(rep[lt]) break; } /* Big rib's left neighbour */ /* * if a rib candidate is closer to coiling axis then both its left * and right ribs, it should be removed */ for (i = 0; i < 12; i++) if(rep[i]&&i!=rt&&i!=lt){ for(j = l ; j<12;j++){ k = ( i + j < 12)?i+j : i + j - 12; if(rep[k]) break; } for(j = l ; j<12;j++){ k = ( i - j < 0 ) ? 1 2 + i - j : i - j ; if(rep[k]) break; } if (ox[20 + i] < ox[20 + k] && ox[20 + i] < ox[20 + k]) ox[20 + i] = 0.0; } tmp[0]=tmp[l] = 0; for(i = 0 ; i< 12; i++) if (ox[20 + i] > 0.0 && i != big) for(j = l ; j<12;j++){ rt = ( i + j < 12)? i+j : i + j - 12; if(ox[20 + rt]>0.0){ delta = theta[seq[rep[rt]]] - theta[seq[rep[i]]]; delta = POSITIVE(delta); if (ox[20 + rt] < ox[20 + i] && ox[20 + rt] > ox[20 + i] / exp(0.4 * delta)) tmp[0] += ox[20 + i]; Appendix 5 Source code for automated module 364 else if (ox[20 + rt] > ox[20 + i] && ox[20 + rt] < ox[20 + i] * exp(0.4 * tmp[l])) tmp[l]+=ox[20 + i]; break; } } if(tmp[0]>tmp[l]){ ORIENTATION = 1;/* right-lateral */ forO = i ; j < i i ; j + + ) { rt = (big - j < 0) ? 12 + big - j : big - j ; if (ox[20 + rt] > 0.0) { delta = theta[seq[rep[big]]] - theta[seq[rep[rt]]]; delta = POSITIVE(delta); if (ox[20 + rt] > ribToaxis * exp(0.4 * delta)) ox[20 + rt] = 0.0; else break; } } for (i = 0; i < 12; i++) if (ox[20 + i] > 0.0 && i != rt) { for0 = l ; j<12; j++){ lt = ( i + j < 12 )? i+ j : i + j - 12; if (ox[20 + It] > 0.0) break; } delta = theta[seq[rep[lt]]] - theta[seq[rep[i]]]; delta = POSITIVE(delta); if(ox[20 + i] 0.0) { delta = theta[seq[rep[rt]]] - theta[seq[rep[big]]]; delta = POSITIVE(delta); if (r[2 * rep[rt]] > ribToaxis * exp(0.4 * delta)) ox[20 + rt] = 0.0; else break; } Appendix 5 Source code for automated module 365 } for (i = 0; i < 12; i++) if (ox[20 + i] > 0.0 && i != it) { for ( j= l ; j<12; j++){ lt = ( i - j < 0 ) ? 1 2 + i - j : i - j ; if (ox[20 + It] > 0.0) break; } delta = theta[seq[rep[i]]] - theta[seq[rep[lt]]]; delta = POSITIVE(delta); if (ox[20 + i] < ox[20 + It]) ox[20 + i] = 0.0; else if (ox[20 + It] < ox[20 + i] / exp(0.4 * delta)) ox[20 + It] = 0.0; } } } static void confine_coiling_curve() { register int i, j , k, iO, x[l 10], y[l 10]; double tmp[5]; tmp[ 1 ] = Pi * imageSize / 100.0; for (iO = 0; iO < 12; i0++) if(ox[20 + i0]>0.0){ tmp[3] = tmp[4] = imageSize / 15; k = 0; x[19] = (newseg[seq[rep[iO]]] - l)->x; y[19] = (newseg[seq[rep[i0]]j - l)->y; x[20 + iO] = (newseg[seq[rep[iO]]] - num_of_point[seq[rep[iO]]] - l)->x; y[20 + iO] = (newseg[seq[rep[iO]]] - num_of_point[seq[rep[iO]]] - l)->y; if (D(xo, yo, x[19], y[19]) > D(xo, yo, x[20 + iO], y[20 + iO])) { x[20 + i0]=x[19]; y[20 + i0]=y[19]; } for (i = 1; i < num_of_seg; i++) if (label[i] = -2 && num_of_point[seq[i]] > tmp[l]) { x[100] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->x; y[100] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->y; ox[100] = D(xo, yo, x[100], y[100]); tmp[2] = fabs(theta[seq[rep[iO]]] - theta[seq[i]]); tmp[2] = LESSPI(tmp[2]); ox[101] = imageSize/ 15; if (ox[100] > ox[20 + iO] / 2.0 && tmp[2] < Pi / 4.0) Appendix 5 Source code for automated module 366 for (jj = 0; j <= num_of_point[seq[i]]; j++) { x[100] = (newseg[seq[i]] - j - l)->x; y[100] = (newseg[seq[i]] - j - l)->y; ox[99] = D(xo, yo, x[100], y[100]); if(ox[99]>ox[20 + i0]){ ox[100] = D(x[20 + iO], y[20 + iO], x[100], y[100]); if(ox[100] 0) { if (tmp[4] * num_of_point[seq[rep[20 + iO]]] < tmp[3] * num_of_point[seq[k]]) { rep[20 + iO] = k; x[20 + iO] = x[103]; y[20 + i0]=y[103]; } else if (rep[20 + iO] > 0) { x[20 + i0] = x[102]; y[20 + i0] = y[102]; } } else if (rep[20 + iO] > 0) { x[20 + i0] = x[102]; y[20 + i0] = y[102]; } } } /* * This program was written several years ago, typical spaghetti code, very * difficult to read. It may need a few weeks to clean it up Appendix 5 Source code for automated module 367 */ static void simulate_morph() { int x[200], y[200], pos[1000], n[200]; int varl, var2; float sigma, angle, sclefact, xx[2][MAXNUM], yy[2][MAXNUM]; float a[200], b[200], c[200], d[200]; /* morph parameters */ float rfMAXNUM], ox[MAXNUM], oy[MAXNUM]; float tmp[6]; register i, j , i l , j l , iOJO, i2; for (i = 0; i < 12; i++) if(ox[20 + i]>0.0){ ox[20 + i] = D(xo, yo, x[20 + i], y[20 + i]); oy[20 + i] = atan2((double) y[20 + i] - yo, (double) x[20 + i] - xo); oy[20 + i] = POSITIVE(oy[20 + i]); } ox[l] = tmp[2] = ox[20 + n[3]]; oy[l]=tmp[l] = oy[20 + n[3]]; x[ l]=x[20 + n[3]]; y[l]=y[20 + n[3]]; i 0 = l ; for (i = 1; i < 12; i++) { if(ORTENTATION>0) n[4] = (n[3] + i < 12) ? n[3] + i : n[3] + i - 12; else n[4] = (n[3] - i < 0) ? 12 + n[3] - i : n[3] - i; if (ox[20 + n[4]] > 0.0) { if(ORIENTATION>0) tmp[3] = oy[20 + n[4]] - tmp[l]; else tmp[3] = tmp[l] - oy[20 + n[4]]; tmp[3] = POSITIVE(tmp[3]); tmp[4] = log(tmp[2] / ox[20 + n[4]]); if (tmp[4] < 0.05 * tmp[3] || tmp[4] > 0.4 * tmp[3]) ox[20 + n[4]] = 0.0; else if (iO > 2 && (tmp[4] > 3.0 * tmp[3] * a[i0 - 1] || tmp[4] < tmp[3] * a[i0-l] /3.0)) ox[20 + n[4]] = 0.0; else { a[i0] = tmp[4] / tmp[3]; i0++; x[i0] = x[20 + n[4]]; y[i0] = y[20 + n[4]]; Appendix 5 Source code for automated module 368 tmp[2] = ox[iO] = ox[20 + n[4]]; tmp[l] = oy[i0] = oy[20 + n[4]]; } } } a[0] = tmp[4] = 0.0; b[100] = ox[l]; i0++; for (i = 2; i < iO; i++) { tmp[l] = log(ox[i])/a[i-l]; tmp[2]=log(ox[i- l]) /a[ i- l ] ; tmp[3] = oy[i - 1]; if(i = 2) c[100] = oy[0] = tmp[3]; a[99 + i] = a[i - 1]; b[99 + i] = ox[i]; c[99 + i] = oy[i]; tmp[4] += tmp[2] - tmp[l]; a[0]+=a[i-l]*(tmp[2]-tmp[l]); for (tmp[0] = tmp[l]; tmp[0] <= tmp[2]; tmp[0] += 0.5 / ox[i - 1]) { r[0] = exp(a[i - 1] * tmp[0]); i2 = xo + r[0] * cos(tmp[3] - ORIENTATION * (tmp[0] - tmp[2])); jO = yo + r[0] * sin(tmp[3] - ORIENTATION * (tmp[0] - tmp[2])); pr_put(new_image, i2, jO, 1); } printf("i=%d k=%f \n", i - 1, a[i - 1]); } a[0]/=tmp[4]; var2 = i0- 1; for (i = 1; i < num_of_seg - 1 ; i++) if (labelp] > 0 && labelp] != 2) { rep[100] = i; j l = 101; for (j = i + 1; j < num_of_seg; j++) if (labelfj] > 0) { tmp[3] = (r[2 * i] - r[2 * i - 1] > 120.0) ? (r[2 * i] - r[2 * i -1])/20.0: 6.0; tmp[4] = fabs(r[2 * j] - r[2 * i]); if(tmp[4] 102) Appendix 5 Source code for automated module 369 for0 = 100;j 0 && label[i] != 3) { rep[l 00] = i; j l = 101; for (j = i + 1; j < num_of_seg; j++) if (label[j] > 0) { tmp[3] = (r[2 * i] - r[2 * i - 1] > 120.0) ? (r[2 * i] - r[2 * i -1])/20.0: 6.0; tmp[4] = fabs(r[2 * j - 1] - r[2 * i - 1]); if(tmp[4] 102) { for(j=100;j 2) { ox[100+j] = r [ 2 * i - l ] ; if 0 > 6) break; } for (i = 100; i < 106; i++) for(j = i+ l ; j<107 ; j++) if (ox[i] < ox[j]) { ox[107] = ox[i]; ox[i] = ox[j]; oxjj] = ox[107]; } ox[107] = 0.0; for (i = 101; i < 106; i++) ox[107]+=ox[i]; ox[107] /= 5.0; Appendix 5 Source code for automated module 370 tmp[0] = ox[107] + (ox[l] - ox[107]) / 15.0; n[4]=n[5] = 0; for (i = 1; i < num_of_seg; i++) if ((Iabelp] = 3 || label[i] == 4) && r[2 * i - 1] < ox[107]) { n[4]++; for (j = 1; j < num_of_seg; j++) if (labelfj] > 0 && r[2 * i - 1] > r[2 * j] && r[2 * i - 1] - r[2 * j] < r[2 * i] - r[2 * i - 1]) { tmp[0] = fabs(theta[seq[i]] - theta[seq[j]]); tmp[0] = (tmp[0] > 1.8 * Pi) ? 2 * Pi - tmp[0] : tmp[0]; if(tmp[0] 0.2 * n[4]) { tmp[0] = 0.0; tmpfl] = 2 * Pi * imageSize /100.0; for (i = 1; i < 500; i++) { rep[i] = 0; ox[i] = 1000.0; } i 0 = l ; for (i = 1; i < num_of_seg; i++) if (label[i] = 2 || Iabelp] = 4) { tmp[2]=Pi/18; for (j = 1; j < num_of_seg; j++) if (labelO] > 0 && r[2 * j - 1] > r[2 * i] && r[2 * j - 1] -r[2 * i] < r[2 * i] - r[2 * i - 1]) { tmp[0] = fabs(theta[seq[i]] - theta[seq[j]]); tmp[0] = (tmp[0] > 1.8 * Pi) ? 2 * Pi - tmp[0] : tmp[0]; if(tmp[0] 0 && r[2 * i - 1] > r[2 * j] && r[2 * i - 1] -r [ 2 * j ] < r [ 2 * i ] - r [ 2 * i - l ] ) { tmp[0] = fabs(theta[seq[i]] - theta[seq[j]]); tmp[0] = (tmp[0] > 1.8 * Pi) ? 2 * Pi - tmp[0] : tmp[0]; if(tmp[0] ox[j]) { ox[0] = ox[i]; oxfi] = ox[j]; ox[j] = ox[0]; pos[0] = pos[i]; pos[i] = pos[j]; pos[j] = pos[0]; } /* remove false rib-between points */ for(i= l ; i< i0 ; i++){ tmp[3] = theta[seq[rep[2 * pos[i]]]]; if (r[2 * rep[2 * posp]]] > r[2 * rep[2 * pos[i] - 1]]) tmp[4] = (r[2 * rep[2 * posp] - 1]] + r[2 * rep[2 * pos[i]] - 1]) / 2.0; else tmp[4] = (r[2 * rep[2 * pos[i]]] + r[2 * rep[2 * pos[i] - 1] - 1]) / 2.0; tmp[l] = tmp[2] = 0.0; for (jj = 1; j < num_of_seg; j++) if (labelQ] > 1) { tmp[0] = fabs(theta[seq[j]] - tmp[3]); tmp[0] = LESSPI(tmp[0]); if(tmp[0] tmp[4] && r[2 * j - 1] < tmp[4] && tmp[4] -r [ 2 * j - l ] > 0 . 1 0 * ( r [ 2 * j ] - r [ 2 * j - 1]) && tmp[4] - r[2 * j - 1] < 0.90 * (r[2 * j] - r[2 * j - 1])) t m p [ 2 ] + = r [ 2 * j ] - r [ 2 * j - l ] ; else if (fabs(r[2 * j] - tmp[4]) < 0.1 * (r[2 * j] - r[2 * j - 1]) || fabs(r[2 * j - 1] - tmp[4]) < 0.1 * (r[2 * j] - r[2 * j -1])) t m p [ l ] + = r [ 2 * j ] - r [ 2 * j - l ] ; } } if(tmp[2]>=tmp[l]/2.0) ox[i] = 1000.0; } i 2 = l ; n P ] = 1; /* number of control points-xx-yy */ for(i= l ; i r[2 * rep[2 * pos[i] - 1]]) { xx[0][n[3]] = r[2 * rep[2 * pos[i] - 1]]; xx[l][n[3]] = r [2*rep[2*pos[ i ] ] - l ] ; } else { xx[0][n[3]] = r[2 * rep[2 * pos[i]]]; xx[l][n[3]] = r[2 * rep[2 * pos[i] - 1] - 1]; } tmp[4] = (xx[0][n[3]] + xx[l][n[3]]) / 2.0; n[3]++; tmp[0] = fabs(tmp[3] - oy[0]); tmp[0] = LESSPI(tmp[0]); if(tmp[0] 0) { if(tmp[3]>oy[0]) tmp[l] = tmp[3]-oy[0]; else tmp[l] = 2 * Pi - oy[0] + tmp[3]; } else if (ORIENTATION < 0) { if(tmp[3]10) break; else if (i2 > 5 && ox[i] > imageSize / 20.0) break; } tmp[0] = 1000.0; for (i = 1; i < num_of_seg; i++) if (labelfi] > 2 && r[2 * i - 1] < tmp[0]) { tmp[0] = r[2 * i -1] ; n[100 + 2 * i 2 - l ] = i; } x[100] = (newseg[seq[n[100 + 2 * i2 - 1]]] - l)->x; y[100] = (newseg[seq[n[100 + 2 * i2 - 1]]] - l)->y; x[101] = (newseg[seq[n[100 + 2 * i2 - 1]]] - num_of_point[seq[n[100 + 2 * i2 - 1]]] -l)->x; y[101] = (newseg[seq[n[100 + 2 * i2 - 1]]] - num_of_point[seq[n[100 + 2 * i2 - 1]]] -i)->y; oy[i2] = theta[seq[n[100 + 2 * i2 - 1]]]; ox[i2] = imageSize / 60; tmp[l] = D(xo, yo, x[100], y[100]); tmp[2] = D(xo, yo, x[101], y[101]); Appendix 5 Source code for automated module 374 if(tmp[l] ox[j]) { ox[0] = ox[i]; ox[i] = ox[j]; oxjj] = ox[0]; pos[0] = pos[i]; posji] = pos[j]; pos[j] = pos[0]; } d[62] = ox[i2 - 1]; f o r ( i = l ; i < i 2 - 1; i++) if (ox[i] < 100.0) for(j = i+ l ; j< i2 ; j++) if (ox[j] < 100.0) { tmp[l] = oy[100 + pos[i]]; tmp[2] = oy[100 + posjj]]; if(tmp[l]>tmp[2]){ tmp[0] = tmp[l]; tmp[l] = tmp[2]; tmp[2] = tmp; tmp[0] = oy[pos[i]]; tmp[5] = oy[pos[j]]; } else { tmp[0] = oy[pos[j]]; tmp[5] = oy[pos[i]]; d[60]=1.0; d[61] = 0.0; tmp[0] = 0.0; for (iO = -4; iO < 5; i0++) { d[50 + iO] = log(tmp[2] / tmp[l]) / (2 * Pi * iO -ORIENTATION * (tmp[0] - tmp[5])); if (d[50 + iO] < 0.3 && d[50 + iO] > 0.05) { n[4] = n[5] = n [ 6 ] = l ; for(il = l ; i l tmp[2] || xx[l][il] < tmp[l])) { f o r ( j l = 0 ; j l < 5 ; j l + + ) { tmp[3] = 2 * P i * j l -ORIENTATION * (tmp[0] - yy[0][il]); tmp[4] = tmp[2] / exp(d[50 + iO] * tmp[3]); if (tmp[4] < tmp[2] && tmp[4] > tmpfl] && tmp[4] > xx[0][il] && tmp[4] < xx[l][il]) { n[4]++; break; } if(tmp[4] 0 && !(r[2 * il - 1] > tmp[2] && r[2 * i l ]< tmp[ l ] ) ){ r[0] = (r[2 * il] - r[2 * il -1]) / 8.0; fo r ( j l=0 ; j l<5 ; j l -H- ){ tmp[3] = 2 * Pi * j l - ORIENTATION * (tmp[0] - theta[seq[il]]); tmp[4] = tmp[2] / exp(d[50 + iO] * tmp[3]); if (tmp[4] > tmp[l] && tmp[4] < tmp[2]) { tmp[3] = MIN(fabs(tmp[4] - r[2 * il]), fabs(tmp[4] - r[2 * il -1])); if (tmp[4] > r[2 * il - 1] + r[0] && tmp[4] < r[2 * il] -r[0]){ n[5] += num_of_point[seq[il]]; break; }elseif(tmp[3] d[61] || tmp[3] = d[61] && fabs(d[50 + iO] - a[0]) < d[60]) { d[60] = fabs(d[50 + iO] - a[0]); tmp[0] = d[50 + iO]; d[61] = tmp[3]; } } } if (d[60] > 0.4 || tmp[0] > 0.3) Appendix 5 Source code for automated module 376 ox[j] = 100.0; else { for (iO = j + 1; iO <= i2; i0++) if (oy[100 + pos[i0]] > tmp[l] && oy[100 + pos[i0]] < tmp[2]) { if (r[2 * n[100 + 2 * pos[i0]]] > r[2 * n[100 + 2 * pos[i0] - 1]]) { tmp[3] = r[2 * n[100 + 2 * pos[i0] - 1]]; tmp[5] = r[2 * n[100 + 2 * pos[i0]] - 1]; } else { tmp[3] = r[2 * n[100 + 2 * pos[i0]]]; tmp[5] = r[2 * n[100 + 2 * pos[i0] - 1] - 1]; } forOO = -4;jO<5;jO++){ tmp[0] = 2 * Pi * jO - ORIENTATION * (oy[pos[i]] -oy[pos[i0]]); tmp[0] = oy[100 + pos[i]] * exp(tmp[0] * tmp); if (tmp[0] > tmp[3] && tmp[0] < tmp[5]) ox[i0] = 100.0; } } } } for (i = 101; i <= 100 + i2; i++) pos[i] = i - 100; fo r ( i= l ; i<=i2 ; i++) if (ox[i] = 100.0) pos[100 + pos[i]] = 0; for(i= l ; i0) for0 = i+ l ; j<=i2; j++) if(pos[100+j]>0) if (oy[pos[100 + i] + 100] < oy[pos[100 + j] + 100]) { pos[100] = pos[100 + i]; pos[100 + i] = pos[100+j]; pos[100+j] = pos[100]; } jo = i; for(i= 101;i<100 + i2;i++) if(pos[i]>0){ for (j = i + 1; j <= 100 + i2; j++) if(posD]>0){ i0=j ; break; } tmp[3] = oy[100 + pos[i]]; tmp[4] = oy[100 + pos[i0]]; a[j0] = 0.0; Appendix 5 Source code for automated module 377 d[61] = 0.0; d[60] = 1.0; for(j = 0;j<5;j++){ d[50 + j] = log(tmp[3] / tmp[4]) / (2 * Pi * j - ORIENTATION * (oy[pos[i]] - oy[pos[iO]])); if (d[50 + j] < 0.3 && d[50 + j] > 0.05) { n[4] = n[5]=n[6] = l; for(il = l;il tmp[3] || xx[L][il] < tmp[4])) { f o r01=0 ; j l<5 ; j l - f+ ){ tmp[l] = 2 * P i * j l -ORIENTATION * (oy[pos[i]] -yy[0][ii]); tmp[2] = tmp[3] / exp(d[50 + j] * tmp[l]); if (tmp[2] > tmp[4] && tmp[2] < tmp[3] && tmp[2] > xx[0][il] && tmp[2] 0 && !(r[2 * il - 1] > tmp[3] && r[2 * il] < tmp[4])) { r[0] = (r[2 * il] - r[2 * il - 1]) / 8.0; fo r ( j l=0 ; j l<5 ; j l++){ tmp[l] = 2 * Pi * j l - ORIENTATION * (oy[pos[i]] -theta[seq[il]]); tmp[2] = tmp[3] / exp(d[50 + j] * tmp[l]); if (tmp[2] < tmp[3] && tmp[2] > tmp[4]) { tmp[l] = MIN(fabs(tmp[2] - r[2 * il]), fabs(tmp[2] - r[2 * il - 1])); n[6] += num_of_point[seq[il]]; if (tmp[2] > r[2 * il - 1] + r[0] && tmp[2] < r[2 * il] - r[0]) { n[5] += num_of_point[seq[il]]; break; }elseif(tmp[l] d[61] || tmp[2] = d[61] && fabs(d[50 + iO] - a[0]) < d[60]) { Appendix 5 Source code for automated module 378 d[61] = tmp[2]; d[60] = fabs(d[50+j]-a[0]); aD'0] = d[50+j]; } } } if(aOO]>0.05){ tmp[l] = log(tmp[4])/aOO]; tmp[2] = log(tmp[3])/a[j0]; >f 00 — 1) { b[0]=tmp[3]; c[0] = oy[pos[i]]; } bB0] = tmp[4]; c[j0] = oy[pos[i0]]; tmp[3] = oy[pos[i]]; for (tmp[0] = tmp[2]; tmp[0] >= tmp[l]; tmp[0] -= 0.5 / r[0]) { r[0] = exp(a[j0] * tmp[0]); il = xo + r[0] * cos(tmp[3] - ORIENTATION * (tmp[0] - tmp[2])); j l = yo + r[0] * sin(tmp[3] - ORIENTATION * (tmp[0] - tmp[2])); pr_put(new_image, i 1, j 1, 1); } J0++; } } varl =j0; b[varl - 1] /= exp(a[varl -1] * 2 * Pi); } else { for (i = 1; i < 100; i++) repp] = 0; i 0 = l ; cl = l; ox[0] = tmp[0]; tmp[0] = 0.0; while (cl) { ox[i0] = ox[0]; for (i = 1; i < numofseg; i++) if ((label[i] = 3 || label[i] = 4) && r[2 * i - 1] < ox[i0]) { if (iO = 1) J 0 = 1 ; elseif(i0 = 2){ tmp[0] = fabs(theta[seq[i]] - theta[seq[rep[2 * (iO - 1) -i]]]); tmp[0] = LESSPI(tmp[0]); tmp[4] = fabs(log(r[2 * i - 1] / ox[i0 - 1])); if (tmp[0] > Pi / 6.0 && tmp[4] > 0.05 * tmp[0]) Appendix 5 Source code for automated module 379 j o = i ; else j0 = 0; } else if (iO > 2) { tmp[4] = fabs(log(r[2 * i - 1] / ox[iO - 1])); if (ORIENTATION < 0) { tmp[0] = LARGER(theta[seq[i]], theta[seq[rep[2 * (iO - 1) - i]]]); if (tmp[4] < 0.5 * tmp[0] && tmp[4] > 0.05 * tmp[0] && theta[seq[i]] > theta[seq[rep[2 * (iO - 1) -1]]] && tmp[0] > Pi / 6.0 && tmp[0] + tmp < 2 * Pi) J 0 = 1 ; else if (tmp[4] < 0.5 * tmp[0] && tmp[4] > 0.05 * tmp[0] && theta[seq[i]] < theta[seq[rep[2 * (iO -1) - 1]]] && theta[seq[rep[2 * (iO - 1) - 1]]] - theta[seq[i]] < 2 * Pi - Pi / 6.0 && theta[seq[rep[l]]] -theta[seq[i]] > Pi / 6.0 && tmp[0] + tmp < 2 * Pi) J 0 = 1 ; else JO = 0; } else { tmp[0] = LARGER(theta[seq[rep[2 * (iO - 1) - 1]]], theta[seq[i]]); if (tmp[4] < 0.5 * tmp[0] && tmp[4] > 0.05 * tmp[0] && theta[seq[i]] < theta[seq[rep[2 * (iO -1) - 1]]] && tmp[0] > Pi / 6.0 && tmp[0] + tmp < 2 * Pi) J0=1 ; else if (tmp[4] < 0.5 * tmp[0] && tmp[4] > 0.05 * tmp[0] && theta[seq[i]] > theta[seq[rep[2 * (iO - 1) - 1]]] && theta[seq[i]] -theta[seq[rep[2 * (iO -1) - 1]]] < 2 * Pi - Pi / 6.0 && theta[seq[i]] - theta[seq[rep[l]]] > Pi / 6.0 && tmp[0] + tmp < 2 * Pi) J0=1 ; else j0 = 0; } } if GO) { ox[iO] = r[2 * i - 1]; x[101] = (newseg[seq[i]] - l)->x; x[102] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->x; y[102] = (newseg[seq[i]] - 1 - num_of_point[seq[i]])->y; tmp[3]=D(xo,yo,x[101],y[101]); tmp[4] = D(xo, yo, x[102], y[102]); if (tmp[3] > tmp[4]) { x[i0] = x[102]; y[i0] = y[102]; Appendix 5 Source code for automated module 380 } else { x[i0] = x[101]; y[i0]=y[101]; } rep[2*i0- l] = i; } } if (iO > 1 && rep[2 * iO -1] > 0) { tmp = theta[seq[rep[2 * iO -1]]] - theta[seq[rep[2 * (iO - 1) - 1]]]; if(ORIENTATION<0) tmp[0] += POSITIVE(tmp); else tmp[0] +=POSITIVE(-tmp); } if (iO > 2 && rep[2 * iO - 1] > 0) { tmp = fabs(theta[seq[rep[2 * iO -1]]] - theta[seq[rep[l]]]); tmp = LESSPI(tmp); } if (iO > 2 && (tmp < Pi / 4 || rep[2 * iO - 1] = 0)) c l = 0 ; else { tmp[3] = tmp[4] = imageSize /15; j l = 0 ; for (i = 1; i < num_of_seg; i++) if(label[i] = -2){ x[100] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->x; y[100] = (newseg[seq[i]] - num_of_point[seq[i]] / 2)->y; ox[100] = D(xo, yo, x[100], y[100]); ox[101] = imageSize / 15; if(ox[100]<2*ox[i0]) for (j = 0; j <= num_of_point[seq[i]]; j++) { x[100] = (newseg[seq[i]] - j - l)->x; y[100] = (newseg[seq[i]] - j - l)->y; ox[99] = D(xo, yo, x[ 100], y[ 100]); tmp[0] = atan2((double) y[100] - yo, (double) x[100] - xo); tmp[0] = POSITIVE(tmp[0]); tmp[0] = fabs(theta[seq[rep[2 * (iO - 1) - 1]]] - tmp[0]); tmp[0] = LESSPI(tmp[0]); if (ox[99] < ox[iO] && (log(ox[99] / ox[iO - 1]) > 0.05 * t m p [ 0 ] | | i 0 = l ) ) { ox[100] = D(x[i0], y[i0], x[100], y[100]); if(ox[100]0){ if(tmp[4] * num_of_point[seq[rep[2 * iO]]] 0){ x[i0]=x[102]; y[i0] = y[102]; } }elseif(rep[2*i0]>0){ x[i0] = x[102]; y[i0] = y[102]; } if( iO>l){ tmp[3] = atan2((double) y[iO -1] - yo, (double) x[iO - 1] - xo); tmp[3] = POSITIVE(tmp[3]); tmp[4] = atan2((double) y[iO] - yo, (double) x[iO] - xo); tmp[4] = POSITIVE(tmp[4]); if(ORENTATION<0) tmp[0] = LARGER(tmp[4], tmp[3]); else tmp[0] = LARGER(-tmp[4], -tmp[3]); tmp[3] = D(xo, yo, x[iO - 1], y[iO - 1]); tmp[4]=D(xo,yo,x[iO],y[iO]); d[iO - 1] = fabs(log(tmp[3] / tmp[4])) / tmp[0]; } ox[iO++] = D(xo, yo, x[iO], y[iO]); } } for(i= l;ix; * jO=(newseg[seq[rep[i]]]-j-l)->y; * pr_put(new_image,i2j0,l); } */ a[0] = tmp[4] = 0.0; tmp[l]=log(ox[l])/d[l]; tmp[3] = atan2((double) y[l] - yo, (double) x[l] - xo); tmp[3] = POSITIVE(tmp[3]); if (ORIENTATION < 0) { if(tmp[3]>oy[0]) tmp[2] = tmp[l] - (tmp[3] - oy[0]); else tmp[2] = tmp[l] - (tmp[3] + 2 * Pi - oy[0]); \ glse i if(tmp[3]2*Pi ) c[i0 - 2] -= 2 * Pi; for (tmp[0] = tmp[2]; tmp[0] < tmp[l]; tmp[0] += 0.5 / ox[l]) { r[0] = exp(d[l]*tmp[0]); i2 = xo + r[0] * cos(tmp[3] - ORIENTATION * (tmp[0] - tmp[l])); jO = yo + r[0] * sin(tmp[3] - ORIENTATION * (tmp[0] - tmp[l])); pr_put(new_image, i2, jO, 1); } for (i = 2; i < iO; i++) { tmp[2] = log(ox[i])/d[i-l]; tmp[l] = log(ox[ i - l ] ) /d[ i - l ] ; a[i0-i] = d [ i - l ] ; i f ( i>2) b[i0 - i] = ox[i - 1]; i f ( i = = i 0 - l ) { b[0] = ox[i]; c[0] = atan2((double) y[i] - yo, (double) x[i] - xo); c[0] = POSITIVE(c[0]); } tmp[3] = atan2((double) y[i -1] - yo, (double) x[i - 1] - xo); tmp[3] = POSITIVE(tmp[3]); Appendix 5 Source code for automated module 383 if (i > 2) c[iO - i] = tmp[3]; tmp[4] += tmp[2] - tmp[l]; a[0]+=d[i-l]*(tmp[2]-tmp[l]); for (tmp[0] = tmp[l]; tmp[0] <= tmp[2]; tmp[0] += 0.5 / ox[i - 1]) { r[0] = exp(d[i-l]*tmp[0]); i2 = xo + r[0] * cos(tmp[3] - ORIENTATION * (tmp[0] - tmp[l])); jO = yo + r[0] * sin(tmp[3] - ORIENTATION * (tmp[0] - tmp[l])); pr_put(new_image, i2, jO, 1); } printf^i=%d k=%f \n", i - 1, d[i - 1]); } varl = i 0 - 1; a[0]/=tmp[4]; } tmp[l] = 0.0; tmp[2] = c[0]; for (i = 1; i < num_of_seg; i++) if ((label[i] == -1 || label[i] > 0) && r[2 * i - 1] > b[0]) { if (ORIENTATION >0) tmp[0] = c[0] - theta[seq[i]]; else tmp[0] = theta[seq[i]] - c[0]; tmp[0] = POSITIVE(tmp[0]); tmp[3] = b[0] * exp(a[l] * tmp[0]); if (tmp[0] < Pi / 2.0 && tmp[0] > tmp[l] && tmp[3] < (r[2 * i] + r[2 * i -1]) / 2.0 && r[2 * i - 1] - tmp[3] < r[2 * i] - r[2 * i - 1]) { tmp[0] = 2 * (r[2 * i] - r[2 * i - 1]) / (r[2 * i] + r[2 * i - 1]); i l = j l = 0 ; for (j = 1; j < num_of_seg; j++) if (j != i && (label[j] = -1 || label[j] > 0) && r[2 * j - 1] > b[0] && num_of_point[seq[j]] < 3 * num_of_point[seq[i]] && num_of_point[seq[j]] > num_of_point[seq[i]] / 3 && overlap(r[2 * i - l ] , r [ 2 * i ] , r [ 2 * j - l ] , r [ 2 * j ] ) > 0 . 7 ) { if (ORIENTATION > 0) tmp[3] = theta[seq[j]] - theta[seq[i]]; else tmp[3] = theta[seq[i]] - theta[seq[j]]; tmp[3] = POSITIVE(tmp[3]); if(tmp[3]0) tmp[3] = theta[seq[i]] - theta[seq[j]]; else tmp[3] = theta[seq[j]] - theta[seq[i]]; Appendix 5 Source code for automated module 384 tmp[3] = POSITIVE(tmp[3]); if(tmp[3] tmp[l]; tmp[0] -= 0.5 / tmp[4]) { tmp[4] = exp(a[l] * tmp[0]); il• = xo + tmp[4] * cos(tmp[2] - ORIENTATION * (tmp[0] - tmp[l] - tmp[3])); j l = yo + tmp[4] * sin(tmp[2] - ORIENTATION * (tmp[0] - tmp[l] - tmp[3])); pr_put(new_image, il, j l , 1); } b[0]*=exp(a[l]*tmp[3]); if(ORIENTATION>0){ tmp[3] = tmp[2] - c[var2 + 99]; tmp[3] = POSITIVE(tmp[3]); } else { tmp[3] = c[var2 + 99] - tmp[2]; tmp[3] = POSITIVE(tmp[3]); } tmp[4] = b[var2 + 99]; tmp[l] - log(b[var2 + 99]) / a[var2 + 99]; for (tmp[0] = tmp[l] - tmp[3]; tmp[0] < tmp[l]; tmp[0] += 0.5 / tmp[4]) { tmp[4] = exp(a[var2 + 99] * tmp[0]); il = xo + tmp[4] * cos(c[var2 + 99] - ORIENTATION * (tmp[0] - tmp[l])); j l = yo + tmp[4] * sin(c[var2 + 99] - ORIENTATION * (tmp[0] - tmp[l])); pr_put(new_image, il, j l , 1); } b[var2 + 99] /= exp(a[var2 + 99] * tmp[3]); if(ORIENTATION>0){ tmp[3] =c[100]-tmp[2]; tmp[3] = POSITIVE(tmp[3]); } else { tmp[3] = tmp[2]-c[100]; tmp[3] = POSITIVE(tmp[3]); } Appendix 5 Source code for automated module 385 tmp[4] = b[100]; tmp[l] = log(b[100])/a[101]; for (tmp[0] = tmp[l]; tmp[0] < tmp[l] + tmp[3]; tmp[0] += 0.5 / tmp[4]) { tmp[4] = exp(a[101] * tmp[0]); il = xo + tmp[4] * cos(c[100] - ORIENTATION * (tmp[0] - tmp[l])); j l = yo + tmp[4] * sin(c[100] - ORIENTATION * (tmp[0] - tmp[l])); pr_put(new_image, il, j l , 1); } b[100] *= exp(a[101] * tmp[3]); c[0] = c[100] = c[var2 + 99] = tmp[2]; for (i = 1; i < 2 * num_of_seg; i++) ox[i] = 0.0; for (i = 1; i < num_of_seg; i++) if (labelfij = -1 || label[i] > 0) { if (ORIENTATION > 0) tmp[0] = theta[seq[i]] - c[0]; else tmp[0] = c[0] - theta[seq[i]J; tmp[0] = POSITIVE(tmp[0]); tmp[l] = tmp[3] = 0.0; forO=l ; j tmp[0]) { tmp[0] -= tmp[l]; tmp[4] = b[j - 1] * exp(-a[j] * tmp[0]); if (tmp[4] < (r[2 * i] + r[2 * i - 1]) / 2) { ox[2 * i - 1] = tmp[4]; if(tmp[3]) ox[2 * i] = tmp[3]; break; } else { tmp[3]=tmp[4]; tmp[l]=tmp[2]-tmp[0]; tmp[0] = 2 * Pi; jO = tmp[l]/(2*Pi); if 00) for(jl = l ; j l<=j0 ; j l++){ tmp[4] = tmp[3] * exp(-a[j] * 2 * Pi); if (tmp[4] < (r[2 * i] + r[2 * i - 1]) / 2) { o x [ 2 * i - l] = tmp[4]; ox[2 * i] = tmp[3]; break; } else tmp[3] = tmp[4]; } Appendix 5 Source code for automated module 386 tmp[l]-=jO*2*Pi; } } else tmp[l]+=tmp[2]; } i f (ox[2* i - l ]&&!ox[2* i ] ){ if (ORIENTATION > 0) tmp[0] = theta[seq[i]] - c[100]; else tmp[0] = c[100] - theta[seq[i]]; tmp[0] = POSITIVE(tmp[0]); tmp[l] = 0.0; for (j = 101; j < 100 + var2; j++) { tmp[2]=log(b[j-l]/b[j])/a[j]; if (tmp[l] + tmp[2] > tmp[0]) { tmp[0]-=tmp[l]; ox[2 * i] = b[j -1] * exp(-a[j] * tmp[0]); break; } else tmp[l]+=tmp[2]; } if (ox[2 * i] < 0.9 * r[2 * i] && r[2 * i] - r[2 * i - 1] < (ox[2 * i] - ox[2 * i - 1]) / 2) ox[2 * i] = ox[2 * i - 1] = 0.0; } if (overlap(r[2 * i -1] , r[2 * i], ox[2 * i - 1], ox[2 * i]) < 0.5) ox[2 '* i] = ox[2 * i - 1] = 0.0; } for (i = 1; i < num_of_seg; i++) if (ox[2 * i]) for (j = i + 1; j < numofseg; j++) if(ox[2*j]){ if (ox[2 * rep[i] - 1] < ox[2 * repp] - 1]) { rep[0] = rep[i]; rep[i] = repp]; rep[j] = rep[0]; } } for (i = 1; i < num_of_seg; i++) if (ox[2 * rep[i]]) { for (j = 1; j < num_of_seg; j++) if (ox[2 * repp]] >= b[100] && ox[2 * repp] - 1] < 0.9 * ox[2 * repp] - 1]) { label[rep[j]] = 0; ox[2 * rep[j]] = ox[2 * repp] -1] = 0.0; } break; } Appendix 5 Source code for automated module 387 for (i = 100; i < 200; i++) n[i] = 0; fo r ( i= l ; i<200; i++) repp] = 0; for (i = 1; i < num_of_seg; i++) if (ox[2 * i]) { il = rep[0] = i; cl = l; iO = num_of_point[seq[i]] / 2; tmp[0] = r[2 * i - 1] * (exp(a[l] * Pi / 4.0) - 1.0); while (cl) { d[jl] = tmp[0]; for (j = 1; j < num_of_seg; j++) if (ox[2 * j] && num_pf_point[seq[j]] > iO && ox[2 * il -1] > ox[2 * j - 1] && ox[2 * il - 1] - ox[2 * j -1] < d[jl]) { d[jl] = ox[2 * il - 1] - ox[2 * j -1] ; rep[jl] = j ; } if(dQl] < tmp[0] && (jl < 2 || d[jl] > dfll -1] / 3 && dpi] < 3 * d[jl -1])) { il=rep[jl]; jl-H-I } elseif(jl >5) { tmp[l] = imageSize; tmp[2] = 0.0; forO = 0 ; j< j l ; j++){ if (ox[2 * rep[j] - 1] tmp[2]) { rep[901] = rep[j]; tmp[2] = ox[2 * rep[j] - 1]; } label[rep[j]] = 5; } tmp[3] = fabs(theta[seq[rep[901]]] - theta[seq[rep[900]]]); tmp[3] - LESSPI(tmp[3]); sigma = tmp[3] / (jl -1); c l = 0 ; } else break; } if(!cl) break; } Appendix 5 Source code for automated module 388 for (i = 1; i < num_of_seg; i++) if(label[i] = -l | | label[i]>0){ xo = ( r [ 2 * i ] - r [ 2 * i - l])/20.0; break; } n[l] = 0; for (i = 1; i < num_of_seg; i++) if (ox[2 * i]) { j0 = 0; tmp[0] = 6 * sigma; i f ( r [ 2 * i ] - r [ 2 * i - l ] > x o ) i 2 = l ; else i2 = 0; for (j = 1; j < num_of_seg; j++) if (j != i && ox[2 * j] && r[2 * j] - r[2 * j - 1] > (r[2 * i] - r[2 * i -1]) / 6.0 && overlap(r[2 * i -1 ] , r[2 * i], r[2 * j - 1], r[2 * j]) > 0.5) { if (r[2 * i] - r[2 * i - 1] > r[2 * j] - r[2 * j -1]) { tmp[2] = (r[2*j] + r [ 2 * j - l ] ) / 2 . 0 ; for(jl = 0;jl <= num_of_point[seq[i]];jl++) { x[l] = (newseg[seq[i]] - j l - l)->x; y[l] = (newseg[seq[i]] - j l - l)->y; tmp[3] = D(xo,yo,x[l],y[l]); if (fabs(tmp[3] - tmp[2]) < 2.0) { tmp[4] = atan2((double) y[l] - yo, (double) x[l] - xo); tmp[4] = POSITrVE(tmp[4]); tmp[4] = theta[seq[j]] - tmp[4]; tmp[4] = POSITrVE(tmp[4]); break; } } } else { tmp[2] = (r[2 * i] + r[2 * i - 1]) / 2.0; for (jl = 0; jl <= num_of_point[seq[j]]; jl++) { x[l] = (newseg[seq[j]] - j l - l)->x; y[l] = (newseg[seq[j]] - jl - l)->y; tmp[3]=D(xo,yo,x[l],y[l]); if (fabs(tmp[3] - tmp[2]) < 2.0) { tmp[4] = atan2((double) y[l] - yo, (double) x[l] - xo); tmp[4] = POSITIVE(tmp[4]); tmp[4] = tmp[4] - theta[seq[i]]; tmp[4] = POSITIVE(tmp[4]); break; } } Appendix 5 Source code for automated module 389 } if(tmp[4]0) neighbor [0][i] = jO; else n[l] = bright_nearby(i, -1, xo, yo, 0.8 * sigma, i2); } else n[l] = bright_nearby(i, -1, xo, yo, 0.8 * sigma, i2); j0 = 0; tmp[0] = 6 * sigma; for (j = 1; j < num_of_seg; j++) if 0 != i && ox[2 * j] && r[2 * j] - r[2 * j - 1] > (r[2 * i] - r[2 * i - 1]) / 6.0 && overlap(r[2 * i - 1], r[2 * i], r[2 * j - 1], r[2 * j]) > 0.5) { if (r[2 * i] - r[2 * i - 1] > r[2 * j] - r[2 * j - 1]) { tmp[2] = (r[2*j] + r [ 2 * j - l ] ) / 2 . 0 ; for (jl == 0; j 1 <=num_of_point[seq[i]];jl++) { x[l] = (newseg[seq[i]] - j l - l)->x; y[l] = (newseg[seq[i]j - j l - l)->y; tmp[3] = D(xo,yo,x[l],y[l]); if (fabs(tmp[3] - tmp[2]) < 2.0) { tmp[4] = atan2((double) y[l] - yo, (double) x[l] - xo); tmp[4] = POSITIVE(tmp[4]); tmp[4] = tmp[4] - theta[seq[j]]; tmp[4] = POSITIVE(tmp[4]); break; } } } else { tmp[2] = (r[2*i] + r [ 2 * i - l ] ) / 2 . 0 ; for (jl = 0; jl <= num_of_point[seqO]]; jl++) { x[l] = (newseg[seq[j]] - j l - l)->x; y[l] = (newseg[seq[j]] - j l - l)->y; tmp[3] = D(xo,yo,x[l],y[l]); if (fabs(tmp[3] - tmp[2]) < 2.0) { tmp[4] = atan2((double) y[l] - yo, (double) x[l] - xo); tmp[4] = POSITIVE(tmp[4]); tmp[4] = theta[seq[i]] - tmp[4]; tmp[4] = POSITIVE(tmp[4]); break; } Appendix 5 Source code for automated module 390 } } if(tmp[4]0) neighbor[l][i] =j0; else n[2] = bright_nearby(i, 1, xo, yo, 0.8 * sigma, i2); } else n[2] = bright_nearby(i, 1, xo, yo, 0.8 * sigma, i2); if (n[l] >= 0 && n[2] >= 0 && (n[2] - n[l] > 30 || i2 && n[2] > n[l])) labelfi] = 6; else if (n[l] >= 0 && n[2] >= 0 && (n[l] - n[2] > 30 || i2 && n[l] > n[2])) label[i] = 7; } ji = i; for (i = 1; i < num_of_seg; i++) if (labelp] > 5 && r[2 * i] - r[2 * i - 1] > 0.6 * (ox[2 * i] - ox[2 * i - 1]) && r[2 * i]-r[2 * i - 1] >38.0) { n[jl++] = i; if (jl > 150) break; } for (i = 0; i < 20; i++) d[i] = 0.0; for (i = 20; i < 40; i++) d[i] = -1.0; for (i = 280; i < 300; i++) n[i] = 0; f o r ( i = l ; i < j l ; i + + ) { tmp[2] = (ox[2 * n[i]] - ox[2 * n[i] - 1]) / 19.0; for (j = 0; j <= nurn_of_point[seq[n[i]]]; j++) { x[l] = (newseg[seq[n[i]]] - j - l)->x; y[l] = (newseg[seq[n[i]]] - j - l)->y; tmp[l]=D(xo,yo,x[l],y[l]); for(j0 = 0;j0<20;j0-H-) if (fabs(tmp[l] - ox[2 * n[i] - 1] - jO * tmp[2]) < 3.0) { d[20 + jO] = atan2((double) y[l] - yo, (double) x[l] - xo); d[20 + jO] = POSITIVE(d[20 + JO]); j += tmp[2] / 2.0; break; Appendix 5 Source code for automated module 391 } } tmp[0] = d[30]; for(j = 20;j<40;j-H-) if(dD]>=0.0){ d[j]-=tmp[0]; if(dD]>Pi) dD]-=2*Pi; else if (d[j] < -Pi) d[j] += 2 * Pi; d[j-20]+=dD]; n[260 + j]++; } for(j = 20;j<40;j++){ printf("j=%d d=%f ", j - 20, d[j]); d[j] = -1.0; } printfC \n"); } for (i = 0; i < 20; i++) if(n[280 + i]>2) d[i] /= n[280 + i]; else d[i] = 0.0; i l = - l ; for (i = 0; i < 20; i++) if (d[i] != 0.0) { i l = i ; break; } for(i = 0 ; i< i l ; i++) d[i] = d[il]; il = 20; for(i= 19; i > 9; i--) if(d[i] !=0.0){ i l = i ; break; } for(i = il + l ; i<20;i++) d[i] = d[il]; for (i = 20; i < 200; i++) d[i] = -1.0; for (i = 1; i < num_of_seg; i++) oy[i] = -1.0; for (i = 1; i < num_of_seg; i++) if (label[i] > 5) { Appendix 5 Source code for automated module 392 tmp[l] = (ox[2 * i] + ox[2 * i - 1]) / 2.0; if (tmp[l] >= r[2 * i - 1] && tmp[l] <= r[2 * i]) { for (j = 0; j <= num_of_point[seq[i]]; j++) { x[l] = (newseg[seq[i]j - j - l)->x; y[l] = (newseg[seq[T|] - j - l)->y; tmp[2]=D(xo,yo,x[l],y[l]); if (fabs(tmp[2] - tmp[l]) < 3.0) break; } oy[i] = atan2((double) y[l] - yo, (double) x[l] - xo); oy[i] = POSITIVE(oy[i]); } else { tmp[2] = (ox[2 * i] - ox[2 * i - 1]) / 20.0; for 01 = 0; j 1<= num_of_point[seq[i]]; j 1++) { x[l] = (newseg[seq[i]] - j l - l)->x; y[l] = (newseg[seq[ij] - j l - l)->y; tmp[l]=D(xo,yo,x[l],y[l]); for (il = 0; il < 20; il++) if (fabs(tmp[l] - ox[2 * i - 1] - il * tmp[2]) < 3.0) { d[20 + il] = atan2((double) y[l] - yo, (double) x[l] -xo); d[20 + il] = POSITIVE(d[20 + il]); j l += tmp[2] / sqrt(2.0); break; } } i l = 0 ; tmp[3] = 2 * Pi; tmp[4] = d[40] = 0.0; for(jl=20;jl<40;jl++) if(d[jl]>=0.0){ tmp[0] = dOl]-dD'l-20]; if (tmp[0] < 0.0) tmp[0] +=2* Pi; else if (tmp[0] > 2 * Pi) tmp[0] -= 2 * Pi; if(tmp[0]tmp[4]) tmp[4] = tmp[0]; d[40] += tmp[0]; il++; } if (il) { if(tmp[4]-tmp[3]=0.0){ tmp[O] = d01]-d[j l-2O]; if (tmp[0] < 0.0 || tmp[0] < Pi) tmp[0] += 2 * Pi; d[40] += tmp[0]; } d[40]/=il; d[40] = TWOPI(d[40]); oy[i] = d[40]; } } else { j l = 20 * ((r[2 * i] + r[2 * i - 1]) / 2.0 - ox[2 * i - 1]) / (ox[2 * i] - ox[2 * i - 1]); d[40]=theta[seq[i]]-d[jl]; i f (d[40]>2*Pi) d[40] -= 2 * Pi; else if (d[40] < 0.0) d[40] += 2 * Pi; oy[i] = d[40]; } for 01= 20; j l <40;jl++) dDl] = -1.0; } } for (i = 1; i < 2 * num_of_seg; i++) ox[i] = 0.0; for (i = 1; i < num_of_seg; i++) if (label[i] > 5) { if(ORIENTATION>0) tmp[0] = oy[i] - c[0]; else tmp[0] = c[0] - oy[i]; tmp[0] = POSITIVE(tmp[0]); tmp[l] = tmp[3] = 0.0; for (jj = 1; j < varl; j++) if (!ox[2 * i - 1]) { tmp[2] = log(bD-l]/bO])/aO]; if (tmp[l] + tmp[2] > tmp[0]) { tmp[0]-=tmp[l]; tmp[4] = b[j - 1] * exp(-a[j] * tmp[0]); if (tmp[4] < (r[2 * i] + r[2 * i - 1]) / 2) { o x [ 2 * i - l ] = tmp[4]; if(tmp[3]) ox[2 * i] = tmp[3]; Appendix 5 Source code for automated module 394 break; } else { tmp[3] = tmp[4]; tmp[l] = tmp[2] - tmp[0]; tmp[0] = 2 * Pi; jO = tmp[l] / (2*Pi) ; if(jO) for01 = l ; j l<=jO; j l++){ tmp[4] = tmp[3] * exp(-a[j] * 2 * Pi); if (tmp[4] < (r[2 * i] + r[2 * i - 1]) / 2) { ox[2 * i - 1] = tmp[4]; ox[2 * i] = tmp[3]; break; } else tmp[3] = tmp[4]; } tmp[l] -=j0 * 2 * Pi; } } else tmp[l]+=tmp[2]; } i f (ox [2* i - l ]&&!ox[2* i ] ){ if(ORffiNTATION>0) tmp[0] = oy[i] - c[100]; else tmp[0] = c[100]-oy[i]; tmp[0] = POSITIVE(tmp[0]); tmp[l] = 0.0; for (j = 101; j < 100 + var2; j++) { tmp[2] = log(bD'-l]/bO])/a(j]; if (tmp[l] + tmp[2] > tmp[0]) { tmp[0]-=tmp[l]; ox[2 * i] = b[j - 1] * exp(-a[j] * tmp[0]); break; } else tmp[l] += tmp[2]; } if (ox[2 * i] < 0.9 * r[2 * i]) ox[2*i] = b[100]; } if (overlap(r[2 * i - 1], r[2 * i], ox[2 * i - 1], ox[2 * i]) < 0.5) ox[2 * i] = ox[2 * i - 1] = 0.0; } for (i = 1; i < num_of_seg; i++) repp] = i; for (i = 1; i < numofseg; i++) Appendix 5 Source code for automated module 395 if(ox[2*i]) for (j = i + 1; j < num_of_seg; j++) if(ox[2*j]){ if (ox[2 * rep[i] - 1] < ox[2 * repp] - 1]) { rep[0] = repp]; rep[i] = repp]; repp] = rep[0]; } } for (i = 1; i < num_of_seg; i++) if(rep[i]!=i) for (j = 1; j < num_of_seg; j++) if(repp] = i) neighbor[0][i] = j ; for (i = 1; i < num_of_seg; i++) if (labelp] = 6 && r[2 * i] - r[2 * i - 1] > (ox[2 * i] - ox[2 * i - 1]) / 2.0) labelp] - 9; for (i = 1; i < numofjeg; i++) if(label[i] = 6){ i2 = 0; tmp[l] = (r[2*i] + r [ 2 * i - l ] ) / 2 ; tmp[2] = r[2 * i] - r[2 * i - 1]; tmp[0] = 2 * tmp[2] / tmp[l]; tmp[0] - MIN(tmp[0], 5 * sigma); for (j = i + 1; j < num_of_seg; j++) if (labelp] > 5 && r[2 * j] - r[2 * j - 1] > 0.25 * tmp[2] && overlap(r[2 * i - 1], r[2 * i], r[2 * j - 1], r[2 * j]) > 0.5) { tmp[3] = fabs(oy[i] - oyp]); tmp[3] = LESSPI(tmp[3]); if(tmp[3] 1) break; } if (i2 <2) for(j = i - l ; j > 0 ; j - ) if (labelp] > 5 && r[2 * j] - r[2 * j - 1] < 4 * tmp[2] && overlap(r[2 * i - 1], r[2 * i], r[2 * j - 1], r[2 * j]) > 0.5) { tmp[3] = fabs(oy[i] - oyp]); tmp[3] = LESSPI(tmp[3]); if(tmp[3] 1) break; } if* (i2 > 1) Appendix 5 Source code for automated module 396 label[i] = 8; } (cl) { c l = 0 ; for (i = 1; i < num_of_seg; i++) if (label[i] > 5 && label[i] != 7) { tmp[l] = MAX(xo, (ox[2 * i] - ox[2 * i - 1]) / 5.0); x[l] = (newseg[seq[i]] - l)->x; y[l] = (newseg[seq[i]j - l)->y; x[2] = (newseg[seq[i]] - num_of_point[seq[i]] - l)->x; y[2] = (newseg[seq[i]] - num_of_point[seq[i]] - l)->y; if(r[2*i]>D(xo,yo,x[2],y[2])){ x[3] = x[2]; y[3] = y[2]; x[2] = x[l]; y[2] = y[i]; x[l] = x[3]; y[i] = y[3]; } tmp[0] = atan2((double) y[2] - y[l], (double) x[2] - x[l]); tmp[0] = POSITIVE(tmp[0]); j l = 100; tmp[3] = r [ 2 * i - l ] ; tmp[4] = r[2*i]; for (j = 1; j < neighbor[0][i]; j++) if (label[rep[neighbor[0][i] - j]] > 5 && label[rep[neighbor[0][i] - j]] != 7) { if (num_of_point[seq[rep[neighbor[0][i] - j]]] < num_of_point[seq[i]] && overlap(r[2 * i - 1], r[2 * i], r[2 * rep[neighbor[0][i] - j] -1 ] , r[2 * rep[neighbor[0][i]-j]])<0.01){ x[3] = (newseg[seq[rep[neighbor[0][i] - j]]] - l)->x; y[3] = (newseg[seq[rep[neighbor[0][i] - j]]] - l)->y; x[4] = (newseg[seq[rep[neighbor[0][i] - j]]] -num_of_point[seq[rep[neighbor[0][i] -j]]] - l)->x; y[4] = (newseg[seq[rep[neighbor[0][i] - j]]] -num_of_point[seq[rep[neighbor[0][i] -j]]] - l)->y; if (r[2 * i] > r[2 * rep[neighbor[0][i] - j]]) { if (D(x[l], y[l], x[3], y[3]) < D(x[l], y[l], x[4], y[4])) tmp[5] = atan2((double) y[l] - y[3], (double) x[l] - x[3]); else tmp[5] = atan2((double) y[l] - y[4], (double) x[l] - x[4]); } else { if (D(x[2], y[2], x[3], y[3]) < D(x[2], y[2], x[4], y[4])) tmp[5] = atan2((double) y[2] - y[3], (double) x[2] - x[3]); else tmp[5] = atan2((double) y[2] - y[4], (double) x[2] - x[4]); Appendix 5 Source code for automated module 397 } tmp[5] = POSITIVE(tmp[5]); tmp[2] = fabs(tmp[5] - tmp[0]); tmp[2] = LESSPI(tmp[2]); if( tmp[2]<8* sigma) { r[2 * i] += (r[2 * rep[neighbor[0][i] - j]] - r[2 * rep[neighbor[0][i] - J ] - l ] ) /2 ; r[2 * i - 1] -= (r[2 * rep[neighbor[0][i] - j]] - r[2 * rep[neighbor[0][i]-j]-l])/2; if (label[i] < 8 && r[2 * i] - r[2 * i -1] > tmp[l]) label[i] = 8; if (label[i] > 7) { cl = l; label[rep[neighbor[0][i] - j]] = 1; } } } else break; } for (j = 1; j < num_of_seg - neighbor[0][i]; j++) if (label[rep[neighbor[0][i] + j]] > 5 && label[rep[neighbor[0][i] + j]] != 7) { if (num_of_point[seq[rep[neighbor[0][i] + j]]] < num_of_point[seq[ij] && overlap(r[2 * i - 1], r[2 * i], r[2 * rep[neighbor[0][i] + j] - 1], r[2 * rep[neighbor[0][i] + j]]) < 0.01) { x[3] = (newseg[seq[rep[neighbor[0][i] + j]]] - l)->x; y[3] = (newseg[seq[rep[neighbor[0][i] + j]]] - l)->y; x[4] = (newseg[seq[rep[neighbor[0][i] + j]]] -num_of_point[seq[rep[neighbor[0][i] + j]]] - l)->x; y[4] = (newseg[seq[rep[neighbor[0][i] + j]]] -num_of_point[seq[rep[neighbor[0][i] + j]]] - l)->y; if (r[2 * i] > r[2 * rep[neighbor[0][i] + j]]) { if (D(x[l], y[l], x[3], y[3]) tmp[l]) labelp] = 8; if(label[i]>7){ cl = l; label[rep[neighbor[0][i] + j]] = 1; } } } else break; } for (i = 1; i < num_of_seg; i++) if (label[i] = 6) { for (j = i + 1; j < num_of_seg; j++) if(label[j]==6&&ox[2*j- 1] < 1.1 * ox[2 * i - l ]&&ox[2 * j - 1] > 0.9 * ox[2 * i - 1] && overlap(tmp[3], tmp[4], r[2 * j - 1], r[2 * j])<0.1){ tmp[2] = fabs(oy[i] - oy[j]); tmp[2] = LESSPI(tmp[2]); if(tmp[2] tmp[l]) { label[i] = 8; r[2*i]=tmp[4]; r [2* i - l ]= tmp[3] ; for(il = 100;i l0) tmp[0] = LARGER(oy[rep[i]], tmp[2]); else tmp[0] = LARGER(tmp[2], oy[rep[i]]); if (tmp[0] < 3 * sigma) tmp[2] = oy[rep[i]]; else if (j0 > 7) { if(ORIENTATION>0) tmp[0] = LARGER(tmp[2], tmp[l]); else tmp[0] = LARGER(tmp[l], tmp[2]); printfC'sigmal=%f j0=%d\n", tmp[0] / (j0 - 1), jO - 1); tmp[l] = tmp[2] = oy[rep[i]]; J0=1 ; Appendix 5 Source code for automated module 400 } else { tmp[l] = tmp[2] = oy[rep[i]]; J0=1; } } } tmp[0] = 0.3 * sigma; for (i = 0; i < 15; i++) n[i] = 0; for (i = 1; i < numofseg; i++) if (label[rep[i]] = 9) for (j = i + 1; j < num_of_seg; j++) if (label[repD]] = 9) { tmp[l] = fabs(oy[rep[i]] - oy[rep[j]]); tmp[l]=LESSPI(tmp[l]); il = tmp[l] / tmp[0]; if (il > 14) il = 14; n[il]++; break; } printfC'W); n[15] = 0; for (i = 0; i < 14; i++) { if(n[i]>n[15]){ n[15] = n[i]; j = i; } } for (i = 1; i < num_of_seg; i++) if(label[rep[i]] = 9) for (j = i + 1; j < num_of_seg; j++) if(label[repQ]] = 9){ tmp[l] = fabs(oy[rep[i]] - oyfrepO]]); tmp[l]=LESSPI(tmp[l]); if (tmp[l] > 3.6 * sigma && tmp[l] < 5 * sigma) { label[rep[(i+j)/2]] = 9; oy[rep[(i + j) / 2]] = (oy[rep[i]] + oy[rep[j]]) / 2.0; ox[2 * rep[(i + j) / 2]] = sqrt(ox[2 * rep[i]] * ox[2 * rep[j]]); ox[2 * rep[(i + j) / 1 j - 1] = sqrt(ox[2 * rep[i] - 1] * ox[2 * rep[j] -1]); } break; } for (i = 1; i < num_of_seg; i++) if (label[rep[i]] = 9) { i0 = i; Appendix 5 Source code for automated module 401 break; } il = iO; j l = 0 ; for (i = iO + 1; i < num_of_seg; i++) if(label[rep[i]] = 9){ tmp[l] = fabs(oy[rep[i]] - oy[rep[il]]); tmp[l] = LESSPI(tmp[l]); for (j = i + 1; j < num_of_seg; j++) if(label[rep[j]] = 9){ break; } tmp[2] = fabs(oy[rep[i]] - oy[rep[j 1 ]]); tmp[2] = LESSPI(tmp[2]); if (tmp[l] < 3.6 * sigma && tmp[2] < 3.6 * sigma && (tmp[l] > 1.4 * tmp[2] || tmp[l] < 0.7 * tmp[2])) { if (fabs(oy[rep[il]] - oy[rep[jl]]) < Pi) oy[rep[i]] = (oy[rep[il]] + oy[rep[jl]]) / 2.0; else { oy[rep[i]] = (2 * Pi + oy[rep[il]] + oy[rep[jl]]) / 2.0; oy[rep[i]] = TWOPI(oy[rep[i]], 2 * Pi); } ox[2 * rep[i]] = sqrt(ox[2 * rep[il]] * ox[2 * rep[jl]]); ox[2 * rep[i] -1] = sqrt(ox[2 * repfil] - 1] * ox[2 * rep[jl] - 1]); i l = i = j l ; } else i l = i ; } i2=j0 = 0; for (i = 1; i < num_of_seg; i++) if(label[rep[i]] = 9){ tmp[l] = tmp[2] = oy[rep[i]]; break; } for (i = 1; i < num_of_seg; i++) if(label[rep[i]] = 9){ n[++j0] = rep[i]; if (ORIENTATION >0){ tmp[0] = LARGER(oy[rep[i]], tmp[l]); tmp = LARGER(oy[rep[i]], tmp[2]); } else { tmp[0] = LARGER(tmp[l], oy[rep[i]]); tmp = LARGER(tmp[2], oy[rep[i]]); } if (tmp < 4 * sigma && tmp[0] < Pi / 2) Appendix 5 Source code for automated module 402 tmp[2] = oy[rep[i]]; else if GO > 6) { if (ORIENTATION > 0) tmp = LARGER(tmp[2], tmp[l]); else tmp = LARGER(tmp[l], tmp[2]); tmp[3] = tmp / 00 - 2); tmp[2] = 0.0; i l = 0 ; for(j = 2;j0) tmp = LARGER(oy[nG]], oy[n[j -1]]); else tmp = LARGER(oy[n[j - 1]], oy[n[j]]); if(tmp>1.2*tmp[3]){ tmp[2] += tmp; il++; if (tmp[2] > (il + 0.9) * tmp[3] && i l < 5) { i0 = il + l; tmp[4] = log(ox[2 * n[j - il] -1] / ox[2 * n[j] - 1]) / tmp[2]; for(jl = l ; j l < i l ; j l + + ) { if (ORIENTATION > 0) { oy[n[j - j l ]] = oy[n[j]] - j l * tmp[2] / iO; oy[n[j - j l ]] = POSITIVE(oy[n[j -j l]]); } else { oy[nD - j l]] = oy[n[j]] + j l * tmp[2] /10; oy[n[j - j l]] = TWOPI(oy[n[j -jl]]); } ox[2 *n[j-j l]] = ox[2 * n[j]] * exp(tmp[4] * j l * tmp[2] / iO); ox[2 * n[j - j l] - 1] = ox[2 * n[j] - 1] * exp(tmp[4] * j l * tmp[2] / iO); } for(jl=il;jl 0) { oy[num_of_seg + i2] = oy[nfj]] - j l * tmp[2] / iO; oy[num_of_seg + i2] = POSITIVE(oy[num_of_seg + i2]); } else { oy[num_of_seg + i2] = oy[n[j]] + j l * tmp[2] / iO; oy[num_of_seg + i2] = TWOPI(oy[num_of_seg + i2]); } Appendix 5 Source code for automated module 403 ox[2 * (num_of_seg + i2)] = ox[2 * n[j]] * exp(tmp[4] * jl * tmp[2] / iO); ox[2 * (num_of_seg + i2) - 1] = ox[2 * n[j] - 1] * exp(tmp[4] * jl * tmp[2] / iO); } i l = 0 ; tmp[2] = 0.0; } } else { il = 0; tmp[2] = 0.0; } } tmp[l] = tmp[2] = oy[rep[i]]; n[l] = rep[i]; J 0 = 1 ; } else { tmp[l] = tmp[2] = oy[rep[i]]; n[l] = rep[i]; j 0 = l ; } } for (i = 1; i < num_of_seg + i2 + 1; i++) rep[i] = i; for (i = 1; i < num_of_seg + i2 + 1; i++) if(label[i] = 9) for (j = i + 1; j < num_of_seg + i2 + 1; j++) if (labeirj] = 9) { if (ox[2 * repp] - 1] < ox[2 * rep[j] - 1]) { rep[0] = rep[i]; rep[i] = rep[j]; repO] = rep[0]; } } j0 = 0; for (i = 1; i < num_of_seg + i2 + 1; i++) if(label[rep[i]] = 9){ if(!j0) tmp = 2 * sigma; else if (ORIENTATION > 0) tmp = LARGER(oy[rep[i]], tmp[3]); else tmp = LARGER(tmp[3], oy[rep[i]]); J0++; tmp[3] = oy[rep[i]]; tmp[l] = (ox[2 * rep[i]] - ox[2 * repp] - 1]) / 19.0; Appendix 5 Source code for automated module 404 for(j = 0;j<19;j++){ x[l] = xo + (ox[2 * rep[i] -1] + j * tmp[l]) * cos(oy[rep[i]] + d[j]); y[l] = yo + (ox[2 * repp] -1] + j * tmp[l]) * sin(oy[rep[i]] + d[j]); x[2] = xo + (ox[2 * repp] - 1] + (j + 1) * tmp[l]) * cos(oy[repp]] + dp + 1]); y[2] = yo + (ox[2 * repp] - 1] + (j + 1) * tmp[l]) * sin(oy[repp]] + dp + 1]); if (abs(y[2] - y[l]) > abs(x[2] - x[l])) { tmp[2] = (float) (x[2] - x[l]) / (y[2] - y[l]); if(y[2]>y[l]){ y[3] = y[i]; y[4] = y[2]; } else { y[3] = y[2]; y[4] = y[i]; } for(j l=y[3];j l<=y[4];j l++){ i l=x[2]+tmp[2]*01-y[2]) ; pr_put(new_image, il, j l , 1); } } else { tmp[2] = (float) (y[2] - y[l]) / (x[2] - x[l]); if(x[2]>x[l]){ x[3]=x[l]; x[4]=x[2]; } else { x[3]=x[2]; x[4]=x[l]; } for (il = x[3]; il <= x[4]; il++) { j l=y[2]+tmp[2]*( i l -x[2]) ; pr_put(new_image, il, j l , 1); } } /* fitting rib form */ static void regress(ox, oy) double { register int double double ox[], oy[]; UJi; a[6][100], r[6][6], sum[6], mean[6], s[6], partial[5][5], t[100]; Appendix 5 Source code for automated module 405 } for (i = 0; i < 6; i++) sum[i] = s[i] = coe[n[6]][i] = 0.0; for( i=l ; i<=n[5]; i++){ a[0][i] = oy[i]; sum[0] += a[0][i]; for(j = l ; j<6; j++){ aD][i] = pow(ox[i], (double) j); sum[j] += a[j][i]; } } for (i = 0; i < 6; i++) mean[i] = sum[i] / n[5]; for (i = 0; i < 6; i++) { forG = l;j<=n[5];j++) s[i] += sqr(a[i][j] - mean[i]); s[i] = sqrt(s[i]); } for (i = 0; i < 6; i++) for(j = i ; j<6;j++){ r[i]0] = 0.0; for01 = l; j l<=n[5];jl++) r[i]D] += (aplDl]" mean[i]) * (a[j][jl] - meanO]); r[i]0] /= (s[i] * sDl); rU][i] = r[i]0]; } for(i= l ; i<6; i++) for(j = l ; j<6; j++) partial[i-l]D-l] = r[i]G]; if (!invert(partial, 5)) fprintf(stdeiT, "Singular partial correlation matrix"); f o r ( i = l ; i < 6 ; i + + ) { for(j = l ; j<6; j++) coe[n[6]][i] += partialp - 1]0 - 1] * r[0]Q]; coe[n[6]][i] = coe[n[6]][i] * s[0] / s[i]; } coe[n[6]][0] = mean[0]; for(i= l;i<6;i-H-) coe[n[6]][0] -= coe[n[6]][i] * mean[i]; return; float invert(matrix, size) int size; double matrix[5][5]; { Appendix 5 Source code for automated module 406 int j , k, 1; double pivot, temp, det = 1.0; for G = 0; j< size; j++) { pivot = matrix[j][j]; det *= pivot; matrix[j][j] = 1.0; for (k = 0; k < size; k++) if (pivot) matrix[j][k] /= pivot; else return (0.0); for (k = 0; k < size; k++) if (k !=j) { temp = matrix[k][j]; matrix[k][j] = 0.0; for (1 = 0; 1< size; 1++) matrix[k][l] -= matrix[j][l] * temp; } } return ((float) det); } Appendix 6 Source code for Fourier analysis 407 Appendix 6 Source code for Fourier analysis There are 6 files in this program: fourier.h, fourier.c, canny.c, trace.c, kuhl.c, foote.c. 1. fourier.h /* * Header file for Fourier analysis * * Author: Bo Liang * Department of Geological Sciences * The University of British Columbia * Date: March 1991 * Modifications: April 1994 * */ #include #include #include #include #define MAX 100 /* maximum number of line segments allowed */ #define KUHL 0 #define FOOTE 1 #define CLOSE 8 /* tha maximum gap in a closed contour is 8 pixels */ #definePi 3.14159 #define sqr(i) ((double)(i)*(double)(i)) enum boolean { NO, YES }; struct point { short int x; short int y; short int z; } * segment [MAX]; /* hold points in line segments */ short seg_points[MAX]; /* number of points in each segment */ short numofseg ; /* the number of line segments in the image */ int outer; /* index for the outer contour */ Appendix 6 Source code for Fourier analysis 408 double *a, *b, *c, *d; /* fourier coefficients. */ Pixrect *outline_image; FILE *fo, *coef_data;; /* two different Fourier techniques */ /* elliptical fourier analysis, see Kuhl 1982 for detail */ void kuhl(int num_of_harmonic, int num_of_point); /* perimeter-based fourier analysis, see Foote 1989 for detail */ void foote(int num_of_harmonic, int num_of_point) 2. fourier.c #include "fourier.h" main(argc, argv) int argc; char *argv[]; { register int i, j , nrows, ncols; boolean option; int num_of_harmonic; FILE *fp; Pixrect *whorl_image; if (argc < 4) { fprintf(stderr, "Please specify a cross section file, a data file to host fourier coefficients and the output image file name"); exit(l); } fp = fopen(argv[l], V ) ; if ((whorlimage = pr_load(fp, colormap)) = NULL) { fprintf(stderr, "Can't open %s as image file", image_file); exit(2); } ncols = whorl_image->pr_size.x; nrows = whorl_image->pr_size.y; coefdata = fopen(argv[2], "w"); Appendix 6 Source code for Fourier analysis 409 outlineimage = mem_create(ncols, nrows, bpp); fo = fopen(image_out, "w"); if ((fo = fopen(argv[3], "w")) = NULL) { fprintf(stderr, "Can't open %s for output", argv[3]); exit(3); } printf("Please give the following parameters:\n"); printf(" 1. Number of harmonic: \n"); scanf("%d", &num_of_harmonic); printf("2. Elliptic (0) / Perimeter-based (1) \n"); scanf("%d", &option); /* use Canny edge detector to mark the outline of the whorl section */ edge_detect(whorl_image, outimage, ncols, nrows); /* group edge points into line contour */ trace_segment(ncols, nrows); /* * there are two contours due to the fact that whorl thickness > 1 * pixel, find the outer contour */ j = seg_points[0]; outer = 0; for (i = 0; i < num_of_seg; i++) { if (seg_points[i] > j) { j = seg_points[i]; outer = i; } } /* check the two end points of the contour, see whether it is closed */ j = sqrt(sqr((segment[outer] - l)->y - (segmentfouter] - seg_points[outer] - l)->y) + sqr((segment[outer] - l)->x - (segment[outer] - seg_points[outer] - l)->x)); if 0 > CLOSE) { fprintf(stderr, "the segment selected is not a closed contour\n"); exit(4); } if (! option) { fprintf(coef_data, "Elliptical Fourier coefficients for %s\n", argv[l]); kuhl(num_of_harmonic, seg_points[outer]); Appendix 6 Source code for Fourier analysis 410 } else { fprintf(coef_data, "Perimeter-based Fourier coefficients for %s\n", argv[l]); foote(num_of_harmonic, seg_points[outer]); } fclose(coefdata); pr_dump(outline_image, fo, NULL, RTSTANDARD, 1); pr_close(whorl_image); pr_close(outline_image); exit(0); } 3. canny.c provided by Department of Computer Science, UBC. 4. trace.c same as in Appendix 5. 5. kuhl.c /* perform elliptical fourier analysis for images of whorl cross sections * the whorl image must be a single closed contour to proceed; based on a * paper by Kuhl & Giardina 1982 */ #include "fourier. h" extern void kuhl(num_of_harmonic, num_of_point) int numofjiarmonic, num_of_point; { register int i, j , n, ymax, ymin; int p[3], xo, yo, xx, yy; boolean cont; float sigfact; /* significance factor for whorl flank */ double *x[2], *y[2], *len, x_sum[2], y_sum[2]; double *aa, *bb, *cc, *dd; /* fourier coef. with * normalization */ double 0, cp, sigma[2], tmp[2]; /* allocate memory for x, y and len */ x[0] = (double) malloc((num_of_point + 1) * sizeof(double)); y[0] = (double) malloc((num_of_point + 1) * sizeof(double)); Appendix 6 Source code for Fourier analysis 411 x[l] = (double) malloc((num_of_point + 1) * sizeof(double)); y[l] = (double) malloc((num_of_point + 1) * sizeof(double)); len = (double) malloc((num_of_point + 1) * sizeof(double)); /* * read coords of points in whorl outline segment into x[0], y[0]; * len[i] is the curve length at point i; */ len[0] = 0.0; x[0][l] = (segment[outer] - l)->x; y[0][l] = ymin = ymax = (segmentfouter] - l)->y; x_sum[0] = x[0][l]; y_sum[0] = y[0][l]; for (i = 2; i <= num_of_point + 1; i++) { x[0][i] = (segmentfouter] - i)->x; y[0][i] = (segmentfouter] - i)->y; if(y[0][i]ymax) ymax = y[0][i]; len[i - 1] = len[i - 2] + sqrt(sqr(y[0][i] - y[0][i - 1]) + sqr(x[0][i] - x[0][i - 1])); x_sum[0]+=x[0][i]; y_sum[0] += y[0][i]; /* approximate venter shoulder with two points p[l], p[2] */ cont = YES; for (i = 1; i <= num_of_point + 1; i++) { if (cont && y[0][i] < ymin + (ymax - ymin) / 10.0) { p[l] = i; cont = NO; } if (cont = NO && y[0][i] > ymin + (ymax - ymin) /10.0) { p[2] = i; break; } } /* compute the raw fourier coefficients */ for (i = 1; i < numofharmonic; i++) { a[i] = b[i] = c[i] = d[i] = 0.0; for (j = 1; j <= num_of_point; j++) { sigma[0] = 2 * Pi * i * lenjj] / len[num_of_point]; Appendix 6 Source code for Fourier analysis 412 sigma[l] = 2 * Pi * i * len[j - 1] / len[num_of_point]; a[i] += (x[0][j + 1] - x[0][j]) * (cos(sigma[0]) - cos(sigma[l])) / (len[j]-len|j-l]); b[i] += (x[0][j + 1] - x[0][j]) * (sin(sigma[0]) - sin(sigma[l])) / (lenG]-len[j-l]); c[i] += (y[0][j + 1] - y[0]G]) * (cos(sigma[0]) - cos(sigma[l])) / (lenQ] - lenD -1]); d[i] += (y[0][j + 1] - y[0][j]) * (sin(sigma[0]) - sin(sigma[l])) / (lenU]-len[j-l]); } a[i] *= len[num_of_point] / (2 * i * i * Pi * Pi); b[i] *= len[num_of_point] / (2 * i * i * Pi * Pi); c[i] *= len[num_of_point] / (2 * i * i * Pi * Pi); d[i] *= len[num_of_point] / (2 * i * i * Pi * Pi); /* normalize fourier coefficients */ 9 = atan2(2 * (a[l] * b[l] + c[l] * d[l]), (a[l] * a[l] + c[l] * c[l] -b [ l ]*b[ l ] -d [ l ]*d[ l ] ) ) ; if(0 <0.0) 9 += 2 * Pi; 0 = 0 / 2 . 0 ; tmp[0] = a[l] * cos(9) + b[l] * sin(0); tmp[l] = c[l] * cos(0) + d[l] * sin(0); cp = atan2(tmp[0], tmp[l]); if (cp < 0.0)

x; yo = (segmentfouter] - l)->y; a[0] = xo * cos(cp) - yo * sin(cp) - x[l][l]; c[0] = xo * sin(cp) + yo * cos(cp) - y[l][l]; /* give different significance for venter and flank */ x_sum[l] = 0; y_sum[l] = 0; for (i = 1; i <= num_of_point; i++) { x[l][i] = a[0]; y[l][i] = c[0]; for (j = 1; j < numofharmonic; j++) { sigma[0] = 2 * Pi * (len[i] - tmp[0]) * j / len[num_of_point]; x[l][i] + = a0J * cos(sigma[0]) + b[j] * sin(sigma[0]); y[l][i] += c[j] * cos(sigma[0]) + d[j] * sin(sigma[0]); } x_sum[l] += x[l][i] * cos(cp) - y[l][i] * sin(cp); y_sum[l] += x[l][i] * sin(cp) + y[l][i] * cos(cp); } xo = -x_sum[l] / num_of_point + x_sum[0] / (num_of_point + 1); yo - -y_sum[l] / num_of_point + y_sum[0] / (num_of_point +1); x_sum[0] = y_sum[0] = 0; sigfact = num_of_point / (4 * (p[2] - p[l])); for (i = 1; i <= num_of__point; i++) { tmp[l] = (x[0][i] - xo) * cos(cp) + (y[0][i] - yo) * sin(cp); y[0][i] = -(x[0][i] - xo) * sin((p) + (y[0][i] - yo) * cos(cp); x[0][i] = tmp[l]; i f ( i>p[ l ]&&i 1; j—) { if(fabs(a[j])>0.0){ x_sum[l] = 0.0; for (i = 1; i <= num_of_point; i++) { sigma[0] = 2 * Pi * (len[i] - tmp[l]) * j / len[num_of_point]; if (i > p[l] && i < p[2]) x_sum[l] += sigfact * fabs(x[l][i] - a[j] * cos(sigma[0]) - x[0][i]); else x_sum[l] += fabs(x[l][i] - a[j] * cos(sigma[0]) - x[0][i]); } if (fabs(tmp[l]) > x_sum[l]) { tmp[l] = x_sum[l]; /* contribution by a[n] */ n = j ; } } if(fabs(b[j])>0.0){ x_sum[l] = 0.0; for (i = 1; i <= num_of_point; i++) { sigma[0] = 2 * Pi * (len[i] - tmp[0]) * j / len[num_of_point]; if (i > p[l] && i < p[2]) x_sum[l] += sigfact * fabs(x[l][i] - b[j] * sin(sigma[0]) - x[0][i]); else x_sum[l] += fabs(x[l][i] - b[j] * sin(sigma[0]) -x[0][i]); } if (fabs(tmp[l]) > x_sum[l]) { tmp[l] = -x_sum[l]; /* contribution by b[n] */ n = j ; } } } if (fabs(tmp[l]) < 1.5 * x_sum[0]) { /* not siginificant */ if(tmp[l] >0) { for (i = 1; i <= num_of_point; i++) Appendix 6 Source code for Fourier analysis 415 x[l][i] -= a[n] * cos(2 * Pi * (len[i] - tmp[0]) * n / len[num_of_point]); /* re-compute x after * eliminating a[n] */ a[n] = 0; } else { for (i = 1; i <= num_of_point; i++) x[l][i] -= b[n] * sin(2 * Pi * (len[i] - tmp[0]) * n / len[num_of_point]); /* re-compute x after * eliminating b[n] */ b[n] = 0; } } else cont = NO; } cont = YES; while (cont) { tmp[l] = 100 * y_sum[0]; for (j = numofjmrmonic - 1 ; j > 1; j—) { if(fabs(cO])>0.0){ y_sum[l] = 0.0; for (i = 1; i <= num_of_point; i++) { sigma[0] = 2 * Pi * (len[i] - tmp[0]) * j / len[num_of_point]; if (i > p[l] && i < p[2]) y_sum[l] += sigfact * fabs(y[l][i] - c[j] * cos(sigma[0]) - y[0][i]); else y_sum[l] += fabs(y[l][i] - c[j] * cos(sigma[0]) -y[0][i]); } if (fabs(tmp[l]) > y_sum[l]) { tmp[l] = y_sum[l]; /* contribution by c[n] */ n = j ; } } if(fabs(d[j])>0.0){ y_sum[l] = 0.0; for (i = 1; i <= num_of_point; i++) { sigma[0] = 2 * Pi * (len[i] - tmp[0]) * j / len[num_of_point]; i f ( i>p[ l ]&&i y_sum[l]) { tmp[l] = -y_sum[l]; /* contribution by d[n] */ n = j ; } } } if (fabs(tmp[l]) < 1.5 * y_sum[0]) { /* not siginificant */ if( tmp[l]>0){ for (i = 1; i <= num_ofjpoint; i++) y[l][i] -= c[n] * cos(2 * Pi * (len[i] - tmp[0]) * n / len[num_of_point]); /* re-compute y after * eliminating c[n] */ c[n] = 0; } else { for (i = 1; i <= num_of_point; i++) y[l][i] -= d[n] * sin(2 * Pi * (len[i] - tmp[0]) * n / len[num_of_point]); /* re-compute y after * eliminating d[n] */ d[n] = 0; } } else cont = NO; } } /* save normalized Fourier coefficients */ b[l] = c[l] = 0; /* TRUE if Fourier coefficients has been * normalized */ fprintf(coef_data, "A0=%f C0=%f\n", xo, yo); for (i = 1; i < num_of_harmonic; i++) { if (fabs(a[i]) > 0.0 || fabs(b[i]) > 0.0 || fabs(c[i]) > 0.0 || fabs(d[i]) > 0.0) { fprintf(coef_data, "harmonic%d ", i); if(fabs(a[i])>0.0) fprintf(coef_data," a=%f", a[i] /magnitude); if(fabs(b[i])>0.0) fprintf(coef_data," b=%f", b[i] / magnitude); if(fabs(c[i])>0.0) fprintf(coef_data," c=%f", c[i] / magnitude); if(fabs(d[i])>0.0) Appendix 6 Source code for Fourier analysis 417 fprintf(coef_data, " d=%f", d[i] / magnitude); fprintf(coef_data, " \n"); } } /* plot Fourier Rep of whorl in outlineimage */ for (i = 1; i <= num_of_point; i++) { x[l][i] = a[0]; y[l][i] = c[0]; for (j = 1; j < num_of_harmonic; j++) { sigma[0] = 2 * Pi * (len[i] - tmp[0]) * j / len[num_of_point]; x[l][i] + = a01 * cos(sigma[0]) + by] * sin(sigma[0]); y[l][i] += cO] * cos(sigma[0]) + d[j] * sin(sigma[0]); } xx = x[l][i] * cos(cp) - y[l][i] * sin(cp) + xo; yy = x[l][i] * sin(cp) + y[l][i] * cos(cp) + yo; pr_put(outline_image, xx, yy, 1); free(x[0]); free(x[l]); free(y[0]); free(y[l]); free(len); } 6. footcc /* perform perimeter-based fourier analysis for images of whorl cross sections * the whorl image must be a single closed contour to proceed; based on a * paper by Foote 1989 */ #include "fourier. h" foote(num_of_harmonic, num_of_point) int numofharmonic, num_of_point; { register int i, j , ymin, ymax, int x, y, xo, yo, p[3]; double *r, *8, *len; double sigma[2], cp, rr,; /* allocate memory for r, s, and len */ r = (double) malloc((num_of_point + 1) * sizeof(double)); Appendix 6 Source code for Fourier analysis 418 9 = (double) malloc((num_of_point + 1) * sizeof(double)); len = (double) malloc((num_of_point + 1) * sizeof(double)); /* locate the geometric center of the whorl section */ ymin = (segment[outer] - l)->y; ymax = (segment [outer] - l)->y; for (i = 2; i < num_of_point / 2; i++) { j = (segment[outer] - i)->y; if(j >ymax) { p[0] = i; /* lowest point at umbilical shoulder */ ymax- j ; } else if (j y; for (i = numofjpoint - 1; i > num_of_point / 2; i~) { j = (segment[outer] - i)->y; if (j > ymax) { p[2] = i; /* lowest point at umbilical shoulder */ ymax=j; } else if (y < ymin) { p[l] = i; ymin=j; } } xo = ((segment[outer] - p[l])->x + ((segment[outer] - p[0])->x + (segment[outer] - p[2])->x) / 2) / 2; yo = ((segment[outer] - p[l])->y + ((segmentfouter] - p[2])->y + (segmentfouter] - p[l])->y) 12)12; /* convert from x-y coord to r-s system, start from p[0] */ len[0] = 0.0; j = i; for (i = p[0]; i >= l ; i - ) { x = (segment[outer] - i)->x; y = (segment[outer] - i)->y; r[j] = sqrt(sqr(y - yo) + sqr(x - xo)); len[j] = len[j - 1] + sqrt(sqr(y - (segment[outer] - i - l)->y) + sqr(x -(segment[outer] - i - l)->x)); if(y = yo){ if (x> xo) eo] = o.o; Appendix 6 Source code for Fourier analysis 419 else 9D] = -Pi; } else 0[j] = atan2((double) y - yo, (double) x - xo); } for (i = num_of_point - 1; i >= p[2]; i~) { x = (segment[outer] - i)->x; y = (segment[outer] - i)->y; r[j] = sqrt(sqr(y - yo) + sqr(x - xo)); len[j] = len[j -1] + sqrt(sqr(y - (segment[outer] - i - l)->y) + sqr(x - (segment[outer] - i - l)->x)); if(y = yo){ if(x>xo) eo] = o.o; else 0[j] = -Pi; } else 0[j] = atan2((double) y - yo, (double) x - xo); } /* normalize r and 0 */ num_of_point = j - 1; sigma[l] = 2 * Pi - fabs(0[l] - 0[num_of_point]); magnitude = len[num_of_point] / sigma[l]; sigma[0] = 0[1]; if(sigma[0]-Pi/2){ for (i = 1; i <= num_of_point; i++) { r[i] = r[i] / magnitude; if (0[i] - sigma[0] >= 0.0) 0[i] = 0[i] - sigma[0] - len[i] * sigma[l] / len[num_of_point]; else 0[i] = 2 * Pi + 0[i] - sigma[0] - len[i] * sigma[l] / len[num_of_point]; } } else { for (i = 1; i <= num_of_point; i++) { r[i] = r[i] / magnitude; if(-0[i] + sigma[O]>=O.O) 0[i] = -0[i] + sigma[0] - len[ij * sigma[l] / len[num_of_point]; else Appendix 6 Source code for Fourier analysis 420 6[i] = 2 * Pi - 9[i] + sigma[0] - len[i] * sigma[l] / len[num_of_point]; } } /* compute Fourier coefficients */ for (i = 0; i < numofharmonic; i++) { a[i]=b[i]=c[i] = d[i] = 0.0; for (j = 1; j <= num_of_point; j++) { a[i] + = r0] * c o s ( 2 * Pi * i * len[j] / (double) len[num_of_point]); b[i] += rD] * sin(2 * Pi * i * len[j] / (double) len[num_of_point]); c[i] += 60] * cos(2 * Pi * i * len[j] / (double) len[num_of_point]); dp] += 6[j] * sin(2 * Pi * i * len[j] / (double) len[num_ofjpoint]); } a[i] = 2 * a[i] / (double) len[num_of_point]; b[i] = 2 * b[i] / (double) len[num_of_point]; c[i] = 2 * c[i] / (double) len[num_of_point]; d[i] = 2 * d[i] / (double) len[num_of_point]; } /* plot simulated whorl using Fourier Rep. */ for (i = 1; i <= num_of_point; i++) { rr = a[0] / 2.0; cp = c[0] / 2.0; for (j = 1; j < num_of_harmonic; j++) { rr += ap] * cos(2 * Pi * len[i] * j / (double) len[num_of_point]) + bO] * sin(2 * Pi * len[i] * j / (double) len[num_of_point]); (p += c[j] * cos(2 * Pi * len[i] * j / (double) len[num_of_point]) + d[j] * sin(2 * Pi * len[i] * j / (double) len[num_of_point]); } if(sigma[l]-Pi/2){ x = magnitude * rr * cos((double) (p + len[i] * sigma[l] / len[num_of_point] + sigma[0]) + xo; y = magnitude * rr * sin((double) cp + len[i] * sigma[l] / len[num_of_point] + sigma[0]) + yo; } else { x = magnitude * rr * cos((double) sigma[0] - (p - len[i] * sigma[l] / len[num_of_point]) + xo; y = magnitude * rr * sin((double) sigma[0] - cp - len[i] * sigma[l] / len[num_of_point]) + yo; } pr_put(image_out, x + 20, y + 20, 1); } Appendix 6 Source code for Fourier analysis 421 free(r); free(s); free(len); Appendix 7 Source code for simulation of whorl shape change 422 Appendix 7 Source code for the animation of whorl shape changes This is a simple whorl shape change simulation program. /* This program is used to interpolate or extrapolate sequence of whorl shape */ #include #include #include #defineMAXCOEF 100 #defineNUMPOINT 2000 #definePI 3.14159 #define INTP 4 /* number of steps during interpolation */ #define EXTP 8 /* number of steps during exterpolation */ enum boolean { NO, YES }; struct rect { int originx; int origin_y; int width; int height; } disp_rect = {50, 50, 600, 600 }; double *a[MAXCOEF], *b[MAXCOEF], *c[MAXCOEF], *d[MAXCOEF]; double x[NUMPOINT], y[NUMPOINT]; main(argc, argv) int argc; char *argv[]; { register int i, j ; int num_of_section, numofharmonic; boolean option, cont; FILE *coef_data; Pixrect *whorl_section, *scrn; if (argc < 2) { fprintf^stderr, "Please specify the Fourier coefficient data file."); exit(l); } if ((coef_data = fopen(argv[l], V) ) = NULL) { printf(stderr, "Can't open%s", argv[l]); Appendix 7 Source code for simulation of whorl shape change 423 exit(l); } fscanf(coef_data, "%d", &num_of_section); fscanf(coef_data, "%d", &i); numofharmonic = i / 4;/* each harmonic has a, b, c, d components */ /* allocate memory to host the fourier coefficients */ for (i = 0; i < num_of_section; i++) { a[i] = (double *) malloc(4 * (num_of_harmonic + 1) * sizeof(double)); b[i] = (double *) malloc(4 * (num_of_harmonic + 1) * sizeof(double)); c[i] = (double *) malloc(4 * (num_of_harmonic + 1) * sizeof(double)); d[i] = (double *) malloc(4 * (num_of_harmonic + 1) * sizeof(double)); } /* prepare screen for display */ who rlsection = mem_create(disp_rect. width, disp_rect.height, 1); scrn = pr_open("/dev/fb"); /* load Fourier coefficients */ for (i = 1; i <= num_of_section; i++) /* reserve i = 0 as buffer */ for (j = 0; j < num_of_harmonic; j++) fscanf(coef_data, "%f %f %f %f", &a[i]G], &b[i][j], &c[i]|j], &d[i][j]); cont = YES; while (cont) { printf("visualize the whole sequence(0)/use two sections for extrapolation (1)"); scanf("%d", &option); if (option) extrapolate(num_of_harmonic, num_of_section); else interpolate(num_of_harmonic, numofsection); } prclose(scrn); } static void extrapolate(num_of_harmonic, num_of_section) int numofharmonic, numofsection { register int i, j ; Appendix 7 Source code for simulation of whorl shape change 424 int section[2]; printf("Which part of the sequence you want to see? i.e. 4,5. l-%d\n", num_of_section); scanfC'%d", §ion[0]); scanf("%d", §ion[l]); /* * section[l] > section[0], extrapolate forward; sectionfl] INTP for extrapolation */ for (i = 0; i <= EXTP; i++) { for (j = 0; j < num_of_harmonic; j-H-) { a[0][j] = a[section[0]][j] + i * (a[section[l]][j] -a[section[0]][j]) / INTP; b[0]D] = b[section[0]]G] + i * (b[section[l]][j] -b[section[0]][j]) / INTP; c[O]0] = c[section[0]][j] + i * (c[section[l]][j] -c[section[0]][j]) / INTP; d[O]0] = d[section[0]][j] + i * (d[section[l]][j] -d[section[0]][j]) / INTP; } /* compute x, y of the Fourier Rep of the whorl section */ compute_fourier(num_of_harmonic); display(x, y, i); } } static void interpolate(num_of_harmonic, num_of_section) int numofjiarmonic, numofsection { register int i, j , k; for (i = 1; i < numofsection; i++) for (k = 0; k < INTP; k++) { for (j = 0; j < numofharmonic; j++) { Appendix 7 Source code for simulation of whorl shape change 425 a[O]0] = a[i][j] + k * (a[i + 1]D] - a[i]D]) / INTP; b[0]D] = b[i]D] + k * (b[i + l][j] - b[i][j]) / INTP; c[0]D] = c[i]Q] + k * (c[i + 1]0] - c[i][j]) / INTP; d[0]D] = d[i][j] + k * (d[i + 1]Q] - d[i]Dl) / INTP; /* compute x, y of the Fourier Rep of the whorl section */ compute_fourier(num_of_harmonic); display(x, y, k); } static void compute_fourier(num_of_harmonic) int numofharmonic { register int i, j ; double tp; for (i = 1; i < NUMPOINT; i++) { x[i] = 0.0; y[i] = 0.0; tp - tp; for (j = 1; j < num_of_harmonic + 1; j++) { x[i] += a[0][j - 1] * cos(tp) + b[O]0 - 1] * sin(tp); y[i] += c[0][j - 1] * cos(tp) + d[0][j - 1] * sin(tp); } } } static void display(x, y, order_in_sequence) int x[], y[], orderinsequence; { register int i, j ; register int xmin, xmax, ymin, ymax, /* determine the dimention of the * whorl section */ xmin = xmax = x[l]; ymin = ymax = y[l]; for (j = 2; j < NUMPOINT; j++) { if (xmin > x[j]) xmin = x[j]; if(xmaxy[j]) ymin = y[j]; if(ymax (ymax - ymin) ? (xmax - xmin) : (ymax - ymin); scale /= displrect. width; } for (j = 1; j < NUMPOINT; j++) { x[j] = (x[j] - xmin) / scale; y[j] = (yDl - ymin) / scale; pr_put(whorl_section, (int) x(j], (int) y[j], 1); } pr_rop(scrn, disp_rect.orig_x, disp_rect.orig_y, displ_rect. width, displrect. height, PIX_SRC, whorl_section, 0, 0); } }