varying sizes

User 870ab5b546

26-08-2014 18:19:04

Hi,


I'm having problems with generating images of approximately equal sizes. I thinkt he problem has to do with shortcut groups, but that may not be the case.


The first figure shows a single figure that should show the same size in all three, but doesn't. The differences are no shortcut groups vs. Me shortcut groups vs. Ph shortcut groups.


The second figure shows a series of different figures that have been rendered in wildly disparate sizes, even though they are all approximately the same size in a Marvin window.


Here's the code we have been using to determine the optimal size to display a figure:


    private static int[] getBestAppletSize(Molecule mol, boolean isLewis,
boolean showMapping, boolean fixedBondLength) {
final String SELF = "MolString.getBestAppletSize: ";
int[] dims = new int[] {OPT_WIDTH, OPT_WIDTH};
final int MAX_SCALE = fixedBondLength ? 30 : 40; // largest scale that looks OK
final int MIN_SCALE = 16; // smallest scale that looks OK
try {
if (mol.getDim() == 0) ChemUtils.clean2D(mol);
final MolPrinter printer = new MolPrinter(mol);
printer.setLonePairsVisible(true);
printer.setRendering(WIREFRAME_RENDERING_S);
printer.setImplicitH(isLewis ? IMPLICITH_ALL_S
: IMPLICITH_HETEROTERM_S);
printer.setScale(MAX_SCALE);
final Rectangle boundingRect = printer.getBoundingRectangle(
mol.getDocument().getAllMolecules());
// determine appropriate width
if (boundingRect.width < OPT_WIDTH || fixedBondLength) {
// use width and height at standard scale
dims[0] = boundingRect.width;
dims[1] = boundingRect.height;
} else {
final double smallerScale = ((double) (MAX_SCALE * OPT_WIDTH))
/ (double) boundingRect.width;
if (smallerScale > ((double) MIN_SCALE)) {
debugPrint(SELF + "scaling down to scale ", smallerScale);
// use optimum width
dims[0] = OPT_WIDTH;
dims[1] = (boundingRect.height * OPT_WIDTH)
/ boundingRect.width;
} else {
debugPrint(SELF + "scaling down to scale ", MIN_SCALE);
// use width that gives minimum bond length
dims[0] = (boundingRect.width * MIN_SCALE) / MAX_SCALE;
dims[1] = (boundingRect.height * MIN_SCALE) / MAX_SCALE;
} // if scale
} // if boundingRect.width
} catch (Exception e2) {
Utils.alwaysPrint(SELF + "got an exception on:\n", mol);
e2.printStackTrace();
}
return dims;
} // getBestAppletSize(Molecule, boolean, boolean, boolean)

The values of OPT_WIDTH is 250.


And here's how we use the applet dimensions to generate images:


    /** Gets the molecule's image as a string.
* @param format SVG or PNG URI
* @param molStr the MRV of a molecule
* @param qFlags flags affecting the image
* @return the molecule's image as a String
*/
private static String getImage(String format, String molStr, long qFlags) {
final String SELF = "MolString.getImage: ";
String imageData = "";
if (!Utils.isEmpty(molStr)) try {
debugPrint(SELF + "molStr:\n", molStr);
final boolean isLewis = molStr.contains("Lewis ");
final Molecule mol = MolImporter.importMol(molStr);
final int[] dims = getBestAppletSize(mol, isLewis);
final String opts =
getImageOptsString(format, dims, qFlags, isLewis);
// workaround for bug in displaying lone pairs in JChem 6.1
MDocument mDoc = mol.getDocument();
if (mDoc == null) mDoc = new MDocument(mol);
if (Question.showLonePairs(qFlags)) toBinFormat(mDoc, opts);
// generates the lone pairs for printing later
imageData = (PNG.equals(format)
? new StringBuilder().append("data:image/")
.append(PNG).append(";base64,")
.append(Base64Coder.encode(toBinFormat(mDoc, opts)))
.toString()
: Utils.bytesToString(toBinFormat(mDoc, opts))
.replaceAll("\"clipPath1\"", "\"clipPath2\""));
debugPrint(SELF + "generated image src URI with options ", opts,
"; isLewis = ", isLewis);
debugPrintMRV(SELF + "image data:\n", imageData);
} catch (MolFormatException e) {
System.out.println(SELF + "caught MolFormatException: ");
e.printStackTrace();
} // try
return imageData;
} // getImage(String, String, long)

