The tmj.ini file

Motion based exam

The data is recorded with the assumption that the TMJ exam is done with a motion based exam.

Opening and closing

Here are the attributes for opening and closing:

[Opening and Closing]
PainOnOpening=[true | false]
LeftClickOnOpen=[true | false]
RightClickOnOpen=[true | false]
DeviationOnOpen=["center" | "left" | "right"]
OpenAmount=[int (in mm)]
PainOnClosing=[true | false]
LeftClickOnClosing=[true | false]
RightClickOnClosing=[true | false]
DeviationOnClosing=["center" | "left" | "right"]


Protrusive movement

Here are the attributes for protrusive movement:

ProtrusiveAmount=[int (in mm)]
PainOnProtrusion=[true | false]


Lateral Movements

Here are the attributes for lateral movement:

LeftLateralAmount=[int (in mm)]
PainOnLeftLateral[true | false]
RightLateralAmount=[int (in mm)]
PainOnRightLateral=[true | false]


Static Bite

Records for when the bite is at centric occlusion.

OcclusionClass=["I" | "II div 1" | "II div 2" | "III"]
Overjet=[int (in mm)]
Overbite=[int (in mm)]
AnteriorCrossbite=[true | false]
PosteriorCrossbite=[true | false]

Let me know in the comments if I am missing anything

The cpcf file

Basics and header

Now that we went over tooth surface charting, lets go over periodontal charting.

Just like the cdcf file, we start with the line: “SpecVersion=1”. And also like the cdcf file, we denote each tooth by the American system followed by the “|” symbol and then will have periodontal attributes associated with each tooth.

Periodontal probing

After the keyword “probing”, six numbers are expected which are associated with the probing depths. Where the probing depths are located depends on the quadrant we are working in. The best way to remember the order is to look at the tooth from the occlusal position and “up” being towards the facial or bucal, then then work clockwise starting with the buccal side “left” and then all the way around.

Maxillary right quadrant: [buccal/facial distal] [buccal/facial center] [buccal/facial mesial] [lingual mesial] [lingual center] [lingual distal]
Maxillary left quadrant: [buccal/facial mesial] [buccal/facial center] [buccal/facial distal] [lingual distal] [lingual center] [lingual mesial]
Mandibular left quadrant: [buccal/facial distal] [buccal/facial center] [buccal/facial mesial] [lingual mesial] [lingual center] [lingual distal]
Mandibular right quadrant: [buccal/facial distal] [buccal/facial center] [buccal/facial mesial] [lingual mesial] [lingual center] [lingual distal]

For example, lets say we have the following line:

3| probing 2 2 3 3 3 4

This would mean for tooth #3, the distal buccal probing depth is 2mm, the center buccal probing depth is 2mm, the mesial buccal probing depth is 3mm, the mesial lingual probing depth is 3mm, the center lingual probing depth is 3mm, and the distal lingual probing depth is 4mm.

Periodontal recession

Recession works the same way as probing but with the keyword “recession”.  So, looking at the following example:

4| probing 3 3 3 2 2 2; recession 0 0 1 2 0 0

Tooth #4 has 1mm recession in the mesial buccal aspect and 2mm recession in the mesial lingual aspect and no recession anywhere else.


Bleeding starts off with they attribute keyword “bleeding” but then expects either a “b” or “-“. The “b” meaning bleeding was present and “-” meaning there was no bleeding present. In the following example:

5| probing 3 3 3 2 2 2; recession 0 0 1 2 0 0; bleeding b b b - - b

In this case, tooth #5 had bleeding all along the buccal aspect and the distal lingual aspect.


Mobility applies for the whole tooth, so there is only one number expected (which is the grade) after the mobility keyword. For example:

12| probing 6 6 7 8 4 7; recession 2 2 1 2 3 2; mobility 2

Which means tooth #12 has a mobility of grade II.


Just like mobility, furcation applies for the whole tooth. For example:

30| probing 6 6 7 8 4 7; recession 5 5 5 2 3 2; furcation 2

Which means that tooth #30 has furcation grade II.

Other keyword attributes

The following are just keyword attributes that do not expect any additional information

  • Keyword dehiscence for Dehiscence
  • Keyword fenestration for Fenestration


