• No results found

Modularitet och objektorientering

N/A
N/A
Protected

Academic year: 2021

Share "Modularitet och objektorientering"

Copied!
73
0
0

Loading.... (view fulltext now)

Full text

(1)

Uppsala universitet

Institutionen för informatik och media

Modularitet och objektorientering

Byggandet av ett program som kan visa en molekyl

Lars Tedenborg

(2)

Abstract

The development of IT systems is usually accomplished by some form of system development methodology. It can be performed as the waterfall method, where each phase is completed before the next begins. One of the reasons to follow a development methodology is that the process is more structured, faster and that the product will have higher quality. One risk of not using a system development approach is that the code can be unstructured and difficult to maintain.

This paper describes an alternative method in which the development occurred without the use of any system development methodology. This has been possible because there was a clear goal of the program that should be developed. The goal was to read a molfile and from the

(3)

Sammanfattning

Vid utveckling av IT-system brukar någon form av systemutvecklingsmetod följas. Det kan vara exempelvis vattenfallsmetoden där varje fas slutförs innan nästa påbörjas. Ett av skälen att följa en utvecklingsmetod är att arbetet ska bli mer strukturerat, gå fortare samt att produkten ska ha hög kvalité. En risk med att inte använda en systemutvecklingsmetod är att koden kan bli ostrukturerad och svår att underhålla.

Denna uppsats beskriver en alternativ metod där utvecklingen skett utan användandet av någon etablerad systemutvecklingsmetod. Det var möjligt då det fanns ett tydligt mål med programmet som skulle utvecklas. Målet var att läsa en molfil och från den information som finns lagrad i filen rita molekylärstrukturen. Utseendet på molekylen har finjusterats allteftersom fler egenskaper lagts till programmet. En molfil har möjlighet att lagra all information om de olika egenskaper en

molekyl kan ha. Alla molekyler innehåller inte alla egenskaper.

(4)

Innehållsförteckning

Abstract ... 2 Sammanfattning ... 3 Innehållsförteckning ... 4 Ordlista ... 5 Inledning ... 6 Problemformulering ... 6 Syfte ... 8 Bakgrund ... 9 Avgränsning ... 12

Hur en molfil är uppbyggd ... 12

Metod ... 15

Undersökningsstrategi ... 15

Teori ... 17

Utveckling av programmkod ... 17

Analys och diskussion ... 31

Slutsatser ... 32

Källförteckning ... 33

Elektroniska källor ... 33

Bilaga 1 lista över program för att rita molekyler ... 34

Bilaga 2 CTFilen från Symyx som beskriver hur en molfil är uppbyggd ... 35

(5)

Ordlista

Acyklisk En struktur som inte innehåller någon cykliskt element.

Agil systemutveckling Metod för programmering, med korta utvecklingscykler med nära kontakt mellan utvecklare och beställare.

http://www.agilemanifesto.org/iso/sv/

Cyklisk En struktur som innehåller ett cykliskt element.

Deprotonerad Heteroatom som saknar ett väte och därmed har laddningen -1. Eter En syreatom som binder två olika kolatomer.

Generisk struktur Struktur där vissa delar inte är fullständigt specificerade, utan de kan innehålla olika atomer eller fragment.

Heteroatom Atom som inte är kol eller väte.

Isotop Atomer av samma grundämne, alltså med samma antal protoner, men med olika antal neutroner.