/** Prepares a string representing options for image formation.
* @param imgType the type of image (SVG or PNG)
* @param dims dimensions of the image
* @param qFlags flags affecting the image
* @param isLewis whether the image is a LewisSketch image
* @return the options as a string
*/
private static String getImageOptsString(String imgType, int[] dims,
long qFlags, boolean isLewis) {
final StringBuilder optsBld = new StringBuilder()
.append(imgType).append(':');
if (SVG.equals(imgType)) optsBld.append("headless,");
optsBld.append('w').append(dims[0]).append(",h").append(dims[1]);
if (!isLewis && !Question.badValenceInvisible(qFlags)) {
optsBld.append(",valenceErrorVisible");
} // if should show valence errors
optsBld.append(",H_").append(
Question.showNoHydrogens(qFlags) || isLewis ? "off"
: Question.showHeteroHydrogens(qFlags) ? "hetero"
: Question.showAllHydrogens(qFlags) ? "all"
: "heteroterm")
.append(",cv_").append(Question.showAllCarbons(qFlags)
|| isLewis ? "on" : "inChain");
if (Question.showLonePairs(qFlags)) optsBld.append(",lp");
if (Question.showMapping(qFlags)) optsBld.append(",amap");
if (Question.showRSLabels(qFlags)) {
optsBld.append(",chiral_all");
} // if should show RS labels
return optsBld.toString();
} // getImageOptsString(String, int[], long, boolean)

This is longstanding code, but I noticed the problem fairly recently.


Any ideas what could be going wrong? Let me know if you need more information.

User 870ab5b546

26-08-2014 18:38:45

Here's an HTML page with many different images on it, so you can have them all in a single place.

User 870ab5b546

26-08-2014 19:25:47

And here's a case where the shortcut group's name was cut off (should show two CO2Me groups, not two CO2M groups).

ChemAxon 2c555f5717

28-08-2014 11:54:38

Dear Bob!


   I start with your last question, since it is easier: If I got it correctly, you miss the e from the CO2Me group on a saved image, but it is visible on a runtime? Could you send us the mrv version of this, since we could not reproduce it. Also: what version of Marvin did you use?


   In your first question: Do you want images, that has equal size letters / bonds  size, or images with similar pixel * pixel size? I could easily do the first one.


Regards:
Balázs 

User 870ab5b546

28-08-2014 13:12:14

Yes, the Me is perfectly visible in MarvinSketch and MarvinView, but not in the generated image. Here is the MRV. I don't know what version of Marvin the structure was originally drawn in, but I copied the MRV in Marvin 2014.8.25.0. We're using the same version to generate the PNG or SVG images.