And that’s it!

Let me know in the comments if anything is missing.

The cdcf file

Why make a chart format?

Because it hasn’t been done before. Apparently nobody has ever decided to create a file format and spec for dental charting. This will be the first.


First of all, all tooth numbers are going by the American / Universal Standard. Just to review, here is the basic chart (taken from the Wikipedia article):

Starting with patient’s upper right, the patient’s maxillary right 3rd molar is tooth #1. As you move to the patient’s left, you increase in number with the patient’s maxillary right 2nd molar being tooth #2. Then, with the maxillary left 3rd molar being #16, then, still staying on the left side, the left mandibular 3rd molar is tooth #17, and working towards the right, the mandibular right 3rd molar is #32.

As for primary (baby) teeth, the standard system (using tooth #A-T) will be used in a similar fashion.

What about European Standards?

Having a UI convert from American to the FDI World Dental Federation Notation is actually very simple. Therefore, whichever system is actually used in the file does not matter as much. But still, why go with American? There is no real good answer outside of the fact this software will be released in the US first and the rest of the world later.

The basic tenants we want in a charting file format

As mentioned in previous posts, we want this file format to be human readable. That way, even if the UI is broken, somebody can at least read the cdcf file using a simple text editor. Therefore, it will use basic text in a way that most dentist can learn in a single day. The side effect of this is that using a system like git, we can be able to push changes via a simple diff rather than uploading an entire binary file.

We also want to use terms that most people can understand. However, things like the CDT codes complicate things. Most people do not know on top of their head what code is assigned to which procedure. Therefore, we need to minimize any kind of CDT code in the format itself. However, there are indeed cases where normal terminology is not sufficient and a code needs to be used to explain what is existing and what kind of procedure was done with the patient. Eventually, as Clear Dental goes international, all the terms will be properly explained in the CDT codes will be unnecessary.

As mentioned before, this will be released in the US first. Therefore, all terms will be in English. Even when Clear Dental makes its way to other countries, the terms will be kept in English.

One real important thing about this format is that when you are reading the file, you are reading the current status of the patient. In order to get a history of what was done you need to use git to see the logs of the changes done to the file and you can use diff to find the difference between the two versions. Of course, in the UI, this will all be integrated so the user does not have to type in command lines to check the history (but that option is always there).

What belongs in the file and does not

Because you want to get a comprehensive view of the patient’s status, it will include all of the following:

  • Existing / missing teeth
  • Restorations (amalgams, composites, crowns, etc.)
  • Implants
  • Existing endodontic treatment (including post/core) and endodontic diagnosis
  • Caries, chip, fractures, abrasions, abfractions, malpositions, braces, diastemas, incipient lesions, open margins, watches

What will not be included:

  • Periodontal probing, recession, or anything else related to a typical periodontal exam. Not because it is not important or wouldn’t be integrated in a UI, but because it would be too much for a simple cdcf file to handle.
  • The billed out procedure (including exams). If an exam is done, it will be part of the comments of the commit log. For example, of a re-care exam is done, the fact a re-care exam was done will not be in the file (the only way you can find it was done would be looking at the git history). However, you would still see the updates to the chart (if any was done) after the exam was done.
  • Non carious lesions (hard or soft). For now, it will be part of the commit log but eventually there will a file and image directory dedicated just for lesions. Things like ulcerations, Morsicatio buccarum and tori are not charted in this file. Please see softTissue.ini and hardTissue.ini along with tmj.ini for this kind of information
  • Treatment plan. That, oddly enough, is done via git branching what treatment you want to do and then merging the actual treatment when you do it. That way, you can have multiple treatment plans, mix treatment plans and even have treatment plan templates for patients.
  • Chief complaint (will also be in the git log)

File format basics

The file will start off with the line “SpecVersion=X” where X is the current version of the spec. In theory, the spec should be backwards and forwards compatible, but this is added in there just in case. For now, each file will start with “SpecVersion=1”. Then, the file will list off each tooth that is existing by its number and then have the “|” to then specify what attributes it has.

So lets start with a patient who has all 32 teeth, all are erupted and not a single filling or cavity. The file would look like this:



Now lets go with the other extreme. You have a fully edentulous patient. The file would look like this:


That’s it, mostly a blank file with the “SpecVersion=1” there just to informed the reader that the whole file isn’t empty, just the chart.

Now supernumerary teeth are strange because neither tooth is the “real” one. Therefore, to designate which tooth is being charted, the tooth will show up twice. For example, lets say the patient has a supernumerary tooth #7, the chart would have something like this:



Now you know that there are two teeth that are maxillary right lateral incisors. This would even apply with there are 3 or even more supernumerary teeth. Also, the teeth would be in the order that they are charted. For example:


7| DL composite

The tooth with the DL composite would be the distal tooth #7, not the mesial. Likewise:

10| DL composite

The tooth with the DL composite would be the mesial tooth #10, not the distal.

Attribute(s) of the teeth

The general format for each tooth will be:

Tooth Number| attribute 1; attribute 2; ... ; attribute n 

Each attribute will be separated by a semicolon. The last attribute does not require a semicolon but does require a newline to end the tooth

Surfaces of the teeth

The following abbreviations will be used in the chart:

  • M = Mesial
  • O = Occlusal
  • D = Distal
  • B = Buccal (valid only for posterior teeth)
  • L = Lingual (for maxillary teeth, lingual and palatal will mean the same thing)
  • F = Facial (valid only for anterior teeth)
  • I = Incisal (valid only for anterior teeth)


All fillings must have a surface and material. All fillings are basically inlays regardless if it was direct or indirect. Lets say there is a MOD amalgam on tooth #30, the line would be:

30| MOD amalgam

There must be a space between the surfaces and the material. The surfaces can come in any order. Repeat surfaces are ignored. A Class V restoration is not charted in this system as it would be an B or F anyway.

The material type can be anything, but it is recommended to use only “amalgam”, “composite”, “irm”, “gold”, or “porcelain”. Using a something like Fuji IX (resin modified glass ionomer) should be charted as composite for the sake of a simple UI but adding in “RMGI” would still be valid; but not recommended.

An onlay is really a crown, just to a full crown. Please see the crown section for more information.


Similar to fillings, decay must have a surface. For example, if #12 has distal caries, you would chart:

12| D caries

This is independent if you wish to do a DO restoration or if there is existing restorations. If #8 has a ML composite with recurrent decay, you would see:

8| ML composite; ML caries

If the decay is incipient, then it is marked as “incipient decay” like:

3| M incipient decay

The UI at this point would assume you want to watch the surface.


Crowns are marked with the format:

tooth number| [material] 

For example, if #9 as a porcelain fused to metal crown, then:

9| [PFM] 

It is recommended to only use the terms “PFM”, “gold”, “ceramic”, “titanium”, or “zirconia”. Technically, any free text can be valid but then the UI may not be able to convert the term to whatever color/scheme it is using.

If no surfaces are mentioned, then it is assumed you are talking about a full coverage crown. If there is even a single surface, then it is assumed you are talking about an onlay. For example:

3| [DL gold] 

Is a distal lingual gold onlay on tooth #3. Without the “[” and “]”, it is assumed we are talking about a filling (or inlay) rather than an onlay.

You can still combine a filling with a full coverage crown. For example, lets say #30 was endodontically treated with a gold restoration, and then had recurrent infection and had to be retreated with a composite to cover up the access. It would be charted as:

30| RCT; post; composite core; [gold]; O composite

Endodontic treatment

If the tooth had a root canal treatment, then the attribute would be “RCT”. No surfaces. It is implied that if a tooth has the “RCT” attribute, then root canal treatment is done. For example, if #11 had a root canal and it was finished off with the lingual access closed via composite, it would be:

11| RCT; L composite


If a tooth has an implant, it will have the “implant” attribute. If there are no words after the term “implant”, then it means we don’t know the details. For example, if we know that #18 has an implant, and a PFM implant crown, but we don’t know what brand of implant, then we would say:

18| implant; [PFM]

It is implied with this system that any crown with an implant is an implant crown. Let say we know #30 is a T3 model BOPS6515, then we say:

30| implant T3 BOPS6515; abutment custom; [PFM]

Note that first it was the vendor name, and then a space, and then the model name.


Posts do not have a surface, but they have a material. If you place a parapost on #13, then you would have:

13| RCT; post parapost; core amalgam; [PFM]

If is unclear which type of post was placed, then the attribute would just be “post” and that’s it.


Similar to posts, there are no surfaces but there is a material. Is there is a

Additional attributes

So, now that we talked about a lot of examples, lets just go one by one and talk about the remaining attributes. It is assumed you will know what the attribute itself means. Just like the previous examples, if there is a surface for the attribute, it would come first.

  • erosion (surface required)
  • chip (surface required)
  • fracture (surface required)
  • watch (surface required)
  • heavy wear (no surface required)
  • discoloration (no surface required)
  • white spot lesion (surface required)
  • stain (surface required)

Free text comments

All comments start with the “#”. The comment is over with either a newline or semicolon. For example:

19| heavy wear; #patient says he uses that tooth to chew on everything

Anything I am missing?

I am sure I am missing out on some more attributes, please leave a comment or e-mail me for suggestions. Thanks.

The .ini file and personal.ini

As mentioned in the previous post, one of the files that will be in the patient’s chart will be “contacts.ini”. So lets break it down:

The .ini file format

Rather than re-inventing the wheel, we can just use a format that many toolkits and other APIs already use: the .ini file. You can read the details of how a .ini file looks like by reading the Wikipedia article on it.

Why go with .ini files?

First of all, a .ini file is human readable. If all else fails, somebody can read the file using a text editor and see the data. This also makes is much easier to debug.

Secondly, it does allow features like sections, being able to assign clear labels for each value, and adding comments.

The third (but not final) reason is that Qt (which Clear Dental will use as the front end) has a built in .ini parser that is fast and light weight. It can also store and serialize strings, integers, etc. all transparently without any issues.

What is wrong with all the other file formats?

XML is not a good choice because although it can be human readable, it can be overly verbose and unnecessarily complex. Also, the lack of hierachy in .ini is more a feature than a bug in this case because we actually want to discourage a fully complex dataset when all we need is just simple data about the patient. This is why JSON probably would not be a good idea either despite being much better than XML.

A .CSV file would not work well either because we normally store things in a simple “key” and “value”. Therefore, the entire file would just be two columns and we also wouldn’t get other features like groups.

YAML could work but would require 3rd party libraries which have their own maintenance required and may not be supported with Qt.

However, in the future, we could move from a .ini file to something else like a .yaml by simply converting the files from one format to another which would be simple because we are working with the file system, not a complex SQL database.

How .ini files will work in this system

The front end software should work even if all fields are missing. Although the presentation would be nonsensical, it should not crash due to lack of data. Therefore, all fields are either “recommended” or “optional”.

The term “recommended” simply means the person entering the data should put it in. If the field is blank, the UI should warn the user that it is blank but the user can still override the system and allow it to move on.

The term “optional” means that there are no warning if the field is missing. This means the UI has to be able to present the data without the field. From here on out, all optional fields will be in italics.

Back to our regularly scheduled program: personal.ini

The file will have the following groups:

    • Name
    • Personal
    • Address
    • Phones
    • Emails
    • Work
    • Emergency Contact
    • Preferences
  • Others

Lets now go in to each group in detail:


Holds everything related to the patient’s name. The name group will have the following keys:

FirstName: The patients first name
NamePhonetic: How to say the patient’s first name (or preferred name) phonetically
MiddleName: The patient’s middle name or middle initial
LastName: The patient’s last name
PreferredName: What the patient would preferred to be called
PreviousName: In case of a name change, what they used to be named (in case insurance has the old name)


NamePhonetic=Say "Jack" with an "e" at the end
PreviousName=Jacqueline Doe



Holds everything related to the patient’s personal data. Please note that things like family relationship is stored as symbolic links in the “family” folder. Things like social security number are stored in the “finance” folder. The personal group will have the following keys:
DateOfBirth: The date of birth of the patient, in the format “MM/dd/yyyy” (American format).
Sex: The sex of the patient (“male” or “female”)
Gender: The gender of the patient (which is independent of sex). This field can include “Male”, “Female”, “Transman”, Transwoman”, “Genderqueer” or “Other”. The patient’s gender will override the sex field when it comes to “he” vs. “she” vs. “they”.
Race: In case you are working in a public health facility and need to kept records of race. This is using the CDREC race codes (the concept field)
Ethnicity: In case you are working in a public health facility and need to kept records of ethnicity. This is using the CDREC ethnicity codes (the concept field)


Ethnicity=Not Hispanic or Latino



This will hold all the basic information about the physical address. In theory, these fields will be “localized” to the region of the practicing doctor (which is why .ini files are nice because they can be extendable and still valid). The address has the following keys:
StreetAddr: The full address including the street number (like “123 Main Street”). In situations where additional lines are needed (like “Apartment 23E”), the escape character  “\n” will be used to append additional lines.
City: The city, town or village
State: The state, commonwealth, prefecture, etc. Use the normal postage prefix like “MA” for Massachusetts or “CA” for California.
PostalCode: Zip or postal code
Country: Nation or country using the ISO 3166-1 Alpha-2 code


StreetAddr=123 Main Street



Basic phone numbers. This whole section is optional. It will have the following keys:
HomePhone: Telephone number of the land line. Recommended to have area code but country code is optional. No dashes but a “+” will be used for country codes.
CellPhone:Cellphone number. Recommended to have area code but country code is optional. No dashes but a “+” will be used for country codes.





Emails can include any form including traditional email or other social networking sites (assuming they have a messaging service). This whole section is optional. The Emails group has the following keys:
Email: This is the traditional email in the format “”
Facebook: Facebook id of the patient
Instagram: Instagram username of the patient
WhatsApp: WhatsApp phone number





Everything related to work. This whole section is optional. The Work group has the following keys:
WorkAddr: Work address. As with personal address, the “\n” is used for additional lines needed
WorkCity: Work city
WorkState: State in which the work location is
WorkPhone: Phone number to contact the patient during work
WorkEmail: Email that the patient uses while at work


WorkAddr=The ACME Company\n123 Main Street


Emergency Contact

This section relates to how to get in touch with the patient’s emergency contact. The Emergency Contact group has the following keys:
EmergencyName: Full name of the emergency contact
EmergencyPhone: Phone number of the emergency contact
EmergencyRelation: The relationship with the person and the emergency contact


EmergencyName=Joe Smith



This section is what the patient has preferences for which can make their experience better. This entire section is optional. The preferences group has the following keys:
PreferredLanguage: The language the patient prefers to communicate in (in ISO 639-1 two letter code)
AvailableDays: Which type of days the patient is available for. The days of the week are abbreviated as “Su M Tu W Th F Sa”. For example, if the patient is only available on Mondays and Thursdays, the value would be “M Th”. If the patient can come in any day of the week, then you would see all “Su M Tu W Th F Sa”.
AvailableTime: Which time of day the patient prefers to come in. These are in a series of ranges which are in 24H format. For example, lets say the patient can come in anytime before noon, then it will have the value “0-12” (the zero is for midnight and 12 hours is noon time). Lets say the patient can come in anytime after 3PM. Then it would have a value of “15-23” (15 being 3PM and 23 being 11PM). Lets say the patient can only come in before 8AM but anytime after 4PM, then it would be “0-8,16-23” with the “,” to separate the ranges.
PreferredContact: How the patient likes to be contacted (appointment reminders, etc.). It can be “homephone”, “cellphone”, “email”, “text”, “workphone”, “workemail”, “facebook”, “instagram”, “whatsapp” or some other text value a human can understand.
PreferredDoctor: Which doctor the patient would like to see. If the patient likes to see Dr. Smith, then the value would be “Dr. Smith”. If the patient likes all the doctors except for Dr. Joe, it would be “-Dr. Joe” (the “-” prefix means patient does not like this particular doctor).


AvailableDays=Th F
PreferredDoctor=Dr. Willis



As with all the .ini files in this system, there will be an “others” section for any kind of additional data that was not originally in this spec. For now, it will have this one field:
SpecVersion: The version of the spec that this file follows. In theory, this should not matter as it should be backwards compatible but sometimes mistakes happen so it would be nice to have a good “get out of jail free” card.




And that’s it!

Please leave a comment on anything that should be changed or added with the specs.