InChi filformat IUPAC standard för lagring av molekylär information. (http://www.iupac.org/inchi/)

Kiral En atoms möjlighet att vara asymmetrisk. Bindningar från atomen kan peka åt olika håll i tre dimensioner.

Konformation En molekyls utseende vid en viss tidpunkt vilket påverkas av molekylens rörlighet i dess bindningar.

Masstal Summan av antalet protoner och neutroner.

Molekyl När atomer sitter ihop i ett visst arrangemang tack vare bindningar. Molfil Ett filformat utvecklat av MDL som blivit en inofficiell standard för

lagring av molekylär struktur information.

Radikaler Atom som inte har tillräckligt med elektroner runt sig.

Stereokemi Förtydligande av hur bindningarna pekar om en atom är kiral. SMILES fil format Simple Molecular Input Line Entry System. Filformat för att lagra

(6)

Inledning

Contur Software AB var i behov av ett dataprogram vars uppgift var att rita en molekylstruktur från en lagrad molfil. Den utritade molekylen skulle visas upp som en bild. Redan vid projektets början sågs ett flertal problem med hur kraven för programmet skulle formuleras. Då det är en bild som ska visas upp finns det en estetisk parameter att ta hänsyn till under utvecklingen. Det är svårt att ge specifika krav beträffande hur alla molekylens egenskaper ska anges, när de olika delarnas utseende i en molekyl påverkar varandra. Därför utvecklades programmet utan någon form av föregående systemanalys, förutom ett begränsat antal funktionskrav. Här används begreppet systemanalys som benämning på den dokumenterade kravspecifikation som normalt föregår programmering. I molfilen finns alla molekylens egenskaper beskriva och utvecklingen gick till så att en egenskap i sänder implementerades.

Denna uppsats kommer att beskriva hur man kan bygga ett datorprogram genom att lägga till en liten funktion i taget, förutsatt att programmeraren kan bedöma resultatet. I detta fall har utvecklaren utbildning i kemi. Molekylen delas alltså upp i ett flertal moduler som en efter en lagts till i programmet. Detta har varit möjligt genom att strikt använda ett objektorienterat synsätt.

Problemformulering

Den mest rigida formen av systemutveckling är vattenfallsmodellen(Royce 1970). Denna metod är ett bra exempel på systemutveckling då varje fas är isolerad och dokumenteras innan nästa fas tar vid. Jag använder den som exempel för att förklara alla faser som ett

systemutvecklingsprojekt normalt har. Varje fas slutar med ett beslut, ska projektet fortsätta eller avslutas. Vattenfallsmodellen består av följande faser:

1. Planering eller förstudie. Man kan också kalla denna fas behovsstudie. Den ska leverera argument för eller emot den fortsatta utvecklingen av IT-systemet.

2. Analysfas. Vad är det systemet ska utföra?

3. Design. Här utvecklas kod och arbetsprocesserna förändras för att passa det nya IT-systemet.

4. Testning. Blev produkten rätt?

5. Driftsättning. Systemet sätts i drift och allt levereras till användarna. 6. Underhåll. Lägga till nya funktioner. Fixa buggar. Förvalta systemet.

(7)

Alternativt till den strukturerade vattenfallsmetoden är Rapid Application Development (RAD) metoderna (Dennis et al 2006). Dessa metoder adresserar den långa utvecklingstiden innan en första fungerade produkt kan testas av användaren. Det uppnås genom att enbart utveckla ett fåtal funktioner i systemet från början, och i och med detta kan användarna tidigt se ett fungerade system och dess funktioner och hur det ska utvecklas vidare.

Det finns även en tredje typ av systemutvecklingsmetoder de Agila (Martin 2003). De är ännu mer flexibla än RAD metoderna. Grundsynsättet i dessa metoder är fokus på användaren av systemet. Utvecklingen sker i små steg med regelbundna leveranser av nyaste versionen sker till användaren sker under hela utvecklingen. Detta arbetssätt främjar förändrade krav och nya önskemål av användarna. Det agila sättet att utveckla mjukvara anser att människor och kommunikation är viktigare än formella dokument och att detta arbetssätt ska underlätta lösandet av problem under utvecklingsfasen. En annan central grundtanke är att den del av systemet som levererats till kunden faktiskt fungerar och därmed redan skapat ett värde för kunden.

Vid början av utvecklingen av molekylritarprogrammet såg jag tidigt problemet med att ställa en exakt kravspecifikation av hur molekylen skulle ritas ut. Det finns många egenskaper i en molekyl som måste ritas ut tydligt för betraktaren, så att strukturinformationen går att förstå. Eftersom det är en bild som ritas ut påverkar de olika delarna varandra. Exempelvis kräver en tjockare bindning en anpassning av typsnitt och storlek på tecknen. Skulle det gå att skapa en

kravspecifikation när utseendet av en egenskap påverkar de övriga? Troligen möjligt, men den skulle behöva revideras under utvecklingen, om det inte gjordes en noggrann analys av alla möjligheter från början. Därför valde jag att utveckla programmet helt utan specifikation av hur programmet skulle rita ut de olika egenskaperna. Nedan visas hur olika storlek på atomsymboler och tjocklek på bindning ser ut. Vilket är bäst, eller snyggast är inte lätt att bestämma. Detta är bara ett exempel på hur utseendet av en sak påverkar en annan.

(8)

Syfte

Syftet med denna uppsats är att dokumentera ett sätt att utveckla programkod till färdigt program, genom att dela upp programmet i ett flertal moduler. Det finns många metoder att utveckla mjukvara. Jag väljer att inte specificera vilken typ som använts, mer än att säga att någon typ av Agil programmering (Martin 2003) använts. En av de viktigaste principerna i Agil systemutveckling är fokus på resultatet och det är precis så utvecklingen gick till.

En frågeställning som uppsatsen ska försöka besvara är:

Går det att utveckla mjukvara genom att tillämpa objektorienterad programmering utan att använda sig av systemutvecklingsverktygen?

(9)

Bakgrund

Det finns ett flertal program som kan rita och visa molekylstrukturer. Dessa kan grovt delas in i två grupper. Den första gruppen är de som kan utföra molekylsimuleringar eller andra typer av beräkningar på den ritade molekylen. Dessa är oftast svårare för en lekman att använda, då det finns många olika typer av inställningar och parametrar att ta hänsyn till. Dessa har även

möjlighet att visa molekyler i 3D. 3D genererade strukturer kräver någon form av speciell

algoritm som kan beräkna den mest energisnåla konformationen, dessutom krävs att användaren kan bedöma om det är en rimlig struktur som presenteras. Denna funktion brukar inte finnas i de mer Office liknande produkterna, som är tänkta att användas av alla kemister som vill kunna rita en molekyl. Denna den andra gruppen är till utseende och funktion likt det vanliga enkla

ritprogrammet som följer med alla datorer. Förutom möjligheten att rita enkla geometriska former kan olika molekylstrukturer, atomer och bindningar ritas, i vissa program finns även mallar för laboratorieutrustning och liknande bilder som används i rapporter eller presentationer. Ibland kan en enkel 3D generator finnas med som ger en ungefärlig 3D bild. Det är den senare typen av molekylritarprogram som hädanefter hänvisas till när ett program som kan rita molekyler nämns i texten. De som tas upp i tabellen nedan är de absolut vanligaste förekommande för PC. För en mer komplett lista se bilaga 1.

ChemSketch ACD Labs Freeware*

ChemDraw Cambridge Soft Inget gratis

ISISDraw/SymyxDraw –Accelrys Draw

Symyx Freeware*

MarwinDraw Chemaxon Freeware*

* för privat bruk, eller utbildning

Tabell 1. De fyra absolut vanligaste molekylritprogrammen.

Alla dessa har stöd för att kopiera eller klistra mellan olika program, samt oftast olika plug-in program som kan köpas separat för att utföra olika typer av beräkningar eller för att få fullständig integrering med exempelvis Excel. Med denna funktion kan cellerna i Excel förstå

molekylstrukturer och beräkningar direkt på strukturen kan utföras.

Det finns även ett stort antal mer eller mindre utvecklade open source program. De mest användarvänliga har sitt ursprung i Open Babel (Open Babel). Open Babel är ett bra exempel på vad open source kan resultera i. Det är ett mer eller mindre komplett system av olika paket för att hantera och omvandla olika typer av kemi-relaterade data. Det är skrivet i Phyton och tänkt att köras på server. Med tiden har det tillkommit fler och fler GUI funktioner. Det mest

(10)

Företaget Contur Software har ett behov att ett program som kan visa upp en molekyl. De har två typer av kunder, de som har behov av att kunna rita molekyler, dessa kunder köper då licens på ett kommersiellt program och kan även använda det för att titta på redan ritade molekyler. Den andra typen av kunder är de som inte kommer att rita molekyler men som ibland behöver kunna titta på en tidigare ritad molekyl. Det är åt dessa kunder som programmet är tänkt att användas. Det finns några olika sätt att rita molekyler. En struktur formel visar hur atomerna sitter ihop. Det mest korrekta sättet är att visa en molekyl i 3D, eftersom all molekyler har utbredning i alla tre riktningar. Dock kan det ofta vara svårt att se alla atomer och bindningar i större molekyler om de representeras i tre dimensioner. Jag har försökt att åskådliggöra detta med de tre bilderna

nedan. Det är samma molekyl som vridigt tills det att de två kolatomerna tillslut överlappar varandra.

Figur 1. Etanol sett från olika vinklar

(11)

Figur 2. Molekyl A har alla väten explisivt utritade, molekyl B har alla väten utritade i en förkortad form, molekyl C har enbart terminala väten med samt vätet på heteroatomen, molekyl D har enbart vätet på heteroatomen.

Även cykliska strukturer kan ritas på några olika sätt, dessa två är de vanligaste. Molekylen heter bensen och är aromatisk. I fallet A har dubbelbindningarna valts att läggas inom den aromatiska strukturen. I fallet B ritas alla dubbelbindningar ut som en vanlig dubbelbindning. Här kan man argumentera för att representationen A ger en mer överskådlig bild av strukturen. Det syns direkt att det är en cyklisk struktur. Liknande argument kan användas på butadien som visas i C och D. Båda representationerna är lika korrekta men A och C är att föredra, av estetiska skäl.

Figur 3. Två olika representationer av dubbelbindningar.

(12)

Avgränsning

Det fanns fyra krav på programmet.

1. Det ska visa upp en korrekt struktur på molekylen från molfilen. 2. Det ska inte ske något minnesläckage i programmet.

3. Programmet som fungera på .NET 2.0 biblioteket. 4. Det ska skrivas i C#.

Det finns en stor mängd olika filformat för att lagra information om molekylersstruktur. Varje mjukvaruföretag har valt att utveckla sitt eget format. Informationen som lagras i filen beskriver atomerna och bindningarna i molekylen. För att underlätta konvertering och kompabilitet mellan olika program har några filformat blivit standarder som de flesta program kan hantera. Ett av dessa av cml (Chemical markup Language) som är ett XML baserat filformat. Ett annat är smiles (Simplified molecular input line entry specification) som använder ASCII strängar för att lagra information. Ett av de tidigaste molekylritprogrammen var MDLs ISISDraw som också, troligen på grund av att ta de var tidigt ute, blivit en inofficiell standard. MDL har efter ett flertal

företagsuppköp kommit att ingå i Accelrys Inc. Alla molekylritprogram har inställningsmöjligheter för att få olika utseende på strukturen, ungefär på samma sätt som andra ritprogram. Jag har valt att inte implementera några inställningar annat än möjlighet att ändra storleken på molekylen. En väldigt tydlig avgränsning i detta arbete är att programmet enbart läser molfiler av version V2000 som är den vanligaste förekommande.

Hur en molfil är uppbyggd

En molfil består av tre delar, fullständig dokumentation av hur en molfil är uppbyggd ses i bilaga 2. Först i molfilen kommer en rubrik del följt av anslutningstabell som innehåller information om atomerna och bindningarna och deras egenskaper. På slutet finns en sektion för mer komplex information.

Följande är ett exempel på en molfil av aminosyran alanin här angiven med dess summa formel som också är ett sätt att representera molekyler C3H7NO2. Summaformel används bara för att

(13)

Figur 5. Molfil skapad på alanin, öppnad i text editor, samt utritad struktur på molekylen.

Varje egenskap eller annan specifikation av molekylens struktur lagras med ett värde i molfilen. 0 betyder frånvaro av den egenskapen eller specifikationen. Värdet översätts sedan till den verkliga egenskapen av programmet som ritar ut molekylen. Nedan följer en förkortad förklaring av vad siffrorna betyder och hur de ska tolkas. Har inte tagit med alla typer av generiska sökfunktioner. Rubrik

Anger vilket program som skapade molfilen. I detta fallet MarwinDraw. Raden under antalet atomer, antalet bindningar följt av olika typer av listor om det är en generisk struktur som används för att söka relaterade strukturer. Denna rad slutar med versionen av molfil, i detta fall V2000 som är standard versionen. Det har nyligen kommit en V3000 som är bättre på att hantera stereokemi.

Atomblock

Varje rad håller information om en atom. Först kommer x-, y-, z-koordinater följt av

atomsymbolen. Efter det kommer massdifferens från naturliga isotopen, följt av laddning (där 1 = +3, 2 = +2, 3 = +1, 5 = -1, 6 = -2, 7 = -3). Nästa siffra anger om atomen är kiral. De följande

(14)

av egenskapblocket. Därför används inte alla egenskaper längre. Av kompabilitets skäl finns dessa kvar i de senare versionerna.

Bindningsblock

Varje rad utgör en bindning i molekylen. Först kommer information om vilka atomer bindningen består, från atom nummer och till atomnummer. Den tredje siffran anger bindningstypen (1 = enkelbindning, 2 = dubbelbindning, 3 = tripelbindning, 4 = aromatisk, samt många fler) . Det finns även här möjlighet att ange andra typer av bindningar för att utföra generiska sökningar. Nästa siffra anger stereokemi hos bindningen följt av fler generiska inställningsmöjligheter.

Egenskapblocket

Här anges en egenskap per rad. Alltså samlas alla likadana egenskaper på en rad. Av

kompabilitets skäl finns här fler parametrar än nödvändigt. Kommer bara att förklara de två som finns med i exemplet.

M CHG 2 1 1….Läser från vänster till höger.

M CHG Det en del av egenskap blocket som beskriver laddning (charge). 2 Det finns en laddad atom i molekylen.

1 Det är atom nummer 1 som har laddning 1 Laddningen på atomen översätts till +1. På samma sätt kan nästa egenskaps rad läsas.

M ISO 1 6 13

Det finns en isotop i molekylen och det är atom 6 som har vikten 13 M END avslutar filen.

dalton.

En avgränsning som gjordes direkt i programmeringen av att inte implementera alla egenskaper som en molfil kan innehålla. Syftet med programmet är att läsa diskreta substanser som saknar generiska element. Exakt vilka som skulle implementeras gick dock inte att bestämma innan ett test set av substanser ritats och respektive molfils innehåll jämförts med strukturen. Även manipulering av molfilerna öppnad i texteditor utfördes för att jämföra vilka egenskaper som är nödvändiga för att kunna visa upp en struktur på rätt sätt.

Följande egenskaper valdes;

En atom ska kunna ha X och Y koordinater, atomsymbol, isotopmassa, laddning, radikal.

(15)

Metod

Undersökningsstrategi

För att analysera arbetet med utvecklingen av programmet har undersökningsstrategin Design och Skapade valts.(Oates 2006), jag har valt att översätta ”Design and Creation” till design och skapande. Design och skapande metoden används med fördel när utvecklingen bedrivs som en iterativ process enligt Oates. Med iterativ process menas att utvecklingen sker i många små steg där vissa steg upprepas för att förbättra dem. Oftast består också utvecklingen av en

problemlösande del där design och skapade metoden används. Design och skapade processen används även när nya IT produkter framställs. IT produkter kan vara dataprogram eller studier av olika metoder att skapa datorprogram eller skapandet av modeller av olika slag för att tydliggöra förlopp eller processer. Det kan även vara skapandet av definitioner av ord eller uttryck.

Slutresultatet brukar vara en konstruktion, modell, metod, instansiering eller en blandning av dessa (March, Smith 1995).

• Konstruktion eller tankeskapelse: En exakt definition på ord eller objekt inom ett visst område. Detta är själva grunden för all IT utveckling, att alla som jobbar inom ett område menar samma sak när de använder ett visst ord eller uttryck.

• Modell: Använder en kombination av olika konstruktioner för att beskriva en process eller flöde av information, för att tydliggöra en viss händelse eller företeelse och därmed underlätta problemlösning.

• Metod eller handling: Ett förtydligande av modellen där mer exakt processen beskrivs. Det kan vara allt ifrån en exakt matematisk formel till detaljerade manualer över procedurer.

• Instansiering: Ett fullt fungerade IT-baserat system som demonstrerar att konstruktioner, modeller och metoder kan implementeras.

Denna uppsats beskriver utveckling av mjukvara till färdigt program där utvecklingen bedrevs med hjälp av en massa iterativa processer vilket passar perfekt för design och skapande metoden. Därför valdes denna metod.

Design och skapande är en forskningsstrategi. Med forskningsstrategi menas att kunskapen inom ett visst ämne utökas. Det är alltså skillnad på att enbart skapa en IT-produkt och att öka

kunskapen inom en IT-produkt. För att räknas som forskning måste utvecklingen innehålla analys, förklaringar, argumentation och kritisktgranskande. Det är svårt att ge exakta definitioner på dessa ord då deras betydelse delvis kommer att bero på vilket området som undersöks. Generellt sagt måste dock utvecklingen följa en iterativ process där utvecklaren hela tiden lär sig mer och mer under tiden projektet utvecklas. Denna iterativa process kan delas in i följande steg:

• Medvetenhet om att ett problem existerar. Det kan utvecklaren få genom att studera litteraturen eller genom att följa utvecklingen inom andra discipliner.

(16)

• Utvecklandet av en fungerade produkt. Det räcker inte med att föreslå en ny ide

utvecklaren måste också utveckla en produkt av iden. Detta kan ske på många olika sätt beroende på vilken typ av produkt som utvecklas. Produkten måste vara tillräckligt välutvecklad för att kunna bevisa att förslaget på lösningen av problemet fungerar. • Utvärdering av produkten. När produkten är klar måste utvecklaren jämföra med andra

produkter och kontrollera att produkten uppfyller de angivna önskemålen. • Slutsats. Här summeras resultatet och dokumenteras.

Figur 6. Iterativ process. En pil in som beskriver att processen börjar. Cykeln i mitten symboliserar den iterativa processen som upprepas tills resultatet uppnår de ställda kraven, pilen ut ur cykeln visar att resultatet tas till vara. En nackdel med att använda design och skapade metoden för att beskriva arbetet i denna uppsats var att det inte gick att hitta exempel på forskning utförd med design och skapande metoden i litteraturen. Det blir svårt att ställa olika metoder mot varandra när det inte finns exempel på dess användning i litteraturen. Skälet till detta kan vara att Oates utvecklat denna metod själv och att den ännu inte fått fäste inom den akademiska världen. Det kan också vara så att den inte tillför något nytt till de redan etablerade metoderna och därför inte används.

(17)

Teori

Det är svårt att jämföra utveckling av mjukvara som utförs av en person med de etablerade systemutvecklingsmetoderna. Både vattenfallsmetoden och de olika RAD metoderna har båda analys och planeringsfaser och är tänkta att användas av grupper av utvecklare för att hjälpa till med koordinering av planering av utvecklingen. När en ensam utvecklare arbetar finns bara en version av produkten och alla funktioner och förändringar styrs av samma person. Därför är det svårt att ge någon jämförelse mellan detta mer hacker liknande sätt att programmera med den mer styrda och organiserade formen som en grupp av utvecklare måste hålla sig inom.

Jag har valt att kalla utvecklingen agil av det enda skälet att fokus hela tiden legat på produkten och att det ska vara korta utvecklingscykler.

Kodningen har bitvis varit svår. Inte för att det saknats modeller för hur programmet skulle se ut och inte heller för att det varit svårt att hitta en viss egenskap i molfilen. Däremot har det varit svårigheter i fasen att rita ut molekylen, för att varje egenskaps utseende har påverkat de övriga. Algoritmerna för att dra linjer eller symboler har ständigt förändrats för att den ritade bilden ska bli så lättläst och tydlig som möjligt.

Självklart hade det varit lättare att utgå från en färdigdesignad mall hur alla egenskaper och metoder skulle se ut, då hade det varit lättare att implementera alla egenskaper. En sådan design skulle dock kräva noggranna tester och jämförelser för att resultatet ska bli en så tydlig bild som möjligt.

Utveckling av programkod

I molfilen finns all information som behövs för att rita upp vilken molekyl som helst. Jag gjorde viss prioritering mellan de olika egenskaperna från början. De första egenskaperna jag valde var att läsa av atomsymbol och dess position. Skälet till detta var att det skulle det vara lätt att se om programmet fungerade eller inte. Om programmet fungerade skulle atomsymboler ritas ut på ritytan. Dessutom la jag in tre olika egenskaper från början, för att se om det fungerade att lagra informationen i en lista. På samma sätt har sedan egenskap för egenskap adderats i

programkoden.

Programmet är skrivet i C# och med Visual Studio 2008.

(18)

Molekylritarprogrammet utför sin uppgift i fyra faser. Den första fasen läser in molfilen i

programmet. Den andra fasen läser varje rad i molfilen och skapar en lista av atomer och en lista av bindningar. När detta är klart finns molekylen lagrad i programmet. Den tredje fasen ritar ut molekylen baserad på den information som finns lagrad. Slutligen den fjärde fasen returnerar bilden ut från programmet.

Det första som gjordes i programmet var att läsa in molfilen som innehåller en massa rader med text. Den enda publika metoden Render skapades som tar argumentet en sträng och returnerar en bild. Initialt lästes en rad i taget för att sedan gå in i fas två i programmet och skapa listor med atomer och bindningar. Detta upprepades tills alla raderna var lästa i molfilen. Exempel på kod där varje rad lästes in för en atom, den första fungerande versionen som kunde läsa in en molfil. Siffran numerOfAtoms lästes in först, denna information finns lagrad i molfilen och anger antalet atomer.

private void createAtoms(int numerOfAtoms) {

StreamReader readFile = File.OpenText(molfileLocation); readFile.ReadLine();

readFile.ReadLine(); readFile.ReadLine(); readFile.ReadLine();

for (int i = 0; i < numerOfAtoms; i++) {

string lineRead = readFile.ReadLine(); //läser en rad i taget

myAtom = new Atom(); myAtom.AtomCount = i + 1;

myAtom.XCoordinate = double.Parse(lineRead.Substring(0, 10).Trim(), CultureInfo.InvariantCulture);

myAtom.YCoordiante =

double.Parse(lineRead.Substring(10, 10).Trim(),

CultureInfo.InvariantCulture);

myAtom.AtomSymbol = lineRead.Substring(30, 3).Trim(); atoms[i] = myAtom;

}

readFile.Close(); }

Detta fungerade, men det blev otydligt vad programmet gjorde när både fas ett och fas två utfördes samtidigt för varje rad i programmet. Därför ändrades koden så hela molfilen läses in vid ett tillfälle och därefter klipps varje rad ut i en array enligt följande kod exempel. Där molfile är den inlästa molfilen som text sträng.

String [] lines = molfile.Split(Environment.NewLine.ToCharArray(),

StringSplitOptions.RemoveEmptyEntries);

(19)

samt atomsymbolen i programmet. En molekyl har alltså då enbart en atomsymbol och position. En molekyl består av objekten atomer och bindningar, så det skapades två klasser Atom och Bond som beskriver de egenskaper dessa kan ha. En molekyl var nu klar att ritas ut, alltså tillbaka till MoleculeRenderer klassen och metoden Render. Först måste ett bild objekt skapas och på detta objekt ritas atomerna ut med metoden RenderMolecule. Delar av denna kod visas nedan.

Image myImage = new Bitmap(300, 300);

Graphics paper = Graphics.FromImage(myImage); this.RenderMolecule(paper, mymolecule);

Metoden RenderMolecule tar den skapade molekylen och ritar ut atomerna för att se att alla fyra faserna fungerar. Här är den första fungerade kod som visar upp en molekyls atomer i bilden.

private void RenderMolecule(Graphics paper, Molecule mymolecule) {

for (int i = 0; i < atoms.Length; i++) {

Font atomFont = new Font("Arial", 8, FontStyle.Regular);

SolidBrush symbolBrush = new SolidBrush(Color.Black); paper.DrawString(atoms[i].AtomSymbol, atomFont, symbolBrush, (float)atoms[i].XCoordinate, (float) atoms[i].YCoordiante);

} }

Det visade sig att molfilen har koordinaterna lagrade som kartesiksta koordinater medan C# har längst upp till vänster som (0,0). Därför behövdes en omvandlingsmetod för att få koordinaterna rätt. När detta var gjort valdes etan samt etylenglykol som test molekyler för att se om

programmet fungerade. Nedan ses hur etan, molekyl A, ritades ut. Den enda information som fanns lagrad var X/Y-koordinat och atomsymbol. Molekyl B är hur etan ska ritas ut. Man kan se att atomerna kommer på rätt ställe och har rätt atomsymbol. Bindningar finns ännu inte med, inte heller möjlighet att visa väten på heteroatomer, vilket ses i etylenglykol exemplet molekyl C och D. Det viktiga här är att programmet fungerade i sin enkelhet.

Figur 7. De första molekylerna A och C som ritades ut med hjälp av programmet. A molekylen etan, ska ritas som B. Molekyl C etylenglykol, ska ritas som D.

När hela processen från att läsa in molfil till att visa upp molekylen som en bild fungerade började själva byggandet av den kompletta molekylen. Den fortsatta utvecklingen följde samma mönster. Först lästes en ny egenskap in i atom atomlistan för att sedan implementeras i

(20)

Nedan visas den nästan kompletta metoden för att skapa en atom med alla dess egenskaper. Eftersom alla atomens egenskaper återfinns på samma ställe i varje rad går det att förutse vart en siffra ska plockas upp. Från början ställdes räknaren i till 2 för att hoppa över de två rubrik raderna, men för att göra koden tydligare räknas det numera från noll och två adderas till radens nummer vid varje programrad.

private void createAtoms(int numerOfAtoms, string[] molfilelines) {

for (int i = 0; i < numerOfAtoms; i++) {

Atom myatom = new Atom();

myatom.AtomCount = i + 1; // molfilen börjar med atom 1 och inte atom 0

myatom.XCoordinate = double.Parse(molfilelines[2 + i].Substring(0, 10).Trim(), CultureInfo.InvariantCulture);//hade problem med att omvandla med decimalpunkt, detta löste problemet myatom.YCoordiante = double.Parse(molfilelines[2 + i].Substring(10, 10).Trim(), CultureInfo.InvariantCulture);

myatom.AtomSymbol = molfilelines[2 + i].Substring(30, 3).Trim();

myatom.Charge = Convert.ToInt32(molfilelines[2 + i].Substring(35, 3).Trim());

atoms[i] = myatom; }

Kod har utelämnats från den fullständiga metoden, nedan visas ett exempel på hur det ser ut för att lägga till laddning som finns representerad i egenskapblocket.

if (isCharged(molfilelines)) //om den är laddad gör detta {

for (int i = 0; i < molfilelines.Length; i++) {

if (molfilelines[i].Substring(0, 6) == "M CHG") {

int numberOfChargedAtoms = int.Parse(molfilelines[i].Substring(6, 3).Trim());

for (int j = 0; j < numberOfChargedAtoms; j++) {

int atomNumberOfChargedAtom = int.Parse(molfilelines[i].Substring(9 + j * 8, 4).Trim()); int chargeValue = Convert.ToInt32( molfilelines[i].Substring(13 + j * 8, 4).Trim() );

atoms[atomNumberOfChargedAtom - 1].Charge = chargeValue; //'atomNumber - 1' därför att molfilen börjar med

atomnummer 1 och listan har första possitionen index 0. }

(21)

Det har generellt varit lätt att lägga till molekylens egenskaper, när väl strukturen på molfilens innehåll var förstådd. Det har varit desto svårare att rita ut molekylens egenskaper.

Tidigt i utveckling noterades det att storleken på molekylen borde anpassas efter storleken på ritarean. En liten molekyl blev liten och en stor molekyl blev stor på den fixerade storleken på ritarean. En metod som räknar ut storleken på molekylen lades till och används för att skapa ritytan innan molekylen börjar rits ut. För att få bilden snyggare läggs molekylen en bit in på ritarean. Det finns även en skalningsfakor med som konstant i programmet för att enkelt kunna ändra storleken på molekylen. Denna skalningsfaktor finns med i alla delar av utritningsfasen som påverkas av storleken på molekylen, allt ifrån bindningstjocklek, typsnittets storlek till hur långt in på ritarean molekylen ska komma. Denna skalningsfaktor ligger med som konstant i klassen MoleculeRender.

En klass RenderAtoms skapades för att sköta all hantering av hur atomerna ska ritas ut.

När utvecklingen kommit till denna punkt fungerade programmet på detta sätt. MoleculeRender skapar en molekyl från molecule klassen. Molecule klassen innehåller en lista med atomer som är skapade från Atom klassen. När molekylen är skapad anropas AtomRender klassen som ritar ut molekylen. Eftersom alla instansieringar av klasserna ligger inne i olika metoder och

instansieringarna skickas med som argument dör dessa när metoden är klar.

När bindningarna skulle läggas till i programmet valde jag att först visa dem som ett streck. Nedan visas hur resultatet av detta blev när etylenglykol ritades ut. Bindningen går in i

atomsymbolen, vilket inte ser bra ut. Detta visar tydligt hur sammanvävda alla delar i den grafiska delen av programmet är. Det hade varit väldigt svår att utföra systemanalys och fått med den aspekten. Istället har varje problem löst när det uppkommit.

Figur 8. Atomer och bindningar tillsammans för första gången.

När molekylen ovan visades valde jag att istället lägga atomsymbolen i en vit ruta ovanpå

bindningen. Delar av denna kod ses nedan. Resultatet av detta är att atomsymbolen inte nuddar bindningen.

//mäter storleken av atomsymbolen på ritobjektet i pixlar atomSymbolSize = paper.MeasureString(atomSymbol, atomFont);

//korrigerar för rektangels hörn i förhållande till X-koordinaten xCorrection = atomSymbolSize.Width / 2;

(22)

//MeasureString metoden adderar extra marginal runt strängen, därför reduceras storleken med 0.9

atomRectangle = new

RectangleF(Convert.ToInt32(mymolecule.Atoms[i].XCoordinate -

xCorrection * 0.9), Convert.ToInt32(mymolecule.Atoms[i].YCoordiante) - yCorrection, atomSymbolSize.Width, atomSymbolSize.Height);

//ritar den vita rektangeln där atomsymbolen kommer att läggas ovanpå paper.FillRectangle(backgroundBrush, atomRectangle);

//ritar atomsymbolen

paper.DrawString(atomSymbol, atomFont, symbolBrush, atomRectangle);

En atom ska enbart visas om det är en heteroatom eller om kolatomen har laddning, är en isotop eller radikal. Därför börjar metoden för att rita ut alla atomer med följande if-sats.

if (atomSymbol != "C"

|| (

(atomSymbol == "C" && isotopeSymbol != "0") || (atomSymbol == "C" && chargeAsString != "0") || (atomSymbol == "C" && radicalType != 0) )

)

Vissa atomer brukar visas tillsammans med de väten som finns på atomen, exempelvis syre och kväve. För att lösa detta används ett Dictionary som innehåller alla de atomer som ska visas på detta sätt samt hur många bindningar dessa atomer har. Dessutom måste hänsyn tas till laddning eller övriga bindningar till denna atom. Ett syre har två bindningar. Är syret en alkohol ska ett väte synas, men sitter syret som en eter finns det inget väte. Samma gäller om alkoholen är deprotonerad och därmed har laddningen -1. För att lösa detta skapades en metod som

returnerar antalet väten som ska visas upp, argumenten är den i programmet skapade molekylen samt index i en tidigare metod som ritar ut atom för atom. numberOfBondsDictionary är

dictionaryt som håller reda på hur många bindningar olika heteroatomer har. Koden ses nedan. Bondlist är en lista som innehåller alla bindningar från en atom.

private int returnNumberOfHydrogenOnHeteroAtom(Molecule mymolecule, int index)

{

//ställer lokala variabler till noll från start int numberOfBonds = 0;

int totalBonds = 0;

//plockar fram atomsymbolen för att göra koden lättare att läsa string atomSymbol = mymolecule.Atoms[index].AtomSymbol; //loopar igenom bondlist för att få reda på totala antalet bindningar atomen har

for (int i = 0; i <

mymolecule.Atoms[index].BondsList.Count; i++) {

//adderar antalet bindningar numberOfBonds +=

mymolecule.Atoms[index].BondsList[i].Type; }

(23)

if (mymolecule.Atoms[index].Charge != 0) {

//använder värdet då + innebär fler väten och - färre numberOfBonds -= mymolecule.Atoms[index].Charge; }

//läs hur många bindningar atomen kan ha

totalBonds = numberOfBondsDictionary[atomSymbol]; //svaret är totalt möjliga – hur många det faktisk är return totalBonds - numberOfBonds;

} }

I och med detta har en kortfattad beskrivning av utvecklingen av hur atomerna lästs in i programmet och hur de sedan ritats ut gjorts. En liknande beskrivning av utvecklingen av bindningarna följer.

En bindning har inte så många egenskaper. Den kan vara av en viss typ och den kan innehålla information om den är kiral och hur den i så fall pekar. Dessutom innehåller den information om mellan vilka två atomer den går, från atom och till atom. För at göra koden mer lättläslig har koordinaterna för från atom och till atom plockats ut ur listorna, enligt följande kod fragment.

for (int j = 0; j < bonds.Length; j++) {

int fromX = Convert.ToInt32(atoms[bonds[j].From - 1].XCoordinate ); int fromY = Convert.ToInt32(atoms[bonds[j].From - 1].YCoordiante ); int toX = Convert.ToInt32(atoms[bonds[j].To - 1].XCoordinate ); int toY = Convert.ToInt32(atoms[bonds[j].To - 1].YCoordiante); En switch sats har använts I stället för en massa if satser, allt för att göra koden lättare att följa. En enkelbindning består bara av ett streck mellan atomerna. Nedan visas ett kodfragment på en enkelbindning, där även delar av switch satsen kan ses.

switch (bonds[j].Type) {

case 1: //Type = 1 => enkelbindning

paper.DrawLine(bondPen, fromX, fromY, toX, toY); break;

En dubbelbindning skapade stora problem att rita ut. Först provades att ställa in bindningarna med tre if satser beroende på om bindningen var horisontell, vertikal eller sned. Resultatet av detta ses i bild nedan. Det är bensen som använts som exempel. Det syns att båda

dubbelbindningarna har samma Y-värde när bindningen är horisontell och att de har samma X-värde när bindningen lutar. Det ser inte tillräckligt bra ut och en alternativ metod måste utvecklas, jämför med bilden till höger.

(24)

Lite kod exempel på detta första försök att rita dubbelbindningar, som inte höll måttet. case 2: //Type = 2 => dubbelbindning

if (fromX == toX) //vertikal bindning {

paper.DrawLine(bondPen, fromX + 2, fromY, toX + 2, toY); paper.DrawLine(bondPen, fromX - 2, fromY, toX - 2, toY); }

else if (fromY == toY) //horisontell bindning {

paper.DrawLine(bondPen, fromX, fromY + 2, toX, toY + 2); paper.DrawLine(bondPen, fromX, fromY - 2, toX, toY - 2); }

else //diagonal bindning {

paper.DrawLine(bondPen, fromX, fromY + 2, toX, toY + 2); paper.DrawLine(bondPen, fromX, fromY - 2, toX, toY - 2); }

break;

Det gjordes även ett försök att ställa in längden på alla dubbelbindningar genom att ha en if sats för varje möjligt fall. Visar ett exempel av de 32 möjliga på denna kod.

if (fromX > toX && fromY > toY)

(25)

Figur 10. Alla olika sätt en dubbelbindning av vara lagrad i molfilen.

Nu vändes hoppet till linjär algebra, att det skulle gå att generalisera en dubbelbindning som två parallell förflyttade linjer från samma punkt. Varje bindning hanteras som en vektor. Det

behövdes en metod som flyttar ut linjen parallellt från atomen mot den andra atomen. Denna skulle även gå att använda när trippel bindningar eller zig-zag bindningar ska ritas, därför gjordes den generell under utvecklingen. Det blev två metoder beroende på vilken sida om atomen dubbelbindningen ska vara. Visar först metoden addTheSecondDubbleBond som returnerar en point array för en parallell förflyttad linje mellan de båda atomerna. Denna metod anropar metoderna calculateOrthogonalDistanceAtFromAtom och

(26)

Bild 1. Vektorn mellan punkt (X1, Y1) och (X2, Y”)

Vektorn har lutningen (X2-X1)/(Y2-Y1). Den nya linjen parallellt till höger om linjen mellan punkterna har funktionen f(x) = X1 + (Y2 – Y1) och f(y) = Y1 – (X2 – X1).

private Point[] addTheSecondDubbleBondLine(int fromX, int fromY, int toX, int toY, Molecule mymolecule)

{

Point[] theCoordinatesForTheDubbleBond = new Point[4];//I ordningen fromX1 fromX2, toY1, toY2

//arrayen som har punkterna för den nya linjen

Point[] newToPoint = new Point[3];

Point[] newFromPoint = new Point[3];

newToPoint = calculateOrhtogonalDistancetAtToAtom(fromX, fromY, toX, toY, DISTANCEFROMTHEMIDDLEOFTHEBOND);

newFromPoint = calculateOrthogonalDistanceAtFromAtom(fromX, fromY, toX, toY, DISTANCEFROMTHEMIDDLEOFTHEBOND);

theCoordinatesForTheDubbleBond[0] = newFromPoint[1]; theCoordinatesForTheDubbleBond[1] = newFromPoint[2]; theCoordinatesForTheDubbleBond[2] = newToPoint[1]; theCoordinatesForTheDubbleBond[3] = newToPoint[2]; return theCoordinatesForTheDubbleBond; }

private Point[] calculateOrthogonalDistanceAtFromAtom(int fromX, int fromY, int toX, int toY, int distanceToBondLine) //distanceToBondLine avser hur brett isär de båda linjerna kommer att hamna

{

Point[] array = new Point[3];

(27)

array[1].X = ((fromX) + Convert.ToInt32(toY - fromY) / distanceToBondLine); //ny P1X

array[1].Y = ((fromY) - Convert.ToInt32(toX - fromX) / distanceToBondLine); //ny P1Y

array[2].X = ((fromX) - Convert.ToInt32(toY - fromY) / distanceToBondLine); //ny P2X

array[2].Y = ((fromY) + Convert.ToInt32(toX - fromX) / distanceToBondLine); //ny P2Y

return array; }

Slutligen, koden inne i switch satsen i stället för de 32 if satserna. Det blev mycket enklare att läsa och överskådligare, men framför allt kommer alltid alla tänkbara fall av orienteringar av vinklar hos dubbelbindningarna att visas upp.

Point[] newCoordinates = addTheSecondDubbleBondLine(fromX, fromY, toX, toY, mymolecule);

paper.DrawLine(bondPen, newCoordinates[0], newCoordinates[2]); paper.DrawLine(bondPen, newCoordinates[1], newCoordinates[3]); Resultatet med bensen som exempel ses nedan. Har förstorat bilden så det lättare ses att

dubbelbindningarna ritas vinkelräta i förhållande till bindningens riktning. Alla riktningar kommer att ritas ut och alla kommer att se likadana ut, ett stort framsteg sålunda. Har även med den tidigare ritade versionen från de tre if-satserna horisontell, vertikal eller övrig, samt typ exempel på hur der ser ut i andra ritprogram.

Figur 11. A molekyl ritad med linjäralgebra, B molekyl ritad med tre if-satser, C molekyl som den borde se ut.

(28)

När utvecklingen nått hit lades den fortsatta utvecklingen av dubbelbindningar i cykliska system åt sidan. För att komma vidare måste en bindning veta om den ingår i en cykel samt att en atom i en dubbelbindning måste veta om dess bindningar pekar ut från cykeln eller om bindningen ingår i cykeln. Det var viktigare att se till att alla typer av bindningar kunde ritas ut. Detta finns kvar att utveckla.

Metoden för att parallell flytta en linje i en bindning hade gjorts med hänsyn tagen till att den skulle fungera även för andra typer av bindningar än dubbelbindningar. Det är möjligt tack vare det sista argumentet som avgör hur långt ifrån den ursprungliga linjen mellan atomerna som den nya kommer att hamna. När det var dags att lägga till trippelbindningar gick alltså att använda samma metoder som för dubbelbindningar men med annat värde på denna konstant, då trippelbindningar ligger närmare varandra. Koden har samma uppbyggnad som för

dubbelbindningen med den skillnaden att även bindningen mellan de båda atomerna tas med. Visar inget kodexempel utan visar en molekyl direkt. Väl värt att notera är skillnader kring syre atomen där programmet ritat olika långa bindningar i jämförelse med den mindre molekylen.

Figur 12. Molekyl till vänster ritad av programmet och molekyl till höger ritat av kommersiell mjukvara

(29)

Figur 13. Två olika typer av kirala bindningar, samt de två trianglarna som används för att beräkna hur de ska ritas ut.

Det medför att koden för att rita de kirala bindningarna också blir väldigt enkel. Nedan visas koden för den fyllda triangeln, i fallet med den streckade körs en loop som ritar streck mellan de båda hörnpunkterna.

int lengthOfTheLines = 6;

Point[] chiralBondPoints =

calculateOrhtogonalDistancetAtToAtom(fromX, fromY, toX, toY, lengthOfTheLines);

paper.FillPolygon(blackBrush, chiralBondPoints);

Andra delar av programmet som inte alls berörts är en klass för att hantera olika typer av fel. Det kastas olika typer av felmeddelanden beroende på vilken fas i programmet som inte fungerar. En effekt av att allt hänger ihop i den slutliga bilden är att det inte räckte med en skalningskonstant. En stor bindning kräver annat anstånd mellan dubbelbindningslinjerna än en liten. Därför har en extra avståndskonstant införts för att kunna trimma utseendet ytterligare. Alla klasser ligger också helt separerade och inga instansvariabler skickas mellan klasserna. När en metod skapar en ny klass eller anropar en annan metod skickas nödvändiga argument med för att inte lämna variabler kvar när programmet utfört en cykel. Tanken med detta är att arbetsminnet på datorn som använder programmet inte ska fyllas med överbliven information.

Nedan följer ett klassdiagram över alla klasser i det utvecklade ritprogrammet. Det finns inga hänvisningar till formulärklassen som använts under utvecklingen. Det som återstår av utvecklingen är att rita cykliska strukturer med homogen yttre bindning och eventuella

(30)
(31)

Analys och diskussion

Det går alltid att argumentera vad som är forskning och vad som är utveckling av ännu ett exempel på en IT-produkt. Definitionen av forskning är enligt Nationalencyklopedin

”process som genom systematiskt arbete kan frambringa

nya kunskaper och ökat vetande.”

Det har argumenterats emot att utvecklingen av IT-system skulle vara forskning. Benbasat

(Benbasat 1984) identifierar fallstudie, fältstudie, fältförsök, experiment utfört i laboratorier samt urvalsundersökning som forskningsmetoder. Inget exempel på forskningsmetod på utveckling av IT-system finns med. I en artikel av Gallier och Lands (Gallier och Lands 1897) argumenterar de emot traditionen att skriva vetenskapliga uppsatser på IT-systemutveckling baserad på

forskningsmetodik utvecklad för att användas inom naturvetenskapens experimentella forskning. De refererar till flertal studier där forskarna delvis har gjort om forskningsmetoder för att passa utveckling av IT-system, vilket de hävdar omöjliggör jämförelse mellan olika publicerade resultat. Intressant nog ger de förslaget att studera IT-system på ett alternativt sätt till den stereotypa empiriska naturvetenskapliga metoden med teknikiskt fokus. Det som inte går att mäta går inte heller att undersöka med denna metod. Gallier och Land föreslår att forskning kring IT-system ska innehålla studier av beteenden och organisationer för att kunna förbättra kunskapen om IT-system. Detta kräver att forskaren är insatt i fler ämnen än de rent tekniska, samt att

forskarvärlden accepterar forskning utförd mer nya metoder. Tyvärr kommer författarna inte med något förslag på ny forskningsmetod, men de öppnar för en diskussion om att det behövs ett alternativ.

Både kursboken (Oates 2006) och Nunamaker (Nunamaker, Chen och Purdin 1991) argumenterar för en alternativ forskningsmetod. Oates kallar den för design och skapande och Nunamaker ger inget namn men tanken är den samma i båda författarnas förslagna metoder I korthet kan deras alternativa metod beskrivas att ett problem identifieras följt av att forskaren presenteras en hypotes. Efter samlande av data och påföljande analys presenteras ett argument eller resultat. . Ett forskningsupplägg inom den experimentella delen av positivismens paradigm följer samma mönster som den metod de föreslår. Följer forskaren denna struktur är det alltså fullt acceptabelt att bedriva forskning inom systemutveckling. Där argumentet att utveckling av IT-system är forskning för att själva IT-produkten är beviset på att hypotesen stämmer. Det krävs inga experimentella data när själva produkten är bevis på att hypotesen stämde.

(32)

Slutsatser

(33)

Källförteckning

Benbasat, I. (1984) An analysis of research methodologies. In The Information Systems Research

Challenge, W.F. McFarlan, ed. Cambridge, MA: Harvard Business School Press, 47-85.

Dennis, A., Wixom, B. H. (2006) System Analysis Design. New Jersey, USA, John Wiley & Sons, Inc. Galliers, R.D., Land, F.F. (1987) Choosing appropriate information systems research

methodologies. Communications of the ACM, 30, 11, 900-902.

March, S., Smith, G. (1995) Design and natural science research on information technology,

Design Support Systems, 15, 251-166.

Martin, R., C. (2003) Agile Software Development: Principles, Patterns and Practice. New Jersey, USA, Prentice Hall.

Nunamaker, J.F., Chen, M., Purdin T.D.M. (1991) System Development in Information Systems Research, Journal of Management Information Systems, 3(7), 89-106.

Oates, B. (2006) Researching Information Systems and Computing. London, United Kingdom: SAGE Publications Ltd.

Royce, W., W., (1970) Managing the Development of Large Software Systems: Concepts and Techniques, Proccedings of WESCON, agusti, pp. A1/1-A1/9.

Elektroniska källor

(34)

Bilaga 1 lista över program för att rita molekyler

• ACD/ChemSketch: egenutvecklad, från ACD/Labs, finns både som kommersiell och som freeware version. Finns för Windows.

• Ascalaph: egenutvecklad, finns både som kommersiell och som freeware version. Finns för Windows och Linux.

• ArgusLab: egenutvecklad, enbart freeware. Finns för Windows. • Avogadro, open source. Baserad på Open Babel.

• Ball View: open-source, (L)GPL, C++, Finns för Windows, Mac och Linux. • Bioclipse: open-source, EPL, + a GPL-exception, Java. Eclipse RPC baserad. • BKchem: open-source, GPL, Phyton, Phyton. Mestadels platform oberoende.

• ChemDoodle: egenutvecklad from iChemLabs. Finns för Windows, Mac, och Linux. • ChemDraw: egenutvecklad from CambridgeSoft. Finns för Windows och Mac. • ICEDIT egenutvecklad from InfoChem.

• ChemTool:gratis, skriven i C med hjälp av GTK Finns för Unix och Linux.

• ChemWindow egenutvecklad från Bio-Rad, del av KnowItAll mjukvarumiljön, freeware. • ISISDraw and Symyx Draw: egenutvecklad från MDL Information Systems och Symyx

Technologies.

• JChemPaint: open-source, (L)GPL, Java.

• KnowItAll: egenutvecklad från Bio-Rad. freeware.

• MarwinSketch: egenutvecklad från ChemAxon, finns både som kommersiell och som freeware version (Java Beans).

• MarwinSpace: egenutvecklad från ChemAxon finns både som kommersiell och som freeware version. 3D (Java Beans).

• Mobile Molecular DataSheet: egenutvecklad från Molecular Materials Informatics. BlackBerry smartphones.

• molsKetch: open source, GPL, multiplatform, Qt4.

• ODYSSEY, egenutvecklad från Wavefunction, Inc. Finns för Windows och Mac. • SketchEl: open source, GPL, Java.

• Smormo-Ed: BSD license, C and GTK+, Finns för Windows och Linux.

• SPARTAN, egenutvecklad från Wavefunction, Inc. Finns för Windows, Mac och Linux. • Str3Di32, egenutvecklad från Exorga, Inc. Finns för Windows.

• XDrawChem: open-source software, (L)GPL, C++, bygger vidare på OpenBabel. Finns för Windowsv, Linux, Mac.

(35)

Bilaga 2 CTFilen från Symyx som beskriver hur en molfil är uppbyggd

Filen i sin helhet finns att ladda ned på Symyx hemsida efter det att man skapat ett konto. Det är enbart de delar som rör molfiler som finns med här i bilagan.

(36)
(37)
(38)
(39)
(40)
(41)
(42)
(43)

Bilaga 3 Komplett kod från programmet

Klassen Atom using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MoleculeRenderer { /// <summary>

/// Atomclass, contains properties of the atoms /// </summary>

internal class Atom : System.Object

{

//the private instance variables

private int atomCount;//the numbering figure from the molfile private double xCoordinate;

private double yCoordinate; private string atomSymbol; private int isotopeMass; private int charge; private int radical;

private List<Bond> bondslist = new List<Bond>(); public static bool operator ==(Atom a, Atom b) {

// If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b))

{

return true; }

// If one is null, but not both, return false. if (((object)a == null) || ((object)b == null)) {

return false; }

// Return true if the fields match:

return a.xCoordinate == b.xCoordinate && a.yCoordinate == b.yCoordinate; }

public static bool operator !=(Atom a, Atom b) {

return !(a == b); }

public override bool Equals(object obj) {

return base.Equals(obj); }

public override int GetHashCode() {

return base.GetHashCode(); }

(44)

/// </summary>

public List<Bond> BondsList { get { return this.bondslist; } set { this.bondslist = value; } } /// <summary>

/// property - the atomnumber identical the the number in the molfile /// </summary>

public int AtomCount { get { return this.atomCount; } set { this.atomCount = value; } } /// <summary>

/// property - X-Coordinate of the atom /// </summary>

public double XCoordinate { get { return this.xCoordinate; } set { this.xCoordinate = value; } } /// <summary>

/// property - Y-Coordinate of the atom /// </summary>

public double YCoordiante { get { return this.yCoordinate; } set { this.yCoordinate = value; } } /// <summary>

/// property - the atomsymbol, the letter /// </summary>

(45)

{ get { return this.atomSymbol; } set { this.atomSymbol = value; } } /// <summary>

/// property - the isotopic mass of the atom /// </summary>

public int IsotopeMass { get { return this.isotopeMass; } set { this.isotopeMass = value; } } /// <summary>

/// property - charge of the atom /// </summary>

public int Charge { get { return this.charge; } set { this.charge = value; } } /// <summary>

/// property - radical type /// </summary>

(46)

Klassen AtomRender using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; namespace MoleculeRenderer { /// <summary>

/// class that render all atoms of the molecule /// </summary>

class AtomRender

{

/// <summary>

/// dictionary - to be used for look up number of bonds on heteroatoms /// </summary>

Dictionary<string, int> numberOfBondsDictionary; /// <summary>

/// constructor for the AtomRender class /// </summary>

public AtomRender() {

//used constructor to define the number of bonds to the heteroatoms //the heteroatoms with the number of bonds

numberOfBondsDictionary = new Dictionary<string, int>(); numberOfBondsDictionary.Add("B", 3); numberOfBondsDictionary.Add("Si", 4); numberOfBondsDictionary.Add("Ge", 4); numberOfBondsDictionary.Add("N", 3); numberOfBondsDictionary.Add("P", 3); numberOfBondsDictionary.Add("As", 3); numberOfBondsDictionary.Add("Sb", 3); numberOfBondsDictionary.Add("O", 2); numberOfBondsDictionary.Add("S", 2); numberOfBondsDictionary.Add("Se", 2); numberOfBondsDictionary.Add("Te", 2); numberOfBondsDictionary.Add("Po", 2); } /// <summary>

/// method that draws the atoms on the paper /// </summary>

/// <param name="paper">the graphics objec</param>

/// <param name="mymolecule">the created molecule</param>

public void DrawTheAtoms(Graphics paper, Molecule mymolecule, int SCALINGFACTOR) {

Font atomFont = new Font(FontFamily.GenericSansSerif, SCALINGFACTOR / 3,

FontStyle.Regular, GraphicsUnit.Pixel);

Font isotopeFont = new Font(FontFamily.GenericSansSerif, SCALINGFACTOR / 5,

(47)

SolidBrush symbolBrush = new SolidBrush(Color.Black); SolidBrush backgroundBrush = new SolidBrush(Color.White); //loop through the mylecule and draw each atom

for (int i = 0; i < mymolecule.AtomList.Count; i++) {

//correction for the rectangle point of the atomSymbol as compared to the X/Y-Coordinate

float xCorrection = 0; float yCorrection = 0;

float xCorrectionHeteroatomNumber = 0; float YCorrectionHeteroatomNumber = 0; //pulls the Symbols from the atomlist

string atomSymbol = mymolecule.AtomList[i].AtomSymbol;

string isotopeSymbol = mymolecule.AtomList[i].IsotopeMass.ToString(); string chargeAsString = mymolecule.AtomList[i].Charge.ToString(); int radicalType = mymolecule.AtomList[i].Radical;

string numberOfHydrogenOnHeteroatomAsString = ""; //number of hydrogen on heteroatom

//size of the text to be calculated SizeF atomSymbolSize = new SizeF();

//the background rectangle of the atomSymbol RectangleF atomRectangle = new RectangleF(); RectangleF isotopeRectangle = new RectangleF(); RectangleF chargeRectangle = new RectangleF();

// if atom not carbon show the atom or if the atom is carbon and contains charge or is isotope or is radical

if (atomSymbol != "C"

|| (

(atomSymbol == "C" && isotopeSymbol != "0") || (atomSymbol == "C" && chargeAsString != "0") || (atomSymbol == "C" && radicalType != 0) )

) {

//TODO kolla åt vilken sida bindningen går först

//för att lägga alla rutor rätt i förhållande till bindningen //hantera de båda fallen olika helatiden.!!

//

//only calculate number of hydrogen if the atom is a heteroatom and the heteroatom is shown with hydrogens

if (atomSymbol != "C" && numberOfBondsDictionary.ContainsKey(atomSymbol)) {

(48)

//if the bonds point to the RIGHT, add the hydrogen on the right side of the heteroatom

if (mymolecule.AtomList[i].BondsList[0].FromAtom.XCoordinate <= mymolecule.AtomList[i].BondsList[0].ToAtom.XCoordinate)

{

//add the hydrogens on the heteroatom if it should be any if (Convert.ToInt32(numberOfHydrogenOnHeteroatomAsString) >= 1) { if (Convert.ToInt32(numberOfHydrogenOnHeteroatomAsString) == 1) { atomSymbol += "H"; xCorrectionHeteroatomNumber = (float)mymolecule.AtomList[i].XCoordinate + xCorrection; }

//else if the heteroatom should have one than more hydrogen else { atomSymbol += "H" + numberOfHydrogenOnHeteroatomAsString; xCorrectionHeteroatomNumber = (float)mymolecule.AtomList[i].XCoordinate + xCorrection; } } }

//else the bond must point to the LEFT else

{

//add the hydrogens on the heteroatom if it should be any if (Convert.ToInt32(numberOfHydrogenOnHeteroatomAsString) >= 1) {

//there is one hydrogen on the heteroatom

if (Convert.ToInt32(numberOfHydrogenOnHeteroatomAsString) == 1)

{

//add the hydrogen before the heteroatom atomSymbol = atomSymbol.Insert(0, "H"); xCorrectionHeteroatomNumber =

(float)mymolecule.AtomList[i].XCoordinate - xCorrection; }

//there is more than one hydrogen else

{

(49)

//measures the size of the atomSymbol and the isotope symbol on the image object in pixels

atomSymbolSize = paper.MeasureString(atomSymbol, atomFont);

//correction for the rectangle point of the atomSymbol, as compared to the X-coordinate

xCorrection = atomSymbolSize.Width / 2; yCorrection = atomSymbolSize.Height / 2;

//**MeasureString method adds extra free space around the string therefore I multiply all xCorrections with 0.9

atomRectangle = new

RectangleF(Convert.ToInt32(mymolecule.AtomList[i].XCoordinate - xCorrection * 0.9),

Convert.ToInt32(mymolecule.AtomList[i].YCoordiante) - yCorrection, atomSymbolSize.Width, atomSymbolSize.Height);

//if the atom does not have the default mass value if (mymolecule.AtomList[i].IsotopeMass != 0)

{

//size of the isotope text SizeF isotopeSymbolSize =

paper.MeasureString(mymolecule.AtomList[i].IsotopeMass.ToString(), isotopeFont);

//correction values to make the isotope box at the right place int xcoord = Convert.ToInt32(mymolecule.AtomList[i].XCoordinate - isotopeSymbolSize.Width - xCorrection * 0.9) + SCALINGFACTOR / 25;

int ycoord = Convert.ToInt32(mymolecule.AtomList[i].YCoordiante - isotopeSymbolSize.Height);

//the rectangle in which the isotope value will be put isotopeRectangle = new RectangleF(xcoord, ycoord, isotopeSymbolSize.Width, isotopeSymbolSize.Height);

}

//if the atom is charged show the charge value if (mymolecule.AtomList[i].Charge.ToString() != "0") {

if (mymolecule.AtomList[i].Charge.ToString() != "4")//if the charge has value 4, the atom is a doublet radical

{

//add a + sign to the charge value if the charge is possitive if (mymolecule.AtomList[i].Charge > 0) { chargeAsString = "+" + mymolecule.AtomList[i].Charge.ToString(); } else { chargeAsString = mymolecule.AtomList[i].Charge.ToString(); }

//measures the size i pixels of the charge string bulidning the white where to print the text

SizeF chargeSymbolSize = paper.MeasureString(chargeAsString, isotopeFont);

(50)

int xcoord =

Convert.ToInt32(mymolecule.AtomList[i].XCoordinate + xCorrection - SCALINGFACTOR / 25); int ycoord =

Convert.ToInt32(mymolecule.AtomList[i].YCoordiante - chargeSymbolSize.Height); chargeRectangle = new RectangleF(xcoord, ycoord, chargeSymbolSize.Width, chargeSymbolSize.Height);

}

//to be sure add the radical information

//the radical information might not be pressent in the properties block

//only in the atom block else

{

mymolecule.AtomList[i].Radical = 2; }

}

//if the atom is a radical show the radical dot representation if (mymolecule.AtomList[i].Radical.ToString() != "0")

{

//TODO, ger alltid radikal på samma plats

//egentligen borde den ta hänsyn till bindningaran in mot atomen för att hitta en "ledig" plats

//där den kan rita ut radikal typen.

//alltså en rad ifatser som alla ger nya xCoordRad värden som används av draw metoden

//TODO hela denna delen måste göras om med vektorer på fria platser kring atomen

SolidBrush radicalBrush = new SolidBrush(Color.Black); float xCoordRad = atomRectangle.X + atomRectangle.Width - 1; float yCoordRad = atomRectangle.Y + 5;

paper.FillRectangle(backgroundBrush, atomRectangle); //creates a transperante rectangle to draw the atomsymbol in

paper.DrawString(mymolecule.AtomList[i].AtomSymbol, atomFont, symbolBrush, atomRectangle); //draws the atomsymbol in the white rectangle

//to draw the three different types of radicals

if (mymolecule.AtomList[i].Radical == 1)//Radical type 1 => singlet---two radical dots close

{

paper.FillEllipse(radicalBrush, xCoordRad, yCoordRad, 3, 3);

paper.FillEllipse(radicalBrush, xCoordRad, yCoordRad + atomRectangle.Height / 3, 3, 3);

}

if (mymolecule.AtomList[i].Radical == 2)//Radical type 2 => doublet---one dot

{

paper.FillEllipse(radicalBrush, xCoordRad, yCoordRad, 3, 3);

}

if (mymolecule.AtomList[i].Radical == 3)//Radical type 3 => triplet---two dots one on either side of the atomsymbol

(51)

paper.FillEllipse(radicalBrush, xCoordRad, yCoordRad, 3, 3); paper.FillEllipse(radicalBrush, xCoordRad - (atomRectangle.Width + 2), yCoordRad, 3, 3); } }

//draw the background rectangle and the atomSymbol

paper.FillRectangle(backgroundBrush, atomRectangle);//**creates a white rectangle to draw the atomsymbol

paper.DrawString(atomSymbol, atomFont, symbolBrush, atomRectangle);//rectangle containing the atomsymbol

//TODO

// kankse här att släppa in siffran på heteroatom //men är det ett väte inte siffra, bara om fler än ett //paper.DrawString(numberOfHydrogenOnHeteroAtom.ToString(), atomFont, symbolBrush, xCorrection, yCorrection+10);

//isotop

if (isotopeSymbol != "0")//0 because when the int object is converted to string

{

paper.FillRectangle(backgroundBrush, isotopeRectangle);//a white rectangle under the isotope text

paper.DrawString(isotopeSymbol, isotopeFont, symbolBrush, isotopeRectangle);//rectangle containing the isotopetext

}

//charge

if (chargeAsString != "0") {

paper.FillRectangle(backgroundBrush, chargeRectangle);//background white rectangle

paper.DrawString(chargeAsString, isotopeFont, symbolBrush, chargeRectangle);//charge text

} } } }

//to close the objects atomFont.Dispose(); isotopeFont.Dispose(); symbolBrush.Dispose(); backgroundBrush.Dispose(); } /// <summary>

/// calculates the number of hydrogens that a heteroatom should show /// </summary>

/// <param name="mymolecule"></param>

/// <param name="index">index value from the render atom loop</param>

/// <returns>the number of hydrogens on the heteroatom</returns>

private int returnNumberOfHydrogenOnHeteroAtom(Molecule mymolecule, int index) {

int numberOfBonds = 0;

References

Related documents

Först frågades vilken av följande egenskaper som deltagarna trodde karaktären hade i ett MOBA-spel, om karaktären kan utföra mycket skada, om karaktären kan tåla mycket skada,

[r]

Om alla fyra sidorna i en rektangel är lika långa kallas rektangeln för

Gratis läromedel från KlassKlur – KlassKlur.weebly.com – Kolla in vår hemsida för fler gratis läromedel – 2018-05-19 16:51.

Eftersom förändringsarbete är nödvändigt (Stofler, 2007; Jahren Kristoffersen &amp; Ottvik Jensen, 2006) för att kvaliteten inom hälso- och sjukvården skall kunna

Fullerenerna eller nanorören används inom nanotekniken och består av fem- eller sexkantiga nätverk i form av kablar eller rör.. Fullererenerna tillverkas genom sublimering av

Vidare beskriver läroplanen (Lpfö 98) ett förtydligande angående förskollärarnas roll och ansvar att utmana och stimulera barnens matematiska utveckling samt

3 Två rektanglar med olika form, men båda med omkretsen 18 cm. Lite klurigt