<?xml version="1.0" encoding="UTF-8"?>
<cml xmlns="http://www.chemaxon.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.chemaxon.com/marvin/help/formats/schema/mrvSchema_14_8_4.xsd" version="ChemAxon file format v14.8.4, generated by v14.8.25.0">
<MDocument>
<MChemicalStruct>
<molecule molID="m1">
<atomArray atomID="a1 a2 a3 a4 a5 a6 a7 a8 a9 a10" elementType="C C C C C C C C R R" sgroupRef="0 0 0 0 0 0 0 0 sg1 sg2" x2="-12.133333333333335 -13.46706666666667 -13.46706666666667 -12.133333333333335 -10.799600000000002 -10.799600000000002 -6.650000000000003 -6.650000000000005 -6.650000000000003 -6.650000000000003" y2="10.173333333333336 9.403333333333334 7.863333333333335 7.093333333333334 7.863333333333335 9.403333333333334 8.026666666666664 9.566666666666665 11.106666666666662 6.486666666666663"/>
<bondArray>
<bond id="b1" atomRefs2="a1 a2" order="2"/>
<bond id="b2" atomRefs2="a1 a6" order="1"/>
<bond id="b3" atomRefs2="a2 a3" order="1"/>
<bond id="b4" atomRefs2="a3 a4" order="2"/>
<bond id="b5" atomRefs2="a4 a5" order="1"/>
<bond id="b6" atomRefs2="a5 a6" order="1"/>
<bond id="b7" atomRefs2="a8 a7" order="3"/>
<bond id="b8" atomRefs2="a8 a9" order="1"/>
<bond id="b9" atomRefs2="a7 a10" order="1"/>
</bondArray>
<molecule id="sg1" role="SuperatomSgroup" title="CO2Me" leftName="MeO2C" molID="m2">
<atomArray atomID="a11 a12 a13 a14" elementType="C O C O" attachmentPoint="1 0 0 0" sgroupAttachmentPoint="1 0 0 0" x2="-9.04749980926514 -8.27749980926514 -6.737499809265139 -10.58749980926514" y2="21.47066120202544 20.1369820801974 20.1369820801974 21.470661202025433"/>
<bondArray>
<bond id="b10" atomRefs2="a13 a12" order="1"/>
<bond id="b11" atomRefs2="a12 a11" order="1"/>
<bond id="b12" atomRefs2="a11 a14" order="2"/>
</bondArray>
<AttachmentPointArray>
<attachmentPoint atom="a11" order="1" bond="b8"/>
</AttachmentPointArray>
</molecule>
<molecule id="sg2" role="SuperatomSgroup" title="CO2Me" leftName="MeO2C" molID="m3">
<atomArray atomID="a15 a16 a17 a18" elementType="C O C O" attachmentPoint="1 0 0 0" sgroupAttachmentPoint="1 0 0 0" x2="-9.528749618530274 -8.758749618530274 -7.218749618530276 -11.068749618530273" y2="11.845660248351118 10.511981126523073 10.511981126523077 11.845660248351122"/>
<bondArray>
<bond id="b13" atomRefs2="a17 a16" order="1"/>
<bond id="b14" atomRefs2="a16 a15" order="1"/>
<bond id="b15" atomRefs2="a15 a18" order="2"/>
</bondArray>
<AttachmentPointArray>
<attachmentPoint atom="a15" order="1" bond="b9"/>
</AttachmentPointArray>
</molecule>
</molecule>
</MChemicalStruct>
</MDocument>
</cml>

In response to the first question: I want the image size to be within a certain range. The image should have bond lengths of no greater than m, and the total image size should be no greater than n. For small structures, the bond length will be the controling factor, and for large structures, the image size will be the controling factor.


Note that in the second figure I posted, the structures are all about the same size, but the image sizes vary dramatically. For example, compare the structures on the upper right and the lower right. And of course there are the examples in the first figure, where only the names of the groups change, but the total size changes significantly.

ChemAxon 2c555f5717

29-08-2014 10:37:21

Dear Bob!


   I have created an issue for this bounding problem at first sight we will have a long work with it.


Regards:
Balázs 

User 870ab5b546

22-10-2014 20:43:20

I think I know the root of the problem. If I place a shortcut group on the canvas, the hidden atoms may not be assigned coordinates, or they may be assigned coordinates that wind all over the drawing. I believe the image generator is taking these hidden atoms' coordinates into account when it is calculating the sizes of images and their boundaries. The solution is to use only superatom coordinates for contracted shortcut groups when calculating an image's size and boundaries.

ChemAxon d26931946c

27-10-2014 12:59:15

Thanks for the tip, we'll check it out.

ChemAxon f052bdfe3c

13-11-2014 09:35:40

Hi Bob,


The next release 11.17. will contain a fix which, we belive, will solve this issue. May I ask to take a look at it if you will have time?


Thanks,


Efi

User 870ab5b546

13-11-2014 13:26:03

sure, i'd be happy to